diff --git a/.gitmodules b/.gitmodules index 9bc2a6a70eb45..d2e1fb868a999 100644 --- a/.gitmodules +++ b/.gitmodules @@ -20,10 +20,13 @@ url = https://github.com/rust-lang/libc.git [submodule "src/doc/nomicon"] path = src/doc/nomicon - url = https://github.com/rust-lang-nursery/nomicon + url = https://github.com/rust-lang-nursery/nomicon.git [submodule "src/tools/cargo"] path = cargo - url = https://github.com/rust-lang/cargo + url = https://github.com/rust-lang/cargo.git [submodule "reference"] path = src/doc/reference url = https://github.com/rust-lang-nursery/reference.git +[submodule "book"] + path = src/doc/book + url = https://github.com/rust-lang/book diff --git a/.travis.yml b/.travis.yml index 988ef66f8fadd..ba70497ba3fd9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -48,6 +48,8 @@ matrix: RUSTC_RETRY_LINKER_ON_SEGFAULT=1 SCCACHE_ERROR_LOG=/tmp/sccache.log RUST_LOG=sccache=debug + MACOSX_DEPLOYMENT_TARGET=10.8 + MACOSX_STD_DEPLOYMENT_TARGET=10.7 os: osx osx_image: xcode8.2 install: &osx_install_sccache > @@ -60,6 +62,8 @@ matrix: RUSTC_RETRY_LINKER_ON_SEGFAULT=1 SCCACHE_ERROR_LOG=/tmp/sccache.log RUST_LOG=sccache=debug + MACOSX_DEPLOYMENT_TARGET=10.8 + MACOSX_STD_DEPLOYMENT_TARGET=10.7 os: osx osx_image: xcode8.2 install: *osx_install_sccache @@ -72,6 +76,8 @@ matrix: RUSTC_RETRY_LINKER_ON_SEGFAULT=1 SCCACHE_ERROR_LOG=/tmp/sccache.log RUST_LOG=sccache=debug + MACOSX_DEPLOYMENT_TARGET=10.8 + MACOSX_STD_DEPLOYMENT_TARGET=10.7 os: osx osx_image: xcode8.2 install: > @@ -85,6 +91,8 @@ matrix: RUSTC_RETRY_LINKER_ON_SEGFAULT=1 SCCACHE_ERROR_LOG=/tmp/sccache.log RUST_LOG=sccache=debug + MACOSX_DEPLOYMENT_TARGET=10.8 + MACOSX_STD_DEPLOYMENT_TARGET=10.7 os: osx osx_image: xcode8.2 install: *osx_install_sccache @@ -102,6 +110,8 @@ matrix: RUSTC_RETRY_LINKER_ON_SEGFAULT=1 SCCACHE_ERROR_LOG=/tmp/sccache.log RUST_LOG=sccache=debug + MACOSX_DEPLOYMENT_TARGET=10.8 + MACOSX_STD_DEPLOYMENT_TARGET=10.7 os: osx osx_image: xcode8.2 install: *osx_install_sccache diff --git a/README.md b/README.md index 79f11144a073d..dc9362ca2f0b8 100644 --- a/README.md +++ b/README.md @@ -161,8 +161,9 @@ If you’d like to build the documentation, it’s almost the same: $ ./x.py doc ``` -The generated documentation will appear in a top-level `doc` directory, -created by the `make` rule. +The generated documentation will appear under `doc` in the `build` directory for +the ABI used. I.e., if the ABI was `x86_64-pc-windows-msvc`, the directory will be +`build\x86_64-pc-windows-msvc\doc`. ## Notes diff --git a/RELEASES.md b/RELEASES.md index 606936778c49a..224bd2420a93f 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -4,7 +4,6 @@ Version 1.16.0 (2017-03-16) Language -------- -* Lifetimes in statics and consts default to `'static`. [RFC 1623] * [The compiler's `dead_code` lint now accounts for type aliases][38051]. * [Uninhabitable enums (those without any variants) no longer permit wildcard match patterns][38069] diff --git a/cargo b/cargo index 4a3c0a63b07e9..5f3b9c4c6a7be 160000 --- a/cargo +++ b/cargo @@ -1 +1 @@ -Subproject commit 4a3c0a63b07e9a4feb41cb11de37c92a09db5a60 +Subproject commit 5f3b9c4c6a7be1f177d6024cb83d150b6479148a diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 68b3623a53f25..2b3ae0ccdb822 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -285,6 +285,16 @@ pub fn docs(build: &Build, compiler: &Compiler) { continue } + // The nostarch directory in the book is for no starch, and so isn't guaranteed to build. + // we don't care if it doesn't build, so skip it. + use std::ffi::OsStr; + let path: &OsStr = p.as_ref(); + if let Some(path) = path.to_str() { + if path.contains("nostarch") { + continue; + } + } + println!("doc tests for: {}", p.display()); markdown_test(build, compiler, &p); } diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs index a66ed46fe464f..e9547ee42d077 100644 --- a/src/bootstrap/clean.rs +++ b/src/bootstrap/clean.rs @@ -22,9 +22,9 @@ use std::path::Path; use Build; pub fn clean(build: &Build) { - rm_rf(build, "tmp".as_ref()); - rm_rf(build, &build.out.join("tmp")); - rm_rf(build, &build.out.join("dist")); + rm_rf("tmp".as_ref()); + rm_rf(&build.out.join("tmp")); + rm_rf(&build.out.join("dist")); for host in build.config.host.iter() { let entries = match build.out.join(host).read_dir() { @@ -38,12 +38,12 @@ pub fn clean(build: &Build) { continue } let path = t!(entry.path().canonicalize()); - rm_rf(build, &path); + rm_rf(&path); } } } -fn rm_rf(build: &Build, path: &Path) { +fn rm_rf(path: &Path) { if !path.exists() { return } @@ -55,7 +55,7 @@ fn rm_rf(build: &Build, path: &Path) { let file = t!(file).path(); if file.is_dir() { - rm_rf(build, &file); + rm_rf(&file); } else { // On windows we can't remove a readonly file, and git will // often clone files as readonly. As a result, we have some diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 3459c1d2b8425..af1f43eb4c1ae 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -20,6 +20,7 @@ use std::collections::HashMap; use std::fs::{self, File}; use std::path::{Path, PathBuf}; use std::process::Command; +use std::env; use build_helper::{output, mtime, up_to_date}; use filetime::FileTime; @@ -44,6 +45,11 @@ pub fn std(build: &Build, target: &str, compiler: &Compiler) { build.clear_if_dirty(&out_dir, &build.compiler_path(compiler)); let mut cargo = build.cargo(compiler, Mode::Libstd, target, "build"); let mut features = build.std_features(); + + if let Ok(target) = env::var("MACOSX_STD_DEPLOYMENT_TARGET") { + cargo.env("MACOSX_DEPLOYMENT_TARGET", target); + } + // When doing a local rebuild we tell cargo that we're stage1 rather than // stage0. This works fine if the local rust and being-built rust have the // same view of what the default allocator is, but fails otherwise. Since @@ -170,6 +176,9 @@ pub fn test(build: &Build, target: &str, compiler: &Compiler) { let out_dir = build.cargo_out(compiler, Mode::Libtest, target); build.clear_if_dirty(&out_dir, &libstd_stamp(build, compiler, target)); let mut cargo = build.cargo(compiler, Mode::Libtest, target, "build"); + if let Ok(target) = env::var("MACOSX_STD_DEPLOYMENT_TARGET") { + cargo.env("MACOSX_DEPLOYMENT_TARGET", target); + } cargo.arg("--manifest-path") .arg(build.src.join("src/libtest/Cargo.toml")); build.run(&mut cargo); diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index db8ed579cecdb..baee1ada508f2 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -53,6 +53,82 @@ pub fn rustbook(build: &Build, target: &str, name: &str) { .arg(out)); } +/// Build the book and associated stuff. +/// +/// We need to build: +/// +/// * Book (first edition) +/// * Book (second edition) +/// * Index page +/// * Redirect pages +pub fn book(build: &Build, target: &str, name: &str) { + // build book first edition + rustbook(build, target, &format!("{}/first-edition", name)); + + // build book second edition + rustbook(build, target, &format!("{}/second-edition", name)); + + // build the index page + let index = format!("{}/index.md", name); + println!("Documenting book index ({})", target); + invoke_rustdoc(build, target, &index); + + // build the redirect pages + println!("Documenting book redirect pages ({})", target); + for file in t!(fs::read_dir(build.src.join("src/doc/book/redirects"))) { + let file = t!(file); + let path = file.path(); + let path = path.to_str().unwrap(); + + invoke_rustdoc(build, target, path); + } +} + +fn invoke_rustdoc(build: &Build, target: &str, markdown: &str) { + let out = build.doc_out(target); + + let compiler = Compiler::new(0, &build.config.build); + + let path = build.src.join("src/doc").join(markdown); + + let rustdoc = build.rustdoc(&compiler); + + let favicon = build.src.join("src/doc/favicon.inc"); + let footer = build.src.join("src/doc/footer.inc"); + + let version_input = build.src.join("src/doc/version_info.html.template"); + let version_info = out.join("version_info.html"); + + if !up_to_date(&version_input, &version_info) { + let mut info = String::new(); + t!(t!(File::open(&version_input)).read_to_string(&mut info)); + let info = info.replace("VERSION", &build.rust_release()) + .replace("SHORT_HASH", build.rust_info.sha_short().unwrap_or("")) + .replace("STAMP", build.rust_info.sha().unwrap_or("")); + t!(t!(File::create(&version_info)).write_all(info.as_bytes())); + } + + let mut cmd = Command::new(&rustdoc); + + build.add_rustc_lib_path(&compiler, &mut cmd); + + let out = out.join("book"); + + t!(fs::copy(build.src.join("src/doc/rust.css"), out.join("rust.css"))); + + cmd.arg("--html-after-content").arg(&footer) + .arg("--html-before-content").arg(&version_info) + .arg("--html-in-header").arg(&favicon) + .arg("--markdown-playground-url") + .arg("https://play.rust-lang.org/") + .arg("-o").arg(&out) + .arg(&path) + .arg("--markdown-css") + .arg("rust.css"); + + build.run(&mut cmd); +} + /// Generates all standalone documentation as compiled by the rustdoc in `stage` /// for the `target` into `out`. /// diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 6cc1ca8d02ed0..dea1a607255a8 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -222,9 +222,24 @@ pub fn openssl(build: &Build, target: &str) { let tarball = out.join(&name); if !tarball.exists() { let tmp = tarball.with_extension("tmp"); - build.run(Command::new("curl") - .arg("-o").arg(&tmp) - .arg(format!("https://www.openssl.org/source/{}", name))); + // originally from https://www.openssl.org/source/... + let url = format!("https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/{}", + name); + let mut ok = false; + for _ in 0..3 { + let status = Command::new("curl") + .arg("-o").arg(&tmp) + .arg(&url) + .status() + .expect("failed to spawn curl"); + if status.success() { + ok = true; + break + } + } + if !ok { + panic!("failed to download openssl source") + } let mut shasum = if target.contains("apple") { let mut cmd = Command::new("shasum"); cmd.arg("-a").arg("256"); diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index 6b047c62d99be..6eb12fed5abb2 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -581,7 +581,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { .stage(0) }) .default(build.config.docs) - .run(move |s| doc::rustbook(build, s.target, "book")); + .run(move |s| doc::book(build, s.target, "book")); rules.doc("doc-nomicon", "src/doc/nomicon") .dep(move |s| { s.name("tool-rustbook") diff --git a/src/ci/docker/dist-x86-linux/Dockerfile b/src/ci/docker/dist-x86-linux/Dockerfile index 3f6f71c41b520..282739ceebee9 100644 --- a/src/ci/docker/dist-x86-linux/Dockerfile +++ b/src/ci/docker/dist-x86-linux/Dockerfile @@ -86,4 +86,10 @@ ENV RUST_CONFIGURE_ARGS \ --enable-extended \ --enable-sanitizers ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS + +# This is the only builder which will create source tarballs ENV DIST_SRC 1 + +# When we build cargo in this container, we don't want it to use the system +# libcurl, instead it should compile its own. +ENV LIBCURL_NO_PKG_CONFIG 1 diff --git a/src/doc/book b/src/doc/book new file mode 160000 index 0000000000000..e6d6caab41471 --- /dev/null +++ b/src/doc/book @@ -0,0 +1 @@ +Subproject commit e6d6caab41471f7115a621029bd428a812c5260e diff --git a/src/doc/book/src/README.md b/src/doc/book/src/README.md deleted file mode 100644 index ade4d52c1eb31..0000000000000 --- a/src/doc/book/src/README.md +++ /dev/null @@ -1,39 +0,0 @@ -# The Rust Programming Language - -Welcome! This book will teach you about the [Rust Programming Language][rust]. -Rust is a systems programming language focused on three goals: safety, speed, -and concurrency. It maintains these goals without having a garbage collector, -making it a useful language for a number of use cases other languages aren’t -good at: embedding in other languages, programs with specific space and time -requirements, and writing low-level code, like device drivers and operating -systems. It improves on current languages targeting this space by having a -number of compile-time safety checks that produce no runtime overhead, while -eliminating all data races. Rust also aims to achieve ‘zero-cost abstractions’ -even though some of these abstractions feel like those of a high-level language. -Even then, Rust still allows precise control like a low-level language would. - -[rust]: https://www.rust-lang.org - -“The Rust Programming Language” is split into chapters. This introduction -is the first. After this: - -* [Getting started][gs] - Set up your computer for Rust development. -* [Tutorial: Guessing Game][gg] - Learn some Rust with a small project. -* [Syntax and Semantics][ss] - Each bit of Rust, broken down into small chunks. -* [Effective Rust][er] - Higher-level concepts for writing excellent Rust code. -* [Glossary][gl] - A reference of terms used in the book. -* [Bibliography][bi] - Background on Rust's influences, papers about Rust. - -[gs]: getting-started.html -[gg]: guessing-game.html -[er]: effective-rust.html -[ss]: syntax-and-semantics.html -[gl]: glossary.html -[bi]: bibliography.html - -### Contributing - -The source files from which this book is generated can be found on -[GitHub][book]. - -[book]: https://github.com/rust-lang/rust/tree/master/src/doc/book diff --git a/src/doc/book/src/SUMMARY.md b/src/doc/book/src/SUMMARY.md deleted file mode 100644 index c3763cdf9d6d7..0000000000000 --- a/src/doc/book/src/SUMMARY.md +++ /dev/null @@ -1,60 +0,0 @@ -# Summary - -[Introduction](README.md) - -* [Getting Started](getting-started.md) -* [Tutorial: Guessing Game](guessing-game.md) -* [Syntax and Semantics](syntax-and-semantics.md) - * [Variable Bindings](variable-bindings.md) - * [Functions](functions.md) - * [Primitive Types](primitive-types.md) - * [Comments](comments.md) - * [if](if.md) - * [Loops](loops.md) - * [Vectors](vectors.md) - * [Ownership](ownership.md) - * [References and Borrowing](references-and-borrowing.md) - * [Lifetimes](lifetimes.md) - * [Mutability](mutability.md) - * [Structs](structs.md) - * [Enums](enums.md) - * [Match](match.md) - * [Patterns](patterns.md) - * [Method Syntax](method-syntax.md) - * [Strings](strings.md) - * [Generics](generics.md) - * [Traits](traits.md) - * [Drop](drop.md) - * [if let](if-let.md) - * [Trait Objects](trait-objects.md) - * [Closures](closures.md) - * [Universal Function Call Syntax](ufcs.md) - * [Crates and Modules](crates-and-modules.md) - * [`const` and `static`](const-and-static.md) - * [Attributes](attributes.md) - * [`type` aliases](type-aliases.md) - * [Casting between types](casting-between-types.md) - * [Associated Types](associated-types.md) - * [Unsized Types](unsized-types.md) - * [Operators and Overloading](operators-and-overloading.md) - * [Deref coercions](deref-coercions.md) - * [Macros](macros.md) - * [Raw Pointers](raw-pointers.md) - * [`unsafe`](unsafe.md) -* [Effective Rust](effective-rust.md) - * [The Stack and the Heap](the-stack-and-the-heap.md) - * [Testing](testing.md) - * [Conditional Compilation](conditional-compilation.md) - * [Documentation](documentation.md) - * [Iterators](iterators.md) - * [Concurrency](concurrency.md) - * [Error Handling](error-handling.md) - * [Choosing your Guarantees](choosing-your-guarantees.md) - * [FFI](ffi.md) - * [Borrow and AsRef](borrow-and-asref.md) - * [Release Channels](release-channels.md) - * [Using Rust without the standard library](using-rust-without-the-standard-library.md) - * [Procedural Macros (and custom derive)](procedural-macros.md) -* [Glossary](glossary.md) -* [Syntax Index](syntax-index.md) -* [Bibliography](bibliography.md) diff --git a/src/doc/book/src/associated-types.md b/src/doc/book/src/associated-types.md deleted file mode 100644 index 4db2b9e5eec20..0000000000000 --- a/src/doc/book/src/associated-types.md +++ /dev/null @@ -1,202 +0,0 @@ -# Associated Types - -Associated types are a powerful part of Rust’s type system. They’re related to -the idea of a ‘type family’, in other words, grouping multiple types together. That -description is a bit abstract, so let’s dive right into an example. If you want -to write a `Graph` trait, you have two types to be generic over: the node type -and the edge type. So you might write a trait, `Graph<N, E>`, that looks like -this: - -```rust -trait Graph<N, E> { - fn has_edge(&self, &N, &N) -> bool; - fn edges(&self, &N) -> Vec<E>; - // Etc. -} -``` - -While this sort of works, it ends up being awkward. For example, any function -that wants to take a `Graph` as a parameter now _also_ needs to be generic over -the `N`ode and `E`dge types too: - -```rust,ignore -fn distance<N, E, G: Graph<N, E>>(graph: &G, start: &N, end: &N) -> u32 { ... } -``` - -Our distance calculation works regardless of our `Edge` type, so the `E` stuff in -this signature is a distraction. - -What we really want to say is that a certain `E`dge and `N`ode type come together -to form each kind of `Graph`. We can do that with associated types: - -```rust -trait Graph { - type N; - type E; - - fn has_edge(&self, &Self::N, &Self::N) -> bool; - fn edges(&self, &Self::N) -> Vec<Self::E>; - // Etc. -} -``` - -Now, our clients can be abstract over a given `Graph`: - -```rust,ignore -fn distance<G: Graph>(graph: &G, start: &G::N, end: &G::N) -> u32 { ... } -``` - -No need to deal with the `E`dge type here! - -Let’s go over all this in more detail. - -## Defining associated types - -Let’s build that `Graph` trait. Here’s the definition: - -```rust -trait Graph { - type N; - type E; - - fn has_edge(&self, &Self::N, &Self::N) -> bool; - fn edges(&self, &Self::N) -> Vec<Self::E>; -} -``` - -Simple enough. Associated types use the `type` keyword, and go inside the body -of the trait, with the functions. - -These type declarations work the same way as those for functions. For example, -if we wanted our `N` type to implement `Display`, so we can print the nodes out, -we could do this: - -```rust -use std::fmt; - -trait Graph { - type N: fmt::Display; - type E; - - fn has_edge(&self, &Self::N, &Self::N) -> bool; - fn edges(&self, &Self::N) -> Vec<Self::E>; -} -``` - -## Implementing associated types - -Just like any trait, traits that use associated types use the `impl` keyword to -provide implementations. Here’s a simple implementation of Graph: - -```rust -# trait Graph { -# type N; -# type E; -# fn has_edge(&self, &Self::N, &Self::N) -> bool; -# fn edges(&self, &Self::N) -> Vec<Self::E>; -# } -struct Node; - -struct Edge; - -struct MyGraph; - -impl Graph for MyGraph { - type N = Node; - type E = Edge; - - fn has_edge(&self, n1: &Node, n2: &Node) -> bool { - true - } - - fn edges(&self, n: &Node) -> Vec<Edge> { - Vec::new() - } -} -``` - -This silly implementation always returns `true` and an empty `Vec<Edge>`, but it -gives you an idea of how to implement this kind of thing. We first need three -`struct`s, one for the graph, one for the node, and one for the edge. If it made -more sense to use a different type, that would work as well, we’re going to -use `struct`s for all three here. - -Next is the `impl` line, which is an implementation like any other trait. - -From here, we use `=` to define our associated types. The name the trait uses -goes on the left of the `=`, and the concrete type we’re `impl`ementing this -for goes on the right. Finally, we use the concrete types in our function -declarations. - -## Trait objects with associated types - -There’s one more bit of syntax we should talk about: trait objects. If you -try to create a trait object from a trait with an associated type, like this: - -```rust,ignore -# trait Graph { -# type N; -# type E; -# fn has_edge(&self, &Self::N, &Self::N) -> bool; -# fn edges(&self, &Self::N) -> Vec<Self::E>; -# } -# struct Node; -# struct Edge; -# struct MyGraph; -# impl Graph for MyGraph { -# type N = Node; -# type E = Edge; -# fn has_edge(&self, n1: &Node, n2: &Node) -> bool { -# true -# } -# fn edges(&self, n: &Node) -> Vec<Edge> { -# Vec::new() -# } -# } -let graph = MyGraph; -let obj = Box::new(graph) as Box<Graph>; -``` - -You’ll get two errors: - -```text -error: the value of the associated type `E` (from the trait `main::Graph`) must -be specified [E0191] -let obj = Box::new(graph) as Box<Graph>; - ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -24:44 error: the value of the associated type `N` (from the trait -`main::Graph`) must be specified [E0191] -let obj = Box::new(graph) as Box<Graph>; - ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -``` - -We can’t create a trait object like this, because we don’t know the associated -types. Instead, we can write this: - -```rust -# trait Graph { -# type N; -# type E; -# fn has_edge(&self, &Self::N, &Self::N) -> bool; -# fn edges(&self, &Self::N) -> Vec<Self::E>; -# } -# struct Node; -# struct Edge; -# struct MyGraph; -# impl Graph for MyGraph { -# type N = Node; -# type E = Edge; -# fn has_edge(&self, n1: &Node, n2: &Node) -> bool { -# true -# } -# fn edges(&self, n: &Node) -> Vec<Edge> { -# Vec::new() -# } -# } -let graph = MyGraph; -let obj = Box::new(graph) as Box<Graph<N=Node, E=Edge>>; -``` - -The `N=Node` syntax allows us to provide a concrete type, `Node`, for the `N` -type parameter. Same with `E=Edge`. If we didn’t provide this constraint, we -couldn’t be sure which `impl` to match this trait object to. diff --git a/src/doc/book/src/attributes.md b/src/doc/book/src/attributes.md deleted file mode 100644 index 103ec39aa38a5..0000000000000 --- a/src/doc/book/src/attributes.md +++ /dev/null @@ -1,70 +0,0 @@ -# Attributes - -Declarations can be annotated with ‘attributes’ in Rust. They look like this: - -```rust -#[test] -# fn foo() {} -``` - -or like this: - -```rust -# mod foo { -#![test] -# } -``` - -The difference between the two is the `!`, which changes what the attribute -applies to: - -```rust,ignore -#[foo] -struct Foo; - -mod bar { - #![bar] -} -``` - -The `#[foo]` attribute applies to the next item, which is the `struct` -declaration. The `#![bar]` attribute applies to the item enclosing it, which is -the `mod` declaration. Otherwise, they’re the same. Both change the meaning of -the item they’re attached to somehow. - -For example, consider a function like this: - -```rust -#[test] -fn check() { - assert_eq!(2, 1 + 1); -} -``` - -It is marked with `#[test]`. This means it’s special: when you run -[tests][tests], this function will execute. When you compile as usual, it won’t -even be included. This function is now a test function. - -[tests]: testing.html - -Attributes may also have additional data: - -```rust -#[inline(always)] -fn super_fast_fn() { -# } -``` - -Or even keys and values: - -```rust -#[cfg(target_os = "macos")] -mod macos_only { -# } -``` - -Rust attributes are used for a number of different things. There is a full list -of attributes [in the reference][reference]. Currently, you are not allowed to -create your own attributes, the Rust compiler defines them. - -[reference]: ../reference/attributes.html diff --git a/src/doc/book/src/bibliography.md b/src/doc/book/src/bibliography.md deleted file mode 100644 index 07b2aa94a7746..0000000000000 --- a/src/doc/book/src/bibliography.md +++ /dev/null @@ -1,83 +0,0 @@ -# Bibliography - -This is a reading list of material relevant to Rust. It includes prior -research that has - at one time or another - influenced the design of -Rust, as well as publications about Rust. - -### Type system - -* [Region based memory management in Cyclone](http://209.68.42.137/ucsd-pages/Courses/cse227.w03/handouts/cyclone-regions.pdf) -* [Safe manual memory management in Cyclone](http://www.cs.umd.edu/projects/PL/cyclone/scp.pdf) -* [Typeclasses: making ad-hoc polymorphism less ad hoc](http://www.ps.uni-sb.de/courses/typen-ws99/class.ps.gz) -* [Macros that work together](https://www.cs.utah.edu/plt/publications/jfp12-draft-fcdf.pdf) -* [Traits: composable units of behavior](http://scg.unibe.ch/archive/papers/Scha03aTraits.pdf) -* [Alias burying](http://www.cs.uwm.edu/faculty/boyland/papers/unique-preprint.ps) - We tried something similar and abandoned it. -* [External uniqueness is unique enough](http://www.cs.uu.nl/research/techreps/UU-CS-2002-048.html) -* [Uniqueness and Reference Immutability for Safe Parallelism](https://research.microsoft.com/pubs/170528/msr-tr-2012-79.pdf) -* [Region Based Memory Management](http://www.cs.ucla.edu/~palsberg/tba/papers/tofte-talpin-iandc97.pdf) - -### Concurrency - -* [Singularity: rethinking the software stack](https://research.microsoft.com/pubs/69431/osr2007_rethinkingsoftwarestack.pdf) -* [Language support for fast and reliable message passing in singularity OS](https://research.microsoft.com/pubs/67482/singsharp.pdf) -* [Scheduling multithreaded computations by work stealing](http://supertech.csail.mit.edu/papers/steal.pdf) -* [Thread scheduling for multiprogramming multiprocessors](http://www.eecis.udel.edu/%7Ecavazos/cisc879-spring2008/papers/arora98thread.pdf) -* [The data locality of work stealing](http://www.aladdin.cs.cmu.edu/papers/pdfs/y2000/locality_spaa00.pdf) -* [Dynamic circular work stealing deque](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.170.1097&rep=rep1&type=pdf) - The Chase/Lev deque -* [Work-first and help-first scheduling policies for async-finish task parallelism](http://www.cs.rice.edu/%7Eyguo/pubs/PID824943.pdf) - More general than fully-strict work stealing -* [A Java fork/join calamity](http://www.coopsoft.com/ar/CalamityArticle.html) - critique of Java's fork/join library, particularly its application of work stealing to non-strict computation -* [Scheduling techniques for concurrent systems](http://www.stanford.edu/~ouster/cgi-bin/papers/coscheduling.pdf) -* [Contention aware scheduling](http://www.blagodurov.net/files/a8-blagodurov.pdf) -* [Balanced work stealing for time-sharing multicores](http://www.cse.ohio-state.edu/hpcs/WWW/HTML/publications/papers/TR-12-1.pdf) -* [Three layer cake for shared-memory programming](http://dl.acm.org/citation.cfm?id=1953616&dl=ACM&coll=DL&CFID=524387192&CFTOKEN=44362705) -* [Non-blocking steal-half work queues](http://www.cs.bgu.ac.il/%7Ehendlerd/papers/p280-hendler.pdf) -* [Reagents: expressing and composing fine-grained concurrency](http://www.mpi-sws.org/~turon/reagents.pdf) -* [Algorithms for scalable synchronization of shared-memory multiprocessors](https://www.cs.rochester.edu/u/scott/papers/1991_TOCS_synch.pdf) -* [Epoch-based reclamation](https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-579.pdf). - -### Others - -* [Crash-only software](https://www.usenix.org/legacy/events/hotos03/tech/full_papers/candea/candea.pdf) -* [Composing High-Performance Memory Allocators](http://people.cs.umass.edu/~emery/pubs/berger-pldi2001.pdf) -* [Reconsidering Custom Memory Allocation](http://people.cs.umass.edu/~emery/pubs/berger-oopsla2002.pdf) - -### Papers *about* Rust - -* [GPU Programming in Rust: Implementing High Level Abstractions in a -Systems Level -Language](http://www.cs.indiana.edu/~eholk/papers/hips2013.pdf). Early GPU work by Eric Holk. -* [Parallel closures: a new twist on an old - idea](https://www.usenix.org/conference/hotpar12/parallel-closures-new-twist-old-idea) - - not exactly about Rust, but by nmatsakis -* [Patina: A Formalization of the Rust Programming - Language](ftp://ftp.cs.washington.edu/tr/2015/03/UW-CSE-15-03-02.pdf). Early - formalization of a subset of the type system, by Eric Reed. -* [Experience Report: Developing the Servo Web Browser Engine using - Rust](http://arxiv.org/abs/1505.07383). By Lars Bergstrom. -* [Implementing a Generic Radix Trie in - Rust](https://michaelsproul.github.io/rust_radix_paper/rust-radix-sproul.pdf). Undergrad - paper by Michael Sproul. -* [Reenix: Implementing a Unix-Like Operating System in - Rust](http://scialex.github.io/reenix.pdf). Undergrad paper by Alex - Light. -* [Evaluation of performance and productivity metrics of potential - programming languages in the HPC environment] - (http://octarineparrot.com/assets/mrfloya-thesis-ba.pdf). - Bachelor's thesis by Florian Wilkens. Compares C, Go and Rust. -* [Nom, a byte oriented, streaming, zero copy, parser combinators library - in Rust](http://spw15.langsec.org/papers/couprie-nom.pdf). By - Geoffroy Couprie, research for VLC. -* [Graph-Based Higher-Order Intermediate - Representation](http://compilers.cs.uni-saarland.de/papers/lkh15_cgo.pdf). An - experimental IR implemented in Impala, a Rust-like language. -* [Code Refinement of Stencil - Codes](http://compilers.cs.uni-saarland.de/papers/ppl14_web.pdf). Another - paper using Impala. -* [Parallelization in Rust with fork-join and - friends](http://publications.lib.chalmers.se/records/fulltext/219016/219016.pdf). Linus - Farnstrand's master's thesis. -* [Session Types for - Rust](http://munksgaard.me/papers/laumann-munksgaard-larsen.pdf). Philip - Munksgaard's master's thesis. Research for Servo. -* [Ownership is Theft: Experiences Building an Embedded OS in Rust - Amit Levy, et. al.](http://amitlevy.com/papers/tock-plos2015.pdf) -* [You can't spell trust without Rust](https://raw.githubusercontent.com/Gankro/thesis/master/thesis.pdf). Alexis Beingessner's master's thesis. diff --git a/src/doc/book/src/borrow-and-asref.md b/src/doc/book/src/borrow-and-asref.md deleted file mode 100644 index a6e396571c685..0000000000000 --- a/src/doc/book/src/borrow-and-asref.md +++ /dev/null @@ -1,93 +0,0 @@ -# Borrow and AsRef - -The [`Borrow`][borrow] and [`AsRef`][asref] traits are very similar, but -different. Here’s a quick refresher on what these two traits mean. - -[borrow]: ../std/borrow/trait.Borrow.html -[asref]: ../std/convert/trait.AsRef.html - -# Borrow - -The `Borrow` trait is used when you’re writing a data structure, and you want to -use either an owned or borrowed type as synonymous for some purpose. - -For example, [`HashMap`][hashmap] has a [`get` method][get] which uses `Borrow`: - -```rust,ignore -fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V> - where K: Borrow<Q>, - Q: Hash + Eq -``` - -[hashmap]: ../std/collections/struct.HashMap.html -[get]: ../std/collections/struct.HashMap.html#method.get - -This signature is pretty complicated. The `K` parameter is what we’re interested -in here. It refers to a parameter of the `HashMap` itself: - -```rust,ignore -struct HashMap<K, V, S = RandomState> { -``` - -The `K` parameter is the type of _key_ the `HashMap` uses. So, looking at -the signature of `get()` again, we can use `get()` when the key implements -`Borrow<Q>`. That way, we can make a `HashMap` which uses `String` keys, -but use `&str`s when we’re searching: - -```rust -use std::collections::HashMap; - -let mut map = HashMap::new(); -map.insert("Foo".to_string(), 42); - -assert_eq!(map.get("Foo"), Some(&42)); -``` - -This is because the standard library has `impl Borrow<str> for String`. - -For most types, when you want to take an owned or borrowed type, a `&T` is -enough. But one area where `Borrow` is effective is when there’s more than one -kind of borrowed value. This is especially true of references and slices: you -can have both an `&T` or a `&mut T`. If we wanted to accept both of these types, -`Borrow` is up for it: - -```rust -use std::borrow::Borrow; -use std::fmt::Display; - -fn foo<T: Borrow<i32> + Display>(a: T) { - println!("a is borrowed: {}", a); -} - -let mut i = 5; - -foo(&i); -foo(&mut i); -``` - -This will print out `a is borrowed: 5` twice. - -# AsRef - -The `AsRef` trait is a conversion trait. It’s used for converting some value to -a reference in generic code. Like this: - -```rust -let s = "Hello".to_string(); - -fn foo<T: AsRef<str>>(s: T) { - let slice = s.as_ref(); -} -``` - -# Which should I use? - -We can see how they’re kind of the same: they both deal with owned and borrowed -versions of some type. However, they’re a bit different. - -Choose `Borrow` when you want to abstract over different kinds of borrowing, or -when you’re building a data structure that treats owned and borrowed values in -equivalent ways, such as hashing and comparison. - -Choose `AsRef` when you want to convert something to a reference directly, and -you’re writing generic code. diff --git a/src/doc/book/src/casting-between-types.md b/src/doc/book/src/casting-between-types.md deleted file mode 100644 index 26cd718475eab..0000000000000 --- a/src/doc/book/src/casting-between-types.md +++ /dev/null @@ -1,204 +0,0 @@ -# Casting Between Types - -Rust, with its focus on safety, provides two different ways of casting -different types between each other. The first, `as`, is for safe casts. -In contrast, `transmute` allows for arbitrary casting, and is one of the -most dangerous features of Rust! - -# Coercion - -Coercion between types is implicit and has no syntax of its own, but can -be spelled out with [`as`](#explicit-coercions). - -Coercion occurs in `let`, `const`, and `static` statements; in -function call arguments; in field values in struct initialization; and in a -function result. - -The most common case of coercion is removing mutability from a reference: - -* `&mut T` to `&T` - -An analogous conversion is to remove mutability from a -[raw pointer](raw-pointers.html): - -* `*mut T` to `*const T` - -References can also be coerced to raw pointers: - -* `&T` to `*const T` - -* `&mut T` to `*mut T` - -Custom coercions may be defined using [`Deref`](deref-coercions.html). - -Coercion is transitive. - -# `as` - -The `as` keyword does safe casting: - -```rust -let x: i32 = 5; - -let y = x as i64; -``` - -There are three major categories of safe cast: explicit coercions, casts -between numeric types, and pointer casts. - -Casting is not transitive: even if `e as U1 as U2` is a valid -expression, `e as U2` is not necessarily so (in fact it will only be valid if -`U1` coerces to `U2`). - - -## Explicit coercions - -A cast `e as U` is valid if `e` has type `T` and `T` *coerces* to `U`. - -## Numeric casts - -A cast `e as U` is also valid in any of the following cases: - -* `e` has type `T` and `T` and `U` are any numeric types; *numeric-cast* -* `e` is a C-like enum (with no data attached to the variants), - and `U` is an integer type; *enum-cast* -* `e` has type `bool` or `char` and `U` is an integer type; *prim-int-cast* -* `e` has type `u8` and `U` is `char`; *u8-char-cast* - -For example - -```rust -let one = true as u8; -let at_sign = 64 as char; -let two_hundred = -56i8 as u8; -``` - -The semantics of numeric casts are: - -* Casting between two integers of the same size (e.g. i32 -> u32) is a no-op -* Casting from a larger integer to a smaller integer (e.g. u32 -> u8) will - truncate -* Casting from a smaller integer to a larger integer (e.g. u8 -> u32) will - * zero-extend if the source is unsigned - * sign-extend if the source is signed -* Casting from a float to an integer will round the float towards zero - * **[NOTE: currently this will cause Undefined Behavior if the rounded - value cannot be represented by the target integer type][float-int]**. - This includes Inf and NaN. This is a bug and will be fixed. -* Casting from an integer to float will produce the floating point - representation of the integer, rounded if necessary (rounding strategy - unspecified) -* Casting from an f32 to an f64 is perfect and lossless -* Casting from an f64 to an f32 will produce the closest possible value - (rounding strategy unspecified) - * **[NOTE: currently this will cause Undefined Behavior if the value - is finite but larger or smaller than the largest or smallest finite - value representable by f32][float-float]**. This is a bug and will - be fixed. - -[float-int]: https://github.com/rust-lang/rust/issues/10184 -[float-float]: https://github.com/rust-lang/rust/issues/15536 - -## Pointer casts - -Perhaps surprisingly, it is safe to cast [raw pointers](raw-pointers.html) to and -from integers, and to cast between pointers to different types subject to -some constraints. It is only unsafe to dereference the pointer: - -```rust -let a = 300 as *const char; // `a` is a pointer to location 300. -let b = a as u32; -``` - -`e as U` is a valid pointer cast in any of the following cases: - -* `e` has type `*T`, `U` has type `*U_0`, and either `U_0: Sized` or - `unsize_kind(T) == unsize_kind(U_0)`; a *ptr-ptr-cast* - -* `e` has type `*T` and `U` is a numeric type, while `T: Sized`; *ptr-addr-cast* - -* `e` is an integer and `U` is `*U_0`, while `U_0: Sized`; *addr-ptr-cast* - -* `e` has type `&[T; n]` and `U` is `*const T`; *array-ptr-cast* - -* `e` is a function pointer type and `U` has type `*T`, - while `T: Sized`; *fptr-ptr-cast* - -* `e` is a function pointer type and `U` is an integer; *fptr-addr-cast* - - -# `transmute` - -`as` only allows safe casting, and will for example reject an attempt to -cast four bytes into a `u32`: - -```rust,ignore -let a = [0u8, 0u8, 0u8, 0u8]; - -let b = a as u32; // Four u8s makes a u32. -``` - -This errors with: - -```text -error: non-scalar cast: `[u8; 4]` as `u32` -let b = a as u32; // Four u8s makes a u32. - ^~~~~~~~ -``` - -This is a ‘non-scalar cast’ because we have multiple values here: the four -elements of the array. These kinds of casts are very dangerous, because they -make assumptions about the way that multiple underlying structures are -implemented. For this, we need something more dangerous. - -The `transmute` function is very simple, but very scary. It tells Rust to treat -a value of one type as though it were another type. It does this regardless of -the typechecking system, and completely trusts you. - -In our previous example, we know that an array of four `u8`s represents a `u32` -properly, and so we want to do the cast. Using `transmute` instead of `as`, -Rust lets us: - -```rust -use std::mem; - -fn main() { - unsafe { - let a = [0u8, 1u8, 0u8, 0u8]; - let b = mem::transmute::<[u8; 4], u32>(a); - println!("{}", b); // 256 - // Or, more concisely: - let c: u32 = mem::transmute(a); - println!("{}", c); // 256 - } -} -``` - -We have to wrap the operation in an `unsafe` block for this to compile -successfully. Technically, only the `mem::transmute` call itself needs to be in -the block, but it's nice in this case to enclose everything related, so you -know where to look. In this case, the details about `a` are also important, and -so they're in the block. You'll see code in either style, sometimes the context -is too far away, and wrapping all of the code in `unsafe` isn't a great idea. - -While `transmute` does very little checking, it will at least make sure that -the types are the same size. This errors: - -```rust,ignore -use std::mem; - -unsafe { - let a = [0u8, 0u8, 0u8, 0u8]; - - let b = mem::transmute::<[u8; 4], u64>(a); -} -``` - -with: - -```text -error: transmute called with differently sized types: [u8; 4] (32 bits) to u64 -(64 bits) -``` - -Other than that, you're on your own! diff --git a/src/doc/book/src/chapter_1.md b/src/doc/book/src/chapter_1.md deleted file mode 100644 index b743fda354692..0000000000000 --- a/src/doc/book/src/chapter_1.md +++ /dev/null @@ -1 +0,0 @@ -# Chapter 1 diff --git a/src/doc/book/src/choosing-your-guarantees.md b/src/doc/book/src/choosing-your-guarantees.md deleted file mode 100644 index 89dd09e670481..0000000000000 --- a/src/doc/book/src/choosing-your-guarantees.md +++ /dev/null @@ -1,360 +0,0 @@ -# Choosing your Guarantees - -One important feature of Rust is that it lets us control the costs and guarantees -of a program. - -There are various “wrapper type” abstractions in the Rust standard library which embody -a multitude of tradeoffs between cost, ergonomics, and guarantees. Many let one choose between -run time and compile time enforcement. This section will explain a few selected abstractions in -detail. - -Before proceeding, it is highly recommended that one reads about [ownership][ownership] and -[borrowing][borrowing] in Rust. - -[ownership]: ownership.html -[borrowing]: references-and-borrowing.html - -# Basic pointer types - -## `Box<T>` - -[`Box<T>`][box] is an “owned” pointer, or a “box”. While it can hand -out references to the contained data, it is the only owner of the data. In particular, consider -the following: - -```rust -let x = Box::new(1); -let y = x; -// `x` is no longer accessible here. -``` - -Here, the box was _moved_ into `y`. As `x` no longer owns it, the compiler will no longer allow the -programmer to use `x` after this. A box can similarly be moved _out_ of a function by returning it. - -When a box (that hasn't been moved) goes out of scope, destructors are run. These destructors take -care of deallocating the inner data. - -This is a zero-cost abstraction for dynamic allocation. If you want to allocate some memory on the -heap and safely pass around a pointer to that memory, this is ideal. Note that you will only be -allowed to share references to this by the regular borrowing rules, checked at compile time. - -[box]: ../std/boxed/struct.Box.html - -## `&T` and `&mut T` - -These are immutable and mutable references respectively. They follow the “read-write lock” -pattern, such that one may either have only one mutable reference to some data, or any number of -immutable ones, but not both. This guarantee is enforced at compile time, and has no visible cost at -runtime. In most cases these two pointer types suffice for sharing cheap references between sections -of code. - -These pointers cannot be copied in such a way that they outlive the lifetime associated with them. - -## `*const T` and `*mut T` - -These are C-like raw pointers with no lifetime or ownership attached to them. They point to -some location in memory with no other restrictions. The only guarantee that these provide is that -they cannot be dereferenced except in code marked `unsafe`. - -These are useful when building safe, low cost abstractions like `Vec<T>`, but should be avoided in -safe code. - -## `Rc<T>` - -This is the first wrapper we will cover that has a runtime cost. - -[`Rc<T>`][rc] is a reference counted pointer. In other words, this lets us have multiple "owning" -pointers to the same data, and the data will be dropped (destructors will be run) when all pointers -are out of scope. - -Internally, it contains a shared “reference count” (also called “refcount”), -which is incremented each time the `Rc` is cloned, and decremented each time one of the `Rc`s goes -out of scope. The main responsibility of `Rc<T>` is to ensure that destructors are called for shared -data. - -The internal data here is immutable, and if a cycle of references is created, the data will be -leaked. If we want data that doesn't leak when there are cycles, we need a garbage collector. - -#### Guarantees - -The main guarantee provided here is that the data will not be destroyed until all references to it -are out of scope. - -This should be used when we wish to dynamically allocate and share some data (read-only) between -various portions of your program, where it is not certain which portion will finish using the pointer -last. It's a viable alternative to `&T` when `&T` is either impossible to statically check for -correctness, or creates extremely unergonomic code where the programmer does not wish to spend the -development cost of working with. - -This pointer is _not_ thread safe, and Rust will not let it be sent or shared with other threads. -This lets one avoid the cost of atomics in situations where they are unnecessary. - -There is a sister smart pointer to this one, `Weak<T>`. This is a non-owning, but also non-borrowed, -smart pointer. It is also similar to `&T`, but it is not restricted in lifetime—a `Weak<T>` -can be held on to forever. However, it is possible that an attempt to access the inner data may fail -and return `None`, since this can outlive the owned `Rc`s. This is useful for cyclic -data structures and other things. - -#### Cost - -As far as memory goes, `Rc<T>` is a single allocation, though it will allocate two extra words (i.e. -two `usize` values) as compared to a regular `Box<T>` (for "strong" and "weak" refcounts). - -`Rc<T>` has the computational cost of incrementing/decrementing the refcount whenever it is cloned -or goes out of scope respectively. Note that a clone will not do a deep copy, rather it will simply -increment the inner reference count and return a copy of the `Rc<T>`. - -[rc]: ../std/rc/struct.Rc.html - -# Cell types - -`Cell`s provide interior mutability. In other words, they contain data which can be manipulated even -if the type cannot be obtained in a mutable form (for example, when it is behind an `&`-ptr or -`Rc<T>`). - -[The documentation for the `cell` module has a pretty good explanation for these][cell-mod]. - -These types are _generally_ found in struct fields, but they may be found elsewhere too. - -## `Cell<T>` - -[`Cell<T>`][cell] is a type that provides zero-cost interior mutability by moving data in and -out of the cell. -Since the compiler knows that all the data owned by the contained value is on the stack, there's -no worry of leaking any data behind references (or worse!) by simply replacing the data. - -It is still possible to violate your own invariants using this wrapper, so be careful when using it. -If a field is wrapped in `Cell`, it's a nice indicator that the chunk of data is mutable and may not -stay the same between the time you first read it and when you intend to use it. - -```rust -use std::cell::Cell; - -let x = Cell::new(1); -let y = &x; -let z = &x; -x.set(2); -y.set(3); -z.set(4); -println!("{}", x.get()); -``` - -Note that here we were able to mutate the same value from various immutable references. - -This has the same runtime cost as the following: - -```rust,ignore -let mut x = 1; -let y = &mut x; -let z = &mut x; -x = 2; -*y = 3; -*z = 4; -println!("{}", x); -``` - -but it has the added benefit of actually compiling successfully. - -#### Guarantees - -This relaxes the “no aliasing with mutability” restriction in places where it's -unnecessary. However, this also relaxes the guarantees that the restriction provides; so if your -invariants depend on data stored within `Cell`, you should be careful. - -This is useful for mutating primitives and other types when there is no easy way of -doing it in line with the static rules of `&` and `&mut`. - -`Cell` does not let you obtain interior references to the data, which makes it safe to freely -mutate. - -#### Cost - -There is no runtime cost to using `Cell<T>`, however if you are using it to wrap larger -structs, it might be worthwhile to instead wrap individual fields in `Cell<T>` since each write is -otherwise a full copy of the struct. - - -## `RefCell<T>` - -[`RefCell<T>`][refcell] also provides interior mutability, but doesn't move data in and out of the -cell. - -However, it has a runtime cost. `RefCell<T>` enforces the read-write lock pattern at runtime (it's -like a single-threaded mutex), unlike `&T`/`&mut T` which do so at compile time. This is done by the -`borrow()` and `borrow_mut()` functions, which modify an internal reference count and return smart -pointers which can be dereferenced immutably and mutably respectively. The refcount is restored when -the smart pointers go out of scope. With this system, we can dynamically ensure that there are never -any other borrows active when a mutable borrow is active. If the programmer attempts to make such a -borrow, the thread will panic. - -```rust -use std::cell::RefCell; - -let x = RefCell::new(vec![1,2,3,4]); -{ - println!("{:?}", *x.borrow()) -} - -{ - let mut my_ref = x.borrow_mut(); - my_ref.push(1); -} -``` - -Similar to `Cell`, this is mainly useful for situations where it's hard or impossible to satisfy the -borrow checker. Generally we know that such mutations won't happen in a nested form, but it's good -to check. - -For large, complicated programs, it becomes useful to put some things in `RefCell`s to make things -simpler. For example, a lot of the maps in the `ctxt` struct in the Rust compiler internals -are inside this wrapper. These are only modified once (during creation, which is not right after -initialization) or a couple of times in well-separated places. However, since this struct is -pervasively used everywhere, juggling mutable and immutable pointers would be hard (perhaps -impossible) and probably form a soup of `&`-ptrs which would be hard to extend. On the other hand, -the `RefCell` provides a cheap (not zero-cost) way of safely accessing these. In the future, if -someone adds some code that attempts to modify the cell when it's already borrowed, it will cause a -(usually deterministic) panic which can be traced back to the offending borrow. - -Similarly, in Servo's DOM there is a lot of mutation, most of which is local to a DOM type, but some -of which crisscrosses the DOM and modifies various things. Using `RefCell` and `Cell` to guard all -mutation lets us avoid worrying about mutability everywhere, and it simultaneously highlights the -places where mutation is _actually_ happening. - -Note that `RefCell` should be avoided if a mostly simple solution is possible with `&` pointers. - -#### Guarantees - -`RefCell` relaxes the _static_ restrictions preventing aliased mutation, and replaces them with -_dynamic_ ones. As such the guarantees have not changed. - -#### Cost - -`RefCell` does not allocate, but it contains an additional "borrow state" -indicator (one word in size) along with the data. - -At runtime each borrow causes a modification/check of the refcount. - -[cell-mod]: ../std/cell/index.html -[cell]: ../std/cell/struct.Cell.html -[refcell]: ../std/cell/struct.RefCell.html - -# Synchronous types - -Many of the types above cannot be used in a threadsafe manner. Particularly, `Rc<T>` and -`RefCell<T>`, which both use non-atomic reference counts (_atomic_ reference counts are those which -can be incremented from multiple threads without causing a data race), cannot be used this way. This -makes them cheaper to use, but we need thread safe versions of these too. They exist, in the form of -`Arc<T>` and `Mutex<T>`/`RwLock<T>` - -Note that the non-threadsafe types _cannot_ be sent between threads, and this is checked at compile -time. - -There are many useful wrappers for concurrent programming in the [sync][sync] module, but only the -major ones will be covered below. - -[sync]: ../std/sync/index.html - -## `Arc<T>` - -[`Arc<T>`][arc] is a version of `Rc<T>` that uses an atomic reference count (hence, "Arc"). -This can be sent freely between threads. - -C++'s `shared_ptr` is similar to `Arc`, however in the case of C++ the inner data is always mutable. -For semantics similar to that from C++, we should use `Arc<Mutex<T>>`, `Arc<RwLock<T>>`, or -`Arc<UnsafeCell<T>>`[^4] (`UnsafeCell<T>` is a cell type that can be used to hold any data and has -no runtime cost, but accessing it requires `unsafe` blocks). The last one should only be used if we -are certain that the usage won't cause any memory unsafety. Remember that writing to a struct is not -an atomic operation, and many functions like `vec.push()` can reallocate internally and cause unsafe -behavior, so even monotonicity may not be enough to justify `UnsafeCell`. - -[^4]: `Arc<UnsafeCell<T>>` actually won't compile since `UnsafeCell<T>` isn't `Send` or `Sync`, but we can wrap it in a type and implement `Send`/`Sync` for it manually to get `Arc<Wrapper<T>>` where `Wrapper` is `struct Wrapper<T>(UnsafeCell<T>)`. - -#### Guarantees - -Like `Rc`, this provides the (thread safe) guarantee that the destructor for the internal data will -be run when the last `Arc` goes out of scope (barring any cycles). - -#### Cost - -This has the added cost of using atomics for changing the refcount (which will happen whenever it is -cloned or goes out of scope). When sharing data from an `Arc` in a single thread, it is preferable -to share `&` pointers whenever possible. - -[arc]: ../std/sync/struct.Arc.html - -## `Mutex<T>` and `RwLock<T>` - -[`Mutex<T>`][mutex] and [`RwLock<T>`][rwlock] provide mutual-exclusion via RAII guards (guards are -objects which maintain some state, like a lock, until their destructor is called). For both of -these, the mutex is opaque until we call `lock()` on it, at which point the thread will block -until a lock can be acquired, and then a guard will be returned. This guard can be used to access -the inner data (mutably), and the lock will be released when the guard goes out of scope. - -```rust,ignore -{ - let guard = mutex.lock(); - // `guard` dereferences mutably to the inner type. - *guard += 1; -} // Lock is released when destructor runs. -``` - - -`RwLock` has the added benefit of being efficient for multiple reads. It is always safe to have -multiple readers to shared data as long as there are no writers; and `RwLock` lets readers acquire a -"read lock". Such locks can be acquired concurrently and are kept track of via a reference count. -Writers must obtain a "write lock" which can only be obtained when all readers have gone out of -scope. - -#### Guarantees - -Both of these provide safe shared mutability across threads, however they are prone to deadlocks. -Some level of additional protocol safety can be obtained via the type system. - -#### Costs - -These use internal atomic-like types to maintain the locks, which are pretty costly (they can block -all memory reads across processors till they're done). Waiting on these locks can also be slow when -there's a lot of concurrent access happening. - -[rwlock]: ../std/sync/struct.RwLock.html -[mutex]: ../std/sync/struct.Mutex.html -[sessions]: https://github.com/Munksgaard/rust-sessions - -# Composition - -A common gripe when reading Rust code is with types like `Rc<RefCell<Vec<T>>>` (or even more -complicated compositions of such types). It's not always clear what the composition does, or why the -author chose one like this (and when one should be using such a composition in one's own code) - -Usually, it's a case of composing together the guarantees that you need, without paying for stuff -that is unnecessary. - -For example, `Rc<RefCell<T>>` is one such composition. `Rc<T>` itself can't be dereferenced mutably; -because `Rc<T>` provides sharing and shared mutability can lead to unsafe behavior, so we put -`RefCell<T>` inside to get dynamically verified shared mutability. Now we have shared mutable data, -but it's shared in a way that there can only be one mutator (and no readers) or multiple readers. - -Now, we can take this a step further, and have `Rc<RefCell<Vec<T>>>` or `Rc<Vec<RefCell<T>>>`. These -are both shareable, mutable vectors, but they're not the same. - -With the former, the `RefCell<T>` is wrapping the `Vec<T>`, so the `Vec<T>` in its entirety is -mutable. At the same time, there can only be one mutable borrow of the whole `Vec` at a given time. -This means that your code cannot simultaneously work on different elements of the vector from -different `Rc` handles. However, we are able to push and pop from the `Vec<T>` at will. This is -similar to a `&mut Vec<T>` with the borrow checking done at runtime. - -With the latter, the borrowing is of individual elements, but the overall vector is immutable. Thus, -we can independently borrow separate elements, but we cannot push or pop from the vector. This is -similar to a `&mut [T]`[^3], but, again, the borrow checking is at runtime. - -In concurrent programs, we have a similar situation with `Arc<Mutex<T>>`, which provides shared -mutability and ownership. - -When reading code that uses these, go in step by step and look at the guarantees/costs provided. - -When choosing a composed type, we must do the reverse; figure out which guarantees we want, and at -which point of the composition we need them. For example, if there is a choice between -`Vec<RefCell<T>>` and `RefCell<Vec<T>>`, we should figure out the tradeoffs as done above and pick -one. - -[^3]: `&[T]` and `&mut [T]` are _slices_; they consist of a pointer and a length and can refer to a portion of a vector or array. `&mut [T]` can have its elements mutated, however its length cannot be touched. diff --git a/src/doc/book/src/closures.md b/src/doc/book/src/closures.md deleted file mode 100644 index 5426ed0ff4c9c..0000000000000 --- a/src/doc/book/src/closures.md +++ /dev/null @@ -1,552 +0,0 @@ -# Closures - -Sometimes it is useful to wrap up a function and _free variables_ for better -clarity and reuse. The free variables that can be used come from the -enclosing scope and are ‘closed over’ when used in the function. From this, we -get the name ‘closures’ and Rust provides a really great implementation of -them, as we’ll see. - -# Syntax - -Closures look like this: - -```rust -let plus_one = |x: i32| x + 1; - -assert_eq!(2, plus_one(1)); -``` - -We create a binding, `plus_one`, and assign it to a closure. The closure’s -arguments go between the pipes (`|`), and the body is an expression, in this -case, `x + 1`. Remember that `{ }` is an expression, so we can have multi-line -closures too: - -```rust -let plus_two = |x| { - let mut result: i32 = x; - - result += 1; - result += 1; - - result -}; - -assert_eq!(4, plus_two(2)); -``` - -You’ll notice a few things about closures that are a bit different from regular -named functions defined with `fn`. The first is that we did not need to -annotate the types of arguments the closure takes or the values it returns. We -can: - -```rust -let plus_one = |x: i32| -> i32 { x + 1 }; - -assert_eq!(2, plus_one(1)); -``` - -But we don’t have to. Why is this? Basically, it was chosen for ergonomic -reasons. While specifying the full type for named functions is helpful with -things like documentation and type inference, the full type signatures of -closures are rarely documented since they’re anonymous, and they don’t cause -the kinds of error-at-a-distance problems that inferring named function types -can. - -The second is that the syntax is similar, but a bit different. I’ve added -spaces here for easier comparison: - -```rust -fn plus_one_v1 (x: i32) -> i32 { x + 1 } -let plus_one_v2 = |x: i32| -> i32 { x + 1 }; -let plus_one_v3 = |x: i32| x + 1 ; -``` - -Small differences, but they’re similar. - -# Closures and their environment - -The environment for a closure can include bindings from its enclosing scope in -addition to parameters and local bindings. It looks like this: - -```rust -let num = 5; -let plus_num = |x: i32| x + num; - -assert_eq!(10, plus_num(5)); -``` - -This closure, `plus_num`, refers to a `let` binding in its scope: `num`. More -specifically, it borrows the binding. If we do something that would conflict -with that binding, we get an error. Like this one: - -```rust,ignore -let mut num = 5; -let plus_num = |x: i32| x + num; - -let y = &mut num; -``` - -Which errors with: - -```text -error: cannot borrow `num` as mutable because it is also borrowed as immutable - let y = &mut num; - ^~~ -note: previous borrow of `num` occurs here due to use in closure; the immutable - borrow prevents subsequent moves or mutable borrows of `num` until the borrow - ends - let plus_num = |x| x + num; - ^~~~~~~~~~~ -note: previous borrow ends here -fn main() { - let mut num = 5; - let plus_num = |x| x + num; - - let y = &mut num; -} -^ -``` - -A verbose yet helpful error message! As it says, we can’t take a mutable borrow -on `num` because the closure is already borrowing it. If we let the closure go -out of scope, we can: - -```rust -let mut num = 5; -{ - let plus_num = |x: i32| x + num; - -} // `plus_num` goes out of scope; borrow of `num` ends. - -let y = &mut num; -``` - -If your closure requires it, however, Rust will take ownership and move -the environment instead. This doesn’t work: - -```rust,ignore -let nums = vec![1, 2, 3]; - -let takes_nums = || nums; - -println!("{:?}", nums); -``` - -We get this error: - -```text -note: `nums` moved into closure environment here because it has type - `[closure(()) -> collections::vec::Vec<i32>]`, which is non-copyable -let takes_nums = || nums; - ^~~~~~~ -``` - -`Vec<T>` has ownership over its contents, and therefore, when we refer to it -in our closure, we have to take ownership of `nums`. It’s the same as if we’d -passed `nums` to a function that took ownership of it. - -## `move` closures - -We can force our closure to take ownership of its environment with the `move` -keyword: - -```rust -let num = 5; - -let owns_num = move |x: i32| x + num; -``` - -Now, even though the keyword is `move`, the variables follow normal move semantics. -In this case, `5` implements `Copy`, and so `owns_num` takes ownership of a copy -of `num`. So what’s the difference? - -```rust -let mut num = 5; - -{ - let mut add_num = |x: i32| num += x; - - add_num(5); -} - -assert_eq!(10, num); -``` - -So in this case, our closure took a mutable reference to `num`, and then when -we called `add_num`, it mutated the underlying value, as we’d expect. We also -needed to declare `add_num` as `mut` too, because we’re mutating its -environment. - -If we change to a `move` closure, it’s different: - -```rust -let mut num = 5; - -{ - let mut add_num = move |x: i32| num += x; - - add_num(5); -} - -assert_eq!(5, num); -``` - -We only get `5`. Rather than taking a mutable borrow out on our `num`, we took -ownership of a copy. - -Another way to think about `move` closures: they give a closure its own stack -frame. Without `move`, a closure may be tied to the stack frame that created -it, while a `move` closure is self-contained. This means that you cannot -generally return a non-`move` closure from a function, for example. - -But before we talk about taking and returning closures, we should talk some -more about the way that closures are implemented. As a systems language, Rust -gives you tons of control over what your code does, and closures are no -different. - -# Closure implementation - -Rust’s implementation of closures is a bit different than other languages. They -are effectively syntax sugar for traits. You’ll want to make sure to have read -the [traits][traits] section before this one, as well as the section on [trait -objects][trait-objects]. - -[traits]: traits.html -[trait-objects]: trait-objects.html - -Got all that? Good. - -The key to understanding how closures work under the hood is something a bit -strange: Using `()` to call a function, like `foo()`, is an overloadable -operator. From this, everything else clicks into place. In Rust, we use the -trait system to overload operators. Calling functions is no different. We have -three separate traits to overload with: - -```rust -# #![feature(unboxed_closures)] -# mod foo { -pub trait Fn<Args> : FnMut<Args> { - extern "rust-call" fn call(&self, args: Args) -> Self::Output; -} - -pub trait FnMut<Args> : FnOnce<Args> { - extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; -} - -pub trait FnOnce<Args> { - type Output; - - extern "rust-call" fn call_once(self, args: Args) -> Self::Output; -} -# } -``` - -You’ll notice a few differences between these traits, but a big one is `self`: -`Fn` takes `&self`, `FnMut` takes `&mut self`, and `FnOnce` takes `self`. This -covers all three kinds of `self` via the usual method call syntax. But we’ve -split them up into three traits, rather than having a single one. This gives us -a large amount of control over what kind of closures we can take. - -The `|| {}` syntax for closures is sugar for these three traits. Rust will -generate a struct for the environment, `impl` the appropriate trait, and then -use it. - -# Taking closures as arguments - -Now that we know that closures are traits, we already know how to accept and -return closures: the same as any other trait! - -This also means that we can choose static vs dynamic dispatch as well. First, -let’s write a function which takes something callable, calls it, and returns -the result: - -```rust -fn call_with_one<F>(some_closure: F) -> i32 - where F: Fn(i32) -> i32 { - - some_closure(1) -} - -let answer = call_with_one(|x| x + 2); - -assert_eq!(3, answer); -``` - -We pass our closure, `|x| x + 2`, to `call_with_one`. It does what it -suggests: it calls the closure, giving it `1` as an argument. - -Let’s examine the signature of `call_with_one` in more depth: - -```rust -fn call_with_one<F>(some_closure: F) -> i32 -# where F: Fn(i32) -> i32 { -# some_closure(1) } -``` - -We take one parameter, and it has the type `F`. We also return an `i32`. This part -isn’t interesting. The next part is: - -```rust -# fn call_with_one<F>(some_closure: F) -> i32 - where F: Fn(i32) -> i32 { -# some_closure(1) } -``` - -Because `Fn` is a trait, we can use it as a bound for our generic type. In -this case, our closure takes an `i32` as an argument and returns an `i32`, and -so the generic bound we use is `Fn(i32) -> i32`. - -There’s one other key point here: because we’re bounding a generic with a -trait, this will get monomorphized, and therefore, we’ll be doing static -dispatch into the closure. That’s pretty neat. In many languages, closures are -inherently heap allocated, and will always involve dynamic dispatch. In Rust, -we can stack allocate our closure environment, and statically dispatch the -call. This happens quite often with iterators and their adapters, which often -take closures as arguments. - -Of course, if we want dynamic dispatch, we can get that too. A trait object -handles this case, as usual: - -```rust -fn call_with_one(some_closure: &Fn(i32) -> i32) -> i32 { - some_closure(1) -} - -let answer = call_with_one(&|x| x + 2); - -assert_eq!(3, answer); -``` - -Now we take a trait object, a `&Fn`. And we have to make a reference -to our closure when we pass it to `call_with_one`, so we use `&||`. - -A quick note about closures that use explicit lifetimes. Sometimes you might have a closure -that takes a reference like so: - -```rust -fn call_with_ref<F>(some_closure:F) -> i32 - where F: Fn(&i32) -> i32 { - - let value = 0; - some_closure(&value) -} -``` - -Normally you can specify the lifetime of the parameter to our closure. We -could annotate it on the function declaration: - -```rust,ignore -fn call_with_ref<'a, F>(some_closure:F) -> i32 - where F: Fn(&'a i32) -> i32 { -``` - -However, this presents a problem in our case. When a function has an explicit -lifetime parameter, that lifetime must be at least as long as the *entire* -call to that function. The borrow checker will complain that `value` doesn't -live long enough, because it is only in scope after its declaration inside the -function body. - -What we need is a closure that can borrow its argument only for its own -invocation scope, not for the outer function's scope. In order to say that, -we can use Higher-Ranked Trait Bounds with the `for<...>` syntax: - -```ignore -fn call_with_ref<F>(some_closure:F) -> i32 - where F: for<'a> Fn(&'a i32) -> i32 { -``` - -This lets the Rust compiler find the minimum lifetime to invoke our closure and -satisfy the borrow checker's rules. Our function then compiles and executes as we -expect. - -```rust -fn call_with_ref<F>(some_closure:F) -> i32 - where F: for<'a> Fn(&'a i32) -> i32 { - - let value = 0; - some_closure(&value) -} -``` - -# Function pointers and closures - -A function pointer is kind of like a closure that has no environment. As such, -you can pass a function pointer to any function expecting a closure argument, -and it will work: - -```rust -fn call_with_one(some_closure: &Fn(i32) -> i32) -> i32 { - some_closure(1) -} - -fn add_one(i: i32) -> i32 { - i + 1 -} - -let f = add_one; - -let answer = call_with_one(&f); - -assert_eq!(2, answer); -``` - -In this example, we don’t strictly need the intermediate variable `f`, -the name of the function works just fine too: - -```rust,ignore -let answer = call_with_one(&add_one); -``` - -# Returning closures - -It’s very common for functional-style code to return closures in various -situations. If you try to return a closure, you may run into an error. At -first, it may seem strange, but we’ll figure it out. Here’s how you’d probably -try to return a closure from a function: - -```rust,ignore -fn factory() -> (Fn(i32) -> i32) { - let num = 5; - - |x| x + num -} - -let f = factory(); - -let answer = f(1); -assert_eq!(6, answer); -``` - -This gives us these long, related errors: - -```text -error: the trait bound `core::ops::Fn(i32) -> i32 : core::marker::Sized` is not satisfied [E0277] -fn factory() -> (Fn(i32) -> i32) { - ^~~~~~~~~~~~~~~~ -note: `core::ops::Fn(i32) -> i32` does not have a constant size known at compile-time -fn factory() -> (Fn(i32) -> i32) { - ^~~~~~~~~~~~~~~~ -error: the trait bound `core::ops::Fn(i32) -> i32 : core::marker::Sized` is not satisfied [E0277] -let f = factory(); - ^ -note: `core::ops::Fn(i32) -> i32` does not have a constant size known at compile-time -let f = factory(); - ^ -``` - -In order to return something from a function, Rust needs to know what -size the return type is. But since `Fn` is a trait, it could be various -things of various sizes: many different types can implement `Fn`. An easy -way to give something a size is to take a reference to it, as references -have a known size. So we’d write this: - -```rust,ignore -fn factory() -> &(Fn(i32) -> i32) { - let num = 5; - - |x| x + num -} - -let f = factory(); - -let answer = f(1); -assert_eq!(6, answer); -``` - -But we get another error: - -```text -error: missing lifetime specifier [E0106] -fn factory() -> &(Fn(i32) -> i32) { - ^~~~~~~~~~~~~~~~~ -``` - -Right. Because we have a reference, we need to give it a lifetime. But -our `factory()` function takes no arguments, so -[elision](lifetimes.html#lifetime-elision) doesn’t kick in here. Then what -choices do we have? Try `'static`: - -```rust,ignore -fn factory() -> &'static (Fn(i32) -> i32) { - let num = 5; - - |x| x + num -} - -let f = factory(); - -let answer = f(1); -assert_eq!(6, answer); -``` - -But we get another error: - -```text -error: mismatched types: - expected `&'static core::ops::Fn(i32) -> i32`, - found `[closure@<anon>:7:9: 7:20]` -(expected &-ptr, - found closure) [E0308] - |x| x + num - ^~~~~~~~~~~ - -``` - -This error is letting us know that we don’t have a `&'static Fn(i32) -> i32`, -we have a `[closure@<anon>:7:9: 7:20]`. Wait, what? - -Because each closure generates its own environment `struct` and implementation -of `Fn` and friends, these types are anonymous. They exist solely for -this closure. So Rust shows them as `closure@<anon>`, rather than some -autogenerated name. - -The error also points out that the return type is expected to be a reference, -but what we are trying to return is not. Further, we cannot directly assign a -`'static` lifetime to an object. So we'll take a different approach and return -a ‘trait object’ by `Box`ing up the `Fn`. This _almost_ works: - -```rust,ignore -fn factory() -> Box<Fn(i32) -> i32> { - let num = 5; - - Box::new(|x| x + num) -} - -let f = factory(); - -let answer = f(1); -assert_eq!(6, answer); -``` - -There’s just one last problem: - -```text -error: closure may outlive the current function, but it borrows `num`, -which is owned by the current function [E0373] -Box::new(|x| x + num) - ^~~~~~~~~~~ -``` - -Well, as we discussed before, closures borrow their environment. And in this -case, our environment is based on a stack-allocated `5`, the `num` variable -binding. So the borrow has a lifetime of the stack frame. So if we returned -this closure, the function call would be over, the stack frame would go away, -and our closure is capturing an environment of garbage memory! With one last -fix, we can make this work: - -```rust -fn factory() -> Box<Fn(i32) -> i32> { - let num = 5; - - Box::new(move |x| x + num) -} - -let f = factory(); - -let answer = f(1); -assert_eq!(6, answer); -``` - -By making the inner closure a `move Fn`, we create a new stack frame for our -closure. By `Box`ing it up, we’ve given it a known size, allowing it to -escape our stack frame. diff --git a/src/doc/book/src/comments.md b/src/doc/book/src/comments.md deleted file mode 100644 index 0e68ab218e843..0000000000000 --- a/src/doc/book/src/comments.md +++ /dev/null @@ -1,59 +0,0 @@ -# Comments - -Now that we have some functions, it’s a good idea to learn about comments. -Comments are notes that you leave to other programmers to help explain things -about your code. The compiler mostly ignores them. - -Rust has two kinds of comments that you should care about: *line comments* -and *doc comments*. - -```rust -// Line comments are anything after ‘//’ and extend to the end of the line. - -let x = 5; // This is also a line comment. - -// If you have a long explanation for something, you can put line comments next -// to each other. Put a space between the // and your comment so that it’s -// more readable. -``` - -The other kind of comment is a doc comment. Doc comments use `///` instead of -`//`, and support Markdown notation inside: - -```rust -/// Adds one to the number given. -/// -/// # Examples -/// -/// ``` -/// let five = 5; -/// -/// assert_eq!(6, add_one(5)); -/// # fn add_one(x: i32) -> i32 { -/// # x + 1 -/// # } -/// ``` -fn add_one(x: i32) -> i32 { - x + 1 -} -``` - -There is another style of doc comment, `//!`, to comment containing items (e.g. -crates, modules or functions), instead of the items following it. Commonly used -inside crates root (lib.rs) or modules root (mod.rs): - -``` -//! # The Rust Standard Library -//! -//! The Rust Standard Library provides the essential runtime -//! functionality for building portable Rust software. -``` - -When writing doc comments, providing some examples of usage is very, very -helpful. You’ll notice we’ve used a new macro here: `assert_eq!`. This compares -two values, and `panic!`s if they’re not equal to each other. It’s very helpful -in documentation. There’s another macro, `assert!`, which `panic!`s if the -value passed to it is `false`. - -You can use the [`rustdoc`](documentation.html) tool to generate HTML documentation -from these doc comments, and also to run the code examples as tests! diff --git a/src/doc/book/src/compiler-plugins.md b/src/doc/book/src/compiler-plugins.md deleted file mode 100644 index c05d808a94740..0000000000000 --- a/src/doc/book/src/compiler-plugins.md +++ /dev/null @@ -1,253 +0,0 @@ -# Compiler Plugins - -## Introduction - -`rustc` can load compiler plugins, which are user-provided libraries that -extend the compiler's behavior with new syntax extensions, lint checks, etc. - -A plugin is a dynamic library crate with a designated *registrar* function that -registers extensions with `rustc`. Other crates can load these extensions using -the crate attribute `#![plugin(...)]`. See the -`rustc_plugin` documentation for more about the -mechanics of defining and loading a plugin. - -If present, arguments passed as `#![plugin(foo(... args ...))]` are not -interpreted by rustc itself. They are provided to the plugin through the -`Registry`'s `args` method. - -In the vast majority of cases, a plugin should *only* be used through -`#![plugin]` and not through an `extern crate` item. Linking a plugin would -pull in all of libsyntax and librustc as dependencies of your crate. This is -generally unwanted unless you are building another plugin. The -`plugin_as_library` lint checks these guidelines. - -The usual practice is to put compiler plugins in their own crate, separate from -any `macro_rules!` macros or ordinary Rust code meant to be used by consumers -of a library. - -# Syntax extensions - -Plugins can extend Rust's syntax in various ways. One kind of syntax extension -is the procedural macro. These are invoked the same way as [ordinary -macros](macros.html), but the expansion is performed by arbitrary Rust -code that manipulates syntax trees at -compile time. - -Let's write a plugin -[`roman_numerals.rs`](https://github.com/rust-lang/rust/blob/master/src/test/run-pass-fulldeps/auxiliary/roman_numerals.rs) -that implements Roman numeral integer literals. - -```rust,ignore -#![crate_type="dylib"] -#![feature(plugin_registrar, rustc_private)] - -extern crate syntax; -extern crate rustc; -extern crate rustc_plugin; - -use syntax::parse::token; -use syntax::tokenstream::TokenTree; -use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}; -use syntax::ext::build::AstBuilder; // A trait for expr_usize. -use syntax::ext::quote::rt::Span; -use rustc_plugin::Registry; - -fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) - -> Box<MacResult + 'static> { - - static NUMERALS: &'static [(&'static str, usize)] = &[ - ("M", 1000), ("CM", 900), ("D", 500), ("CD", 400), - ("C", 100), ("XC", 90), ("L", 50), ("XL", 40), - ("X", 10), ("IX", 9), ("V", 5), ("IV", 4), - ("I", 1)]; - - if args.len() != 1 { - cx.span_err( - sp, - &format!("argument should be a single identifier, but got {} arguments", args.len())); - return DummyResult::any(sp); - } - - let text = match args[0] { - TokenTree::Token(_, token::Ident(s)) => s.to_string(), - _ => { - cx.span_err(sp, "argument should be a single identifier"); - return DummyResult::any(sp); - } - }; - - let mut text = &*text; - let mut total = 0; - while !text.is_empty() { - match NUMERALS.iter().find(|&&(rn, _)| text.starts_with(rn)) { - Some(&(rn, val)) => { - total += val; - text = &text[rn.len()..]; - } - None => { - cx.span_err(sp, "invalid Roman numeral"); - return DummyResult::any(sp); - } - } - } - - MacEager::expr(cx.expr_usize(sp, total)) -} - -#[plugin_registrar] -pub fn plugin_registrar(reg: &mut Registry) { - reg.register_macro("rn", expand_rn); -} -``` - -Then we can use `rn!()` like any other macro: - -```rust,ignore -#![feature(plugin)] -#![plugin(roman_numerals)] - -fn main() { - assert_eq!(rn!(MMXV), 2015); -} -``` - -The advantages over a simple `fn(&str) -> u32` are: - -* The (arbitrarily complex) conversion is done at compile time. -* Input validation is also performed at compile time. -* It can be extended to allow use in patterns, which effectively gives - a way to define new literal syntax for any data type. - -In addition to procedural macros, you can define new -[`derive`](../reference/attributes.html#derive)-like attributes and other kinds of -extensions. See `Registry::register_syntax_extension` and the `SyntaxExtension` -enum. For a more involved macro example, see -[`regex_macros`](https://github.com/rust-lang/regex/blob/master/regex_macros/src/lib.rs). - - -## Tips and tricks - -Some of the [macro debugging tips](macros.html#debugging-macro-code) are applicable. - -You can use `syntax::parse` to turn token trees into -higher-level syntax elements like expressions: - -```rust,ignore -fn expand_foo(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) - -> Box<MacResult+'static> { - - let mut parser = cx.new_parser_from_tts(args); - - let expr: P<Expr> = parser.parse_expr(); -``` - -Looking through [`libsyntax` parser -code](https://github.com/rust-lang/rust/blob/master/src/libsyntax/parse/parser.rs) -will give you a feel for how the parsing infrastructure works. - -Keep the `Span`s of everything you parse, for better error reporting. You can -wrap `Spanned` around your custom data structures. - -Calling `ExtCtxt::span_fatal` will immediately abort compilation. It's better to -instead call `ExtCtxt::span_err` and return `DummyResult` so that the compiler -can continue and find further errors. - -To print syntax fragments for debugging, you can use `span_note` together with -`syntax::print::pprust::*_to_string`. - -The example above produced an integer literal using `AstBuilder::expr_usize`. -As an alternative to the `AstBuilder` trait, `libsyntax` provides a set of -quasiquote macros. They are undocumented and very rough around the edges. -However, the implementation may be a good starting point for an improved -quasiquote as an ordinary plugin library. - - -# Lint plugins - -Plugins can extend [Rust's lint -infrastructure](../reference/attributes.html#lint-check-attributes) with -additional checks for code style, safety, etc. Now let's write a plugin -[`lint_plugin_test.rs`](https://github.com/rust-lang/rust/blob/master/src/test/run-pass-fulldeps/auxiliary/lint_plugin_test.rs) -that warns about any item named `lintme`. - -```rust,ignore -#![feature(plugin_registrar)] -#![feature(box_syntax, rustc_private)] - -extern crate syntax; - -// Load rustc as a plugin to get macros -#[macro_use] -extern crate rustc; -extern crate rustc_plugin; - -use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass, - EarlyLintPassObject, LintArray}; -use rustc_plugin::Registry; -use syntax::ast; - -declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); - -struct Pass; - -impl LintPass for Pass { - fn get_lints(&self) -> LintArray { - lint_array!(TEST_LINT) - } -} - -impl EarlyLintPass for Pass { - fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) { - if it.ident.name.as_str() == "lintme" { - cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'"); - } - } -} - -#[plugin_registrar] -pub fn plugin_registrar(reg: &mut Registry) { - reg.register_early_lint_pass(box Pass as EarlyLintPassObject); -} -``` - -Then code like - -```rust,ignore -#![plugin(lint_plugin_test)] - -fn lintme() { } -``` - -will produce a compiler warning: - -```txt -foo.rs:4:1: 4:16 warning: item is named 'lintme', #[warn(test_lint)] on by default -foo.rs:4 fn lintme() { } - ^~~~~~~~~~~~~~~ -``` - -The components of a lint plugin are: - -* one or more `declare_lint!` invocations, which define static `Lint` structs; - -* a struct holding any state needed by the lint pass (here, none); - -* a `LintPass` - implementation defining how to check each syntax element. A single - `LintPass` may call `span_lint` for several different `Lint`s, but should - register them all through the `get_lints` method. - -Lint passes are syntax traversals, but they run at a late stage of compilation -where type information is available. `rustc`'s [built-in -lints](https://github.com/rust-lang/rust/blob/master/src/librustc/lint/builtin.rs) -mostly use the same infrastructure as lint plugins, and provide examples of how -to access type information. - -Lints defined by plugins are controlled by the usual [attributes and compiler -flags](../reference/attributes.html#lint-check-attributes), e.g. -`#[allow(test_lint)]` or `-A test-lint`. These identifiers are derived from the -first argument to `declare_lint!`, with appropriate case and punctuation -conversion. - -You can run `rustc -W help foo.rs` to see a list of lints known to `rustc`, -including those provided by plugins loaded by `foo.rs`. diff --git a/src/doc/book/src/concurrency.md b/src/doc/book/src/concurrency.md deleted file mode 100644 index afed379fe471a..0000000000000 --- a/src/doc/book/src/concurrency.md +++ /dev/null @@ -1,465 +0,0 @@ -# Concurrency - -Concurrency and parallelism are incredibly important topics in computer -science, and are also a hot topic in industry today. Computers are gaining more -and more cores, yet many programmers aren't prepared to fully utilize them. - -Rust's memory safety features also apply to its concurrency story. Even -concurrent Rust programs must be memory safe, having no data races. Rust's type -system is up to the task, and gives you powerful ways to reason about -concurrent code at compile time. - -Before we talk about the concurrency features that come with Rust, it's important -to understand something: Rust is low-level enough that the vast majority of -this is provided by the standard library, not by the language. This means that -if you don't like some aspect of the way Rust handles concurrency, you can -implement an alternative way of doing things. -[mio](https://github.com/carllerche/mio) is a real-world example of this -principle in action. - -## Background: `Send` and `Sync` - -Concurrency is difficult to reason about. In Rust, we have a strong, static -type system to help us reason about our code. As such, Rust gives us two traits -to help us make sense of code that can possibly be concurrent. - -### `Send` - -The first trait we're going to talk about is -[`Send`](../std/marker/trait.Send.html). When a type `T` implements `Send`, it -indicates that something of this type is able to have ownership transferred -safely between threads. - -This is important to enforce certain restrictions. For example, if we have a -channel connecting two threads, we would want to be able to send some data -down the channel and to the other thread. Therefore, we'd ensure that `Send` was -implemented for that type. - -In the opposite way, if we were wrapping a library with [FFI][ffi] that isn't -thread-safe, we wouldn't want to implement `Send`, and so the compiler will help -us enforce that it can't leave the current thread. - -[ffi]: ffi.html - -### `Sync` - -The second of these traits is called [`Sync`](../std/marker/trait.Sync.html). -When a type `T` implements `Sync`, it indicates that something -of this type has no possibility of introducing memory unsafety when used from -multiple threads concurrently through shared references. This implies that -types which don't have [interior mutability](mutability.html) are inherently -`Sync`, which includes simple primitive types (like `u8`) and aggregate types -containing them. - -For sharing references across threads, Rust provides a wrapper type called -`Arc<T>`. `Arc<T>` implements `Send` and `Sync` if and only if `T` implements -both `Send` and `Sync`. For example, an object of type `Arc<RefCell<U>>` cannot -be transferred across threads because -[`RefCell`](choosing-your-guarantees.html#refcellt) does not implement -`Sync`, consequently `Arc<RefCell<U>>` would not implement `Send`. - -These two traits allow you to use the type system to make strong guarantees -about the properties of your code under concurrency. Before we demonstrate -why, we need to learn how to create a concurrent Rust program in the first -place! - -## Threads - -Rust's standard library provides a library for threads, which allow you to -run Rust code in parallel. Here's a basic example of using `std::thread`: - -```rust -use std::thread; - -fn main() { - thread::spawn(|| { - println!("Hello from a thread!"); - }); -} -``` - -The `thread::spawn()` method accepts a [closure](closures.html), which is executed in a -new thread. It returns a handle to the thread, that can be used to -wait for the child thread to finish and extract its result: - -```rust -use std::thread; - -fn main() { - let handle = thread::spawn(|| { - "Hello from a thread!" - }); - - println!("{}", handle.join().unwrap()); -} -``` - -As closures can capture variables from their environment, we can also try to -bring some data into the other thread: - -```rust,ignore -use std::thread; - -fn main() { - let x = 1; - thread::spawn(|| { - println!("x is {}", x); - }); -} -``` - -However, this gives us an error: - -```text -5:19: 7:6 error: closure may outlive the current function, but it - borrows `x`, which is owned by the current function -... -5:19: 7:6 help: to force the closure to take ownership of `x` (and any other referenced variables), - use the `move` keyword, as shown: - thread::spawn(move || { - println!("x is {}", x); - }); -``` - -This is because by default closures capture variables by reference, and thus the -closure only captures a _reference to `x`_. This is a problem, because the -thread may outlive the scope of `x`, leading to a dangling pointer. - -To fix this, we use a `move` closure as mentioned in the error message. `move` -closures are explained in depth [here](closures.html#move-closures); basically -they move variables from their environment into themselves. - -```rust -use std::thread; - -fn main() { - let x = 1; - thread::spawn(move || { - println!("x is {}", x); - }); -} -``` - -Many languages have the ability to execute threads, but it's wildly unsafe. -There are entire books about how to prevent errors that occur from shared -mutable state. Rust helps out with its type system here as well, by preventing -data races at compile time. Let's talk about how you actually share things -between threads. - -## Safe Shared Mutable State - -Due to Rust's type system, we have a concept that sounds like a lie: "safe -shared mutable state." Many programmers agree that shared mutable state is -very, very bad. - -Someone once said this: - -> Shared mutable state is the root of all evil. Most languages attempt to deal -> with this problem through the 'mutable' part, but Rust deals with it by -> solving the 'shared' part. - -The same [ownership system](ownership.html) that helps prevent using pointers -incorrectly also helps rule out data races, one of the worst kinds of -concurrency bugs. - -As an example, here is a Rust program that would have a data race in many -languages. It will not compile: - -```rust,ignore -use std::thread; -use std::time::Duration; - -fn main() { - let mut data = vec![1, 2, 3]; - - for i in 0..3 { - thread::spawn(move || { - data[0] += i; - }); - } - - thread::sleep(Duration::from_millis(50)); -} -``` - -This gives us an error: - -```text -8:17 error: capture of moved value: `data` - data[0] += i; - ^~~~ -``` - -Rust knows this wouldn't be safe! If we had a reference to `data` in each -thread, and the thread takes ownership of the reference, we'd have three owners! -`data` gets moved out of `main` in the first call to `spawn()`, so subsequent -calls in the loop cannot use this variable. - -So, we need some type that lets us have more than one owning reference to a -value. Usually, we'd use `Rc<T>` for this, which is a reference counted type -that provides shared ownership. It has some runtime bookkeeping that keeps track -of the number of references to it, hence the "reference count" part of its name. - -Calling `clone()` on an `Rc<T>` will return a new owned reference and bump the -internal reference count. We create one of these for each thread: - - -```rust,ignore -use std::thread; -use std::time::Duration; -use std::rc::Rc; - -fn main() { - let mut data = Rc::new(vec![1, 2, 3]); - - for i in 0..3 { - // Create a new owned reference: - let data_ref = data.clone(); - - // Use it in a thread: - thread::spawn(move || { - data_ref[0] += i; - }); - } - - thread::sleep(Duration::from_millis(50)); -} -``` - -This won't work, however, and will give us the error: - -```text -13:9: 13:22 error: the trait bound `alloc::rc::Rc<collections::vec::Vec<i32>> : core::marker::Send` - is not satisfied -... -13:9: 13:22 note: `alloc::rc::Rc<collections::vec::Vec<i32>>` - cannot be sent between threads safely -``` - -As the error message mentions, `Rc` cannot be sent between threads safely. This -is because the internal reference count is not maintained in a thread safe -matter and can have a data race. - -To solve this, we'll use `Arc<T>`, Rust's standard atomic reference count type. - -The Atomic part means `Arc<T>` can safely be accessed from multiple threads. -To do this the compiler guarantees that mutations of the internal count use -indivisible operations which can't have data races. - -In essence, `Arc<T>` is a type that lets us share ownership of data _across -threads_. - - -```rust,ignore -use std::thread; -use std::sync::Arc; -use std::time::Duration; - -fn main() { - let mut data = Arc::new(vec![1, 2, 3]); - - for i in 0..3 { - let data = data.clone(); - thread::spawn(move || { - data[0] += i; - }); - } - - thread::sleep(Duration::from_millis(50)); -} -``` - -Similarly to last time, we use `clone()` to create a new owned handle. -This handle is then moved into the new thread. - -And... still gives us an error. - -```text -<anon>:11:24 error: cannot borrow immutable borrowed content as mutable -<anon>:11 data[0] += i; - ^~~~ -``` - -`Arc<T>` by default has immutable contents. It allows the _sharing_ of data -between threads, but shared mutable data is unsafe—and when threads are -involved—can cause data races! - - -Usually when we wish to make something in an immutable position mutable, we use -`Cell<T>` or `RefCell<T>` which allow safe mutation via runtime checks or -otherwise (see also: [Choosing Your Guarantees](choosing-your-guarantees.html)). -However, similar to `Rc`, these are not thread safe. If we try using these, we -will get an error about these types not being `Sync`, and the code will fail to -compile. - -It looks like we need some type that allows us to safely mutate a shared value -across threads, for example a type that can ensure only one thread at a time is -able to mutate the value inside it at any one time. - -For that, we can use the `Mutex<T>` type! - -Here's the working version: - -```rust -use std::sync::{Arc, Mutex}; -use std::thread; -use std::time::Duration; - -fn main() { - let data = Arc::new(Mutex::new(vec![1, 2, 3])); - - for i in 0..3 { - let data = data.clone(); - thread::spawn(move || { - let mut data = data.lock().unwrap(); - data[0] += i; - }); - } - - thread::sleep(Duration::from_millis(50)); -} -``` - -Note that the value of `i` is bound (copied) to the closure and not shared -among the threads. - -We're "locking" the mutex here. A mutex (short for "mutual exclusion"), as -mentioned, only allows one thread at a time to access a value. When we wish to -access the value, we use `lock()` on it. This will "lock" the mutex, and no -other thread will be able to lock it (and hence, do anything with the value) -until we're done with it. If a thread attempts to lock a mutex which is already -locked, it will wait until the other thread releases the lock. - -The lock "release" here is implicit; when the result of the lock (in this case, -`data`) goes out of scope, the lock is automatically released. - -Note that [`lock`](../std/sync/struct.Mutex.html#method.lock) method of -[`Mutex`](../std/sync/struct.Mutex.html) has this signature: - -```rust,ignore -fn lock(&self) -> LockResult<MutexGuard<T>> -``` - -and because `Send` is not implemented for `MutexGuard<T>`, the guard cannot -cross thread boundaries, ensuring thread-locality of lock acquire and release. - -Let's examine the body of the thread more closely: - -```rust -# use std::sync::{Arc, Mutex}; -# use std::thread; -# use std::time::Duration; -# fn main() { -# let data = Arc::new(Mutex::new(vec![1, 2, 3])); -# for i in 0..3 { -# let data = data.clone(); -thread::spawn(move || { - let mut data = data.lock().unwrap(); - data[0] += i; -}); -# } -# thread::sleep(Duration::from_millis(50)); -# } -``` - -First, we call `lock()`, which acquires the mutex's lock. Because this may fail, -it returns a `Result<T, E>`, and because this is just an example, we `unwrap()` -it to get a reference to the data. Real code would have more robust error handling -here. We're then free to mutate it, since we have the lock. - -Lastly, while the threads are running, we wait on a short timer. But -this is not ideal: we may have picked a reasonable amount of time to -wait but it's more likely we'll either be waiting longer than -necessary or not long enough, depending on just how much time the -threads actually take to finish computing when the program runs. - -A more precise alternative to the timer would be to use one of the -mechanisms provided by the Rust standard library for synchronizing -threads with each other. Let's talk about one of them: channels. - -## Channels - -Here's a version of our code that uses channels for synchronization, rather -than waiting for a specific time: - -```rust -use std::sync::{Arc, Mutex}; -use std::thread; -use std::sync::mpsc; - -fn main() { - let data = Arc::new(Mutex::new(0)); - - // `tx` is the "transmitter" or "sender". - // `rx` is the "receiver". - let (tx, rx) = mpsc::channel(); - - for _ in 0..10 { - let (data, tx) = (data.clone(), tx.clone()); - - thread::spawn(move || { - let mut data = data.lock().unwrap(); - *data += 1; - - tx.send(()).unwrap(); - }); - } - - for _ in 0..10 { - rx.recv().unwrap(); - } -} -``` - -We use the `mpsc::channel()` method to construct a new channel. We `send` -a simple `()` down the channel, and then wait for ten of them to come back. - -While this channel is sending a generic signal, we can send any data that -is `Send` over the channel! - -```rust -use std::thread; -use std::sync::mpsc; - -fn main() { - let (tx, rx) = mpsc::channel(); - - for i in 0..10 { - let tx = tx.clone(); - - thread::spawn(move || { - let answer = i * i; - - tx.send(answer).unwrap(); - }); - } - - for _ in 0..10 { - println!("{}", rx.recv().unwrap()); - } -} -``` - -Here we create 10 threads, asking each to calculate the square of a number (`i` -at the time of `spawn()`), and then `send()` back the answer over the channel. - - -## Panics - -A `panic!` will crash the currently executing thread. You can use Rust's -threads as a simple isolation mechanism: - -```rust -use std::thread; - -let handle = thread::spawn(move || { - panic!("oops!"); -}); - -let result = handle.join(); - -assert!(result.is_err()); -``` - -`Thread.join()` gives us a `Result` back, which allows us to check if the thread -has panicked or not. diff --git a/src/doc/book/src/conditional-compilation.md b/src/doc/book/src/conditional-compilation.md deleted file mode 100644 index 0562e9fc430f6..0000000000000 --- a/src/doc/book/src/conditional-compilation.md +++ /dev/null @@ -1,91 +0,0 @@ -# Conditional Compilation - -Rust has a special attribute, `#[cfg]`, which allows you to compile code -based on a flag passed to the compiler. It has two forms: - -```rust -#[cfg(foo)] -# fn foo() {} - -#[cfg(bar = "baz")] -# fn bar() {} -``` - -They also have some helpers: - -```rust -#[cfg(any(unix, windows))] -# fn foo() {} - -#[cfg(all(unix, target_pointer_width = "32"))] -# fn bar() {} - -#[cfg(not(foo))] -# fn not_foo() {} -``` - -These can nest arbitrarily: - -```rust -#[cfg(any(not(unix), all(target_os="macos", target_arch = "powerpc")))] -# fn foo() {} -``` - -As for how to enable or disable these switches, if you’re using Cargo, -they get set in the [`[features]` section][features] of your `Cargo.toml`: - -[features]: http://doc.crates.io/manifest.html#the-features-section - -```toml -[features] -# no features by default -default = [] - -# Add feature "foo" here, then you can use it. -# Our "foo" feature depends on nothing else. -foo = [] -``` - -When you do this, Cargo passes along a flag to `rustc`: - -```text ---cfg feature="${feature_name}" -``` - -The sum of these `cfg` flags will determine which ones get activated, and -therefore, which code gets compiled. Let’s take this code: - -```rust -#[cfg(feature = "foo")] -mod foo { -} -``` - -If we compile it with `cargo build --features "foo"`, it will send the `--cfg -feature="foo"` flag to `rustc`, and the output will have the `mod foo` in it. -If we compile it with a regular `cargo build`, no extra flags get passed on, -and so, no `foo` module will exist. - -# cfg_attr - -You can also set another attribute based on a `cfg` variable with `cfg_attr`: - -```rust -#[cfg_attr(a, b)] -# fn foo() {} -``` - -Will be the same as `#[b]` if `a` is set by `cfg` attribute, and nothing otherwise. - -# cfg! - -The `cfg!` macro lets you use these kinds of flags elsewhere in your code, too: - -```rust -if cfg!(target_os = "macos") || cfg!(target_os = "ios") { - println!("Think Different!"); -} -``` - -These will be replaced by a `true` or `false` at compile-time, depending on the -configuration settings. diff --git a/src/doc/book/src/const-and-static.md b/src/doc/book/src/const-and-static.md deleted file mode 100644 index 66a48566bd7c4..0000000000000 --- a/src/doc/book/src/const-and-static.md +++ /dev/null @@ -1,83 +0,0 @@ -# const and static - -Rust has a way of defining constants with the `const` keyword: - -```rust -const N: i32 = 5; -``` - -Unlike [`let`][let] bindings, you must annotate the type of a `const`. - -[let]: variable-bindings.html - -Constants live for the entire lifetime of a program. More specifically, -constants in Rust have no fixed address in memory. This is because they’re -effectively inlined to each place that they’re used. References to the same -constant are not necessarily guaranteed to refer to the same memory address for -this reason. - -# `static` - -Rust provides a ‘global variable’ sort of facility in static items. They’re -similar to constants, but static items aren’t inlined upon use. This means that -there is only one instance for each value, and it’s at a fixed location in -memory. - -Here’s an example: - -```rust -static N: i32 = 5; -``` - -Unlike [`let`][let] bindings, you must annotate the type of a `static`. - -Statics live for the entire lifetime of a program, and therefore any -reference stored in a static has a [`'static` lifetime][lifetimes]: - -```rust -static NAME: &'static str = "Steve"; -``` - -[lifetimes]: lifetimes.html - -## Mutability - -You can introduce mutability with the `mut` keyword: - -```rust -static mut N: i32 = 5; -``` - -Because this is mutable, one thread could be updating `N` while another is -reading it, causing memory unsafety. As such both accessing and mutating a -`static mut` is [`unsafe`][unsafe], and so must be done in an `unsafe` block: - -```rust -# static mut N: i32 = 5; - -unsafe { - N += 1; - - println!("N: {}", N); -} -``` - -[unsafe]: unsafe.html - -Furthermore, any type stored in a `static` must be `Sync`, and must not have -a [`Drop`][drop] implementation. - -[drop]: drop.html - -# Initializing - -Both `const` and `static` have requirements for giving them a value. They must -be given a value that’s a constant expression. In other words, you cannot use -the result of a function call or anything similarly complex or at runtime. - -# Which construct should I use? - -Almost always, if you can choose between the two, choose `const`. It’s pretty -rare that you actually want a memory location associated with your constant, -and using a `const` allows for optimizations like constant propagation not only -in your crate but downstream crates. diff --git a/src/doc/book/src/crates-and-modules.md b/src/doc/book/src/crates-and-modules.md deleted file mode 100644 index 84f5fac044e0e..0000000000000 --- a/src/doc/book/src/crates-and-modules.md +++ /dev/null @@ -1,593 +0,0 @@ -# Crates and Modules - -When a project starts getting large, it’s considered good software -engineering practice to split it up into a bunch of smaller pieces, and then -fit them together. It is also important to have a well-defined interface, so -that some of your functionality is private, and some is public. To facilitate -these kinds of things, Rust has a module system. - -# Basic terminology: Crates and Modules - -Rust has two distinct terms that relate to the module system: ‘crate’ and -‘module’. A crate is synonymous with a ‘library’ or ‘package’ in other -languages. Hence “Cargo” as the name of Rust’s package management tool: you -ship your crates to others with Cargo. Crates can produce an executable or a -library, depending on the project. - -Each crate has an implicit *root module* that contains the code for that crate. -You can then define a tree of sub-modules under that root module. Modules allow -you to partition your code within the crate itself. - -As an example, let’s make a *phrases* crate, which will give us various phrases -in different languages. To keep things simple, we’ll stick to ‘greetings’ and -‘farewells’ as two kinds of phrases, and use English and Japanese (日本語) as -two languages for those phrases to be in. We’ll use this module layout: - -```text - +-----------+ - +---| greetings | - +---------+ | +-----------+ - +---| english |---+ - | +---------+ | +-----------+ - | +---| farewells | -+---------+ | +-----------+ -| phrases |---+ -+---------+ | +-----------+ - | +---| greetings | - | +----------+ | +-----------+ - +---| japanese |--+ - +----------+ | +-----------+ - +---| farewells | - +-----------+ -``` - -In this example, `phrases` is the name of our crate. All of the rest are -modules. You can see that they form a tree, branching out from the crate -*root*, which is the root of the tree: `phrases` itself. - -Now that we have a plan, let’s define these modules in code. To start, -generate a new crate with Cargo: - -```bash -$ cargo new phrases -$ cd phrases -``` - -If you remember, this generates a simple project for us: - -```bash -$ tree . -. -├── Cargo.toml -└── src - └── lib.rs - -1 directory, 2 files -``` - -`src/lib.rs` is our crate root, corresponding to the `phrases` in our diagram -above. - -# Defining Modules - -To define each of our modules, we use the `mod` keyword. Let’s make our -`src/lib.rs` look like this: - -```rust -mod english { - mod greetings { - } - - mod farewells { - } -} - -mod japanese { - mod greetings { - } - - mod farewells { - } -} -``` - -After the `mod` keyword, you give the name of the module. Module names follow -the conventions for other Rust identifiers: `lower_snake_case`. The contents of -each module are within curly braces (`{}`). - -Within a given `mod`, you can declare sub-`mod`s. We can refer to sub-modules -with double-colon (`::`) notation: our four nested modules are -`english::greetings`, `english::farewells`, `japanese::greetings`, and -`japanese::farewells`. Because these sub-modules are namespaced under their -parent module, the names don’t conflict: `english::greetings` and -`japanese::greetings` are distinct, even though their names are both -`greetings`. - -Because this crate does not have a `main()` function, and is called `lib.rs`, -Cargo will build this crate as a library: - -```bash -$ cargo build - Compiling phrases v0.0.1 (file:///home/you/projects/phrases) -$ ls target/debug -build deps examples libphrases-a7448e02a0468eaa.rlib native -``` - -`libphrases-<hash>.rlib` is the compiled crate. Before we see how to use this -crate from another crate, let’s break it up into multiple files. - -# Multiple File Crates - -If each crate were just one file, these files would get very large. It’s often -easier to split up crates into multiple files, and Rust supports this in two -ways. - -Instead of declaring a module like this: - -```rust,ignore -mod english { - // Contents of our module go here. -} -``` - -We can instead declare our module like this: - -```rust,ignore -mod english; -``` - -If we do that, Rust will expect to find either a `english.rs` file, or a -`english/mod.rs` file with the contents of our module. - -Note that in these files, you don’t need to re-declare the module: that’s -already been done with the initial `mod` declaration. - -Using these two techniques, we can break up our crate into two directories and -seven files: - -```bash -$ tree . -. -├── Cargo.lock -├── Cargo.toml -├── src -│ ├── english -│ │ ├── farewells.rs -│ │ ├── greetings.rs -│ │ └── mod.rs -│ ├── japanese -│ │ ├── farewells.rs -│ │ ├── greetings.rs -│ │ └── mod.rs -│ └── lib.rs -└── target - └── debug - ├── build - ├── deps - ├── examples - ├── libphrases-a7448e02a0468eaa.rlib - └── native -``` - -`src/lib.rs` is our crate root, and looks like this: - -```rust,ignore -mod english; -mod japanese; -``` - -These two declarations tell Rust to look for either `src/english.rs` and -`src/japanese.rs`, or `src/english/mod.rs` and `src/japanese/mod.rs`, depending -on our preference. In this case, because our modules have sub-modules, we’ve -chosen the second. Both `src/english/mod.rs` and `src/japanese/mod.rs` look -like this: - -```rust,ignore -mod greetings; -mod farewells; -``` - -Again, these declarations tell Rust to look for either -`src/english/greetings.rs`, `src/english/farewells.rs`, -`src/japanese/greetings.rs` and `src/japanese/farewells.rs` or -`src/english/greetings/mod.rs`, `src/english/farewells/mod.rs`, -`src/japanese/greetings/mod.rs` and -`src/japanese/farewells/mod.rs`. Because these sub-modules don’t have -their own sub-modules, we’ve chosen to make them -`src/english/greetings.rs`, `src/english/farewells.rs`, -`src/japanese/greetings.rs` and `src/japanese/farewells.rs`. Whew! - -The contents of `src/english/greetings.rs`, -`src/english/farewells.rs`, `src/japanese/greetings.rs` and -`src/japanese/farewells.rs` are all empty at the moment. Let’s add -some functions. - -Put this in `src/english/greetings.rs`: - -```rust -fn hello() -> String { - "Hello!".to_string() -} -``` - -Put this in `src/english/farewells.rs`: - -```rust -fn goodbye() -> String { - "Goodbye.".to_string() -} -``` - -Put this in `src/japanese/greetings.rs`: - -```rust -fn hello() -> String { - "こんにちは".to_string() -} -``` - -Of course, you can copy and paste this from this web page, or type -something else. It’s not important that you actually put ‘konnichiwa’ to learn -about the module system. - -Put this in `src/japanese/farewells.rs`: - -```rust -fn goodbye() -> String { - "さようなら".to_string() -} -``` - -(This is ‘Sayōnara’, if you’re curious.) - -Now that we have some functionality in our crate, let’s try to use it from -another crate. - -# Importing External Crates - -We have a library crate. Let’s make an executable crate that imports and uses -our library. - -Make a `src/main.rs` and put this in it (it won’t quite compile yet): - -```rust,ignore -extern crate phrases; - -fn main() { - println!("Hello in English: {}", phrases::english::greetings::hello()); - println!("Goodbye in English: {}", phrases::english::farewells::goodbye()); - - println!("Hello in Japanese: {}", phrases::japanese::greetings::hello()); - println!("Goodbye in Japanese: {}", phrases::japanese::farewells::goodbye()); -} -``` - -The `extern crate` declaration tells Rust that we need to compile and link to -the `phrases` crate. We can then use `phrases`’ modules in this one. As we -mentioned earlier, you can use double colons to refer to sub-modules and the -functions inside of them. - -(Note: when importing a crate that has dashes in its name "like-this", which is -not a valid Rust identifier, it will be converted by changing the dashes to -underscores, so you would write `extern crate like_this;`.) - -Also, Cargo assumes that `src/main.rs` is the crate root of a binary crate, -rather than a library crate. Our package now has two crates: `src/lib.rs` and -`src/main.rs`. This pattern is quite common for executable crates: most -functionality is in a library crate, and the executable crate uses that -library. This way, other programs can also use the library crate, and it’s also -a nice separation of concerns. - -This doesn’t quite work yet, though. We get four errors that look similar to -this: - -```bash -$ cargo build - Compiling phrases v0.0.1 (file:///home/you/projects/phrases) -src/main.rs:4:38: 4:72 error: function `hello` is private -src/main.rs:4 println!("Hello in English: {}", phrases::english::greetings::hello()); - ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -note: in expansion of format_args! -<std macros>:2:25: 2:58 note: expansion site -<std macros>:1:1: 2:62 note: in expansion of print! -<std macros>:3:1: 3:54 note: expansion site -<std macros>:1:1: 3:58 note: in expansion of println! -phrases/src/main.rs:4:5: 4:76 note: expansion site -``` - -By default, everything is private in Rust. Let’s talk about this in some more -depth. - -# Exporting a Public Interface - -Rust allows you to precisely control which aspects of your interface are -public, and so private is the default. To make things public, you use the `pub` -keyword. Let’s focus on the `english` module first, so let’s reduce our `src/main.rs` -to only this: - -```rust,ignore -extern crate phrases; - -fn main() { - println!("Hello in English: {}", phrases::english::greetings::hello()); - println!("Goodbye in English: {}", phrases::english::farewells::goodbye()); -} -``` - -In our `src/lib.rs`, let’s add `pub` to the `english` module declaration: - -```rust,ignore -pub mod english; -mod japanese; -``` - -And in our `src/english/mod.rs`, let’s make both `pub`: - -```rust,ignore -pub mod greetings; -pub mod farewells; -``` - -In our `src/english/greetings.rs`, let’s add `pub` to our `fn` declaration: - -```rust,ignore -pub fn hello() -> String { - "Hello!".to_string() -} -``` - -And also in `src/english/farewells.rs`: - -```rust,ignore -pub fn goodbye() -> String { - "Goodbye.".to_string() -} -``` - -Now, our crate compiles, albeit with warnings about not using the `japanese` -functions: - -```bash -$ cargo run - Compiling phrases v0.0.1 (file:///home/you/projects/phrases) -src/japanese/greetings.rs:1:1: 3:2 warning: function is never used: `hello`, #[warn(dead_code)] on by default -src/japanese/greetings.rs:1 fn hello() -> String { -src/japanese/greetings.rs:2 "こんにちは".to_string() -src/japanese/greetings.rs:3 } -src/japanese/farewells.rs:1:1: 3:2 warning: function is never used: `goodbye`, #[warn(dead_code)] on by default -src/japanese/farewells.rs:1 fn goodbye() -> String { -src/japanese/farewells.rs:2 "さようなら".to_string() -src/japanese/farewells.rs:3 } - Running `target/debug/phrases` -Hello in English: Hello! -Goodbye in English: Goodbye. -``` - -`pub` also applies to `struct`s and their member fields. In keeping with Rust’s -tendency toward safety, simply making a `struct` public won't automatically -make its members public: you must mark the fields individually with `pub`. - -Now that our functions are public, we can use them. Great! However, typing out -`phrases::english::greetings::hello()` is very long and repetitive. Rust has -another keyword for importing names into the current scope, so that you can -refer to them with shorter names. Let’s talk about `use`. - -# Importing Modules with `use` - -Rust has a `use` keyword, which allows us to import names into our local scope. -Let’s change our `src/main.rs` to look like this: - -```rust,ignore -extern crate phrases; - -use phrases::english::greetings; -use phrases::english::farewells; - -fn main() { - println!("Hello in English: {}", greetings::hello()); - println!("Goodbye in English: {}", farewells::goodbye()); -} -``` - -The two `use` lines import each module into the local scope, so we can refer to -the functions by a much shorter name. By convention, when importing functions, it’s -considered best practice to import the module, rather than the function directly. In -other words, you _can_ do this: - -```rust,ignore -extern crate phrases; - -use phrases::english::greetings::hello; -use phrases::english::farewells::goodbye; - -fn main() { - println!("Hello in English: {}", hello()); - println!("Goodbye in English: {}", goodbye()); -} -``` - -But it is not idiomatic. This is significantly more likely to introduce a -naming conflict. In our short program, it’s not a big deal, but as it grows, it -becomes a problem. If we have conflicting names, Rust will give a compilation -error. For example, if we made the `japanese` functions public, and tried to do -this: - -```rust,ignore -extern crate phrases; - -use phrases::english::greetings::hello; -use phrases::japanese::greetings::hello; - -fn main() { - println!("Hello in English: {}", hello()); - println!("Hello in Japanese: {}", hello()); -} -``` - -Rust will give us a compile-time error: - -```text - Compiling phrases v0.0.1 (file:///home/you/projects/phrases) -src/main.rs:4:5: 4:40 error: a value named `hello` has already been imported in this module [E0252] -src/main.rs:4 use phrases::japanese::greetings::hello; - ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error -Could not compile `phrases`. -``` - -If we’re importing multiple names from the same module, we don’t have to type it out -twice. Instead of this: - -```rust,ignore -use phrases::english::greetings; -use phrases::english::farewells; -``` - -We can use this shortcut: - -```rust,ignore -use phrases::english::{greetings, farewells}; -``` - -## Re-exporting with `pub use` - -You don’t only use `use` to shorten identifiers. You can also use it inside of your crate -to re-export a function inside another module. This allows you to present an external -interface that may not directly map to your internal code organization. - -Let’s look at an example. Modify your `src/main.rs` to read like this: - -```rust,ignore -extern crate phrases; - -use phrases::english::{greetings,farewells}; -use phrases::japanese; - -fn main() { - println!("Hello in English: {}", greetings::hello()); - println!("Goodbye in English: {}", farewells::goodbye()); - - println!("Hello in Japanese: {}", japanese::hello()); - println!("Goodbye in Japanese: {}", japanese::goodbye()); -} -``` - -Then, modify your `src/lib.rs` to make the `japanese` mod public: - -```rust,ignore -pub mod english; -pub mod japanese; -``` - -Next, make the two functions public, first in `src/japanese/greetings.rs`: - -```rust,ignore -pub fn hello() -> String { - "こんにちは".to_string() -} -``` - -And then in `src/japanese/farewells.rs`: - -```rust,ignore -pub fn goodbye() -> String { - "さようなら".to_string() -} -``` - -Finally, modify your `src/japanese/mod.rs` to read like this: - -```rust,ignore -pub use self::greetings::hello; -pub use self::farewells::goodbye; - -mod greetings; -mod farewells; -``` - -The `pub use` declaration brings the function into scope at this part of our -module hierarchy. Because we’ve `pub use`d this inside of our `japanese` -module, we now have a `phrases::japanese::hello()` function and a -`phrases::japanese::goodbye()` function, even though the code for them lives in -`phrases::japanese::greetings::hello()` and -`phrases::japanese::farewells::goodbye()`. Our internal organization doesn’t -define our external interface. - -Here we have a `pub use` for each function we want to bring into the -`japanese` scope. We could alternatively use the wildcard syntax to include -everything from `greetings` into the current scope: `pub use self::greetings::*`. - -What about the `self`? Well, by default, `use` declarations are absolute paths, -starting from your crate root. `self` makes that path relative to your current -place in the hierarchy instead. There’s one more special form of `use`: you can -`use super::` to reach one level up the tree from your current location. Some -people like to think of `self` as `.` and `super` as `..`, from many shells’ -display for the current directory and the parent directory. - -Outside of `use`, paths are relative: `foo::bar()` refers to a function inside -of `foo` relative to where we are. If that’s prefixed with `::`, as in -`::foo::bar()`, it refers to a different `foo`, an absolute path from your -crate root. - -This will build and run: - -```bash -$ cargo run - Compiling phrases v0.0.1 (file:///home/you/projects/phrases) - Running `target/debug/phrases` -Hello in English: Hello! -Goodbye in English: Goodbye. -Hello in Japanese: こんにちは -Goodbye in Japanese: さようなら -``` - -## Complex imports - -Rust offers several advanced options that can add compactness and -convenience to your `extern crate` and `use` statements. Here is an example: - -```rust,ignore -extern crate phrases as sayings; - -use sayings::japanese::greetings as ja_greetings; -use sayings::japanese::farewells::*; -use sayings::english::{self, greetings as en_greetings, farewells as en_farewells}; - -fn main() { - println!("Hello in English; {}", en_greetings::hello()); - println!("And in Japanese: {}", ja_greetings::hello()); - println!("Goodbye in English: {}", english::farewells::goodbye()); - println!("Again: {}", en_farewells::goodbye()); - println!("And in Japanese: {}", goodbye()); -} -``` - -What's going on here? - -First, both `extern crate` and `use` allow renaming the thing that is being -imported. So the crate is still called "phrases", but here we will refer -to it as "sayings". Similarly, the first `use` statement pulls in the -`japanese::greetings` module from the crate, but makes it available as -`ja_greetings` as opposed to simply `greetings`. This can help to avoid -ambiguity when importing similarly-named items from different places. - -The second `use` statement uses a star glob to bring in all public symbols from -the `sayings::japanese::farewells` module. As you can see we can later refer to -the Japanese `goodbye` function with no module qualifiers. This kind of glob -should be used sparingly. It’s worth noting that it only imports the public -symbols, even if the code doing the globbing is in the same module. - -The third `use` statement bears more explanation. It's using "brace expansion" -globbing to compress three `use` statements into one (this sort of syntax -may be familiar if you've written Linux shell scripts before). The -uncompressed form of this statement would be: - -```rust,ignore -use sayings::english; -use sayings::english::greetings as en_greetings; -use sayings::english::farewells as en_farewells; -``` - -As you can see, the curly brackets compress `use` statements for several items -under the same path, and in this context `self` refers back to that path. -Note: The curly brackets cannot be nested or mixed with star globbing. diff --git a/src/doc/book/src/deref-coercions.md b/src/doc/book/src/deref-coercions.md deleted file mode 100644 index 8552a7c8b3425..0000000000000 --- a/src/doc/book/src/deref-coercions.md +++ /dev/null @@ -1,119 +0,0 @@ -# `Deref` coercions - -The standard library provides a special trait, [`Deref`][deref]. It’s normally -used to overload `*`, the dereference operator: - -```rust -use std::ops::Deref; - -struct DerefExample<T> { - value: T, -} - -impl<T> Deref for DerefExample<T> { - type Target = T; - - fn deref(&self) -> &T { - &self.value - } -} - -fn main() { - let x = DerefExample { value: 'a' }; - assert_eq!('a', *x); -} -``` - -[deref]: ../std/ops/trait.Deref.html - -This is useful for writing custom pointer types. However, there’s a language -feature related to `Deref`: ‘deref coercions’. Here’s the rule: If you have a -type `U`, and it implements `Deref<Target=T>`, values of `&U` will -automatically coerce to a `&T`. Here’s an example: - -```rust -fn foo(s: &str) { - // Borrow a string for a second. -} - -// String implements Deref<Target=str>. -let owned = "Hello".to_string(); - -// Therefore, this works: -foo(&owned); -``` - -Using an ampersand in front of a value takes a reference to it. So `owned` is a -`String`, `&owned` is an `&String`, and since `impl Deref<Target=str> for -String`, `&String` will deref to `&str`, which `foo()` takes. - -That’s it. This rule is one of the only places in which Rust does an automatic -conversion for you, but it adds a lot of flexibility. For example, the `Rc<T>` -type implements `Deref<Target=T>`, so this works: - -```rust -use std::rc::Rc; - -fn foo(s: &str) { - // Borrow a string for a second. -} - -// String implements Deref<Target=str>. -let owned = "Hello".to_string(); -let counted = Rc::new(owned); - -// Therefore, this works: -foo(&counted); -``` - -All we’ve done is wrap our `String` in an `Rc<T>`. But we can now pass the -`Rc<String>` around anywhere we’d have a `String`. The signature of `foo` -didn’t change, but works just as well with either type. This example has two -conversions: `&Rc<String>` to `&String` and then `&String` to `&str`. Rust will do -this as many times as possible until the types match. - -Another very common implementation provided by the standard library is: - -```rust -fn foo(s: &[i32]) { - // Borrow a slice for a second. -} - -// Vec<T> implements Deref<Target=[T]>. -let owned = vec![1, 2, 3]; - -foo(&owned); -``` - -Vectors can `Deref` to a slice. - -## Deref and method calls - -`Deref` will also kick in when calling a method. Consider the following -example. - -```rust -struct Foo; - -impl Foo { - fn foo(&self) { println!("Foo"); } -} - -let f = &&Foo; - -f.foo(); -``` - -Even though `f` is a `&&Foo` and `foo` takes `&self`, this works. That’s -because these things are the same: - -```rust,ignore -f.foo(); -(&f).foo(); -(&&f).foo(); -(&&&&&&&&f).foo(); -``` - -A value of type `&&&&&&&&&&&&&&&&Foo` can still have methods defined on `Foo` -called, because the compiler will insert as many * operations as necessary to -get it right. And since it’s inserting `*`s, that uses `Deref`. diff --git a/src/doc/book/src/documentation.md b/src/doc/book/src/documentation.md deleted file mode 100644 index 69d49e2f96aa8..0000000000000 --- a/src/doc/book/src/documentation.md +++ /dev/null @@ -1,672 +0,0 @@ -# Documentation - -Documentation is an important part of any software project, and it's -first-class in Rust. Let's talk about the tooling Rust gives you to -document your project. - -## About `rustdoc` - -The Rust distribution includes a tool, `rustdoc`, that generates documentation. -`rustdoc` is also used by Cargo through `cargo doc`. - -Documentation can be generated in two ways: from source code, and from -standalone Markdown files. - -## Documenting source code - -The primary way of documenting a Rust project is through annotating the source -code. You can use documentation comments for this purpose: - -```rust,ignore -/// Constructs a new `Rc<T>`. -/// -/// # Examples -/// -/// ``` -/// use std::rc::Rc; -/// -/// let five = Rc::new(5); -/// ``` -pub fn new(value: T) -> Rc<T> { - // Implementation goes here. -} -``` - -This code generates documentation that looks [like this][rc-new]. I've left the -implementation out, with a regular comment in its place. - -The first thing to notice about this annotation is that it uses -`///` instead of `//`. The triple slash -indicates a documentation comment. - -Documentation comments are written in Markdown. - -Rust keeps track of these comments, and uses them when generating -documentation. This is important when documenting things like enums: - -```rust -/// The `Option` type. See [the module level documentation](index.html) for more. -enum Option<T> { - /// No value - None, - /// Some value `T` - Some(T), -} -``` - -The above works, but this does not: - -```rust,ignore -/// The `Option` type. See [the module level documentation](index.html) for more. -enum Option<T> { - None, /// No value - Some(T), /// Some value `T` -} -``` - -You'll get an error: - -```text -hello.rs:4:1: 4:2 error: expected ident, found `}` -hello.rs:4 } - ^ -``` - -This [unfortunate error](https://github.com/rust-lang/rust/issues/22547) is -correct; documentation comments apply to the thing after them, and there's -nothing after that last comment. - -[rc-new]: ../std/rc/struct.Rc.html#method.new - -### Writing documentation comments - -Anyway, let's cover each part of this comment in detail: - -```rust -/// Constructs a new `Rc<T>`. -# fn foo() {} -``` - -The first line of a documentation comment should be a short summary of its -functionality. One sentence. Just the basics. High level. - -```rust -/// -/// Other details about constructing `Rc<T>`s, maybe describing complicated -/// semantics, maybe additional options, all kinds of stuff. -/// -# fn foo() {} -``` - -Our original example had just a summary line, but if we had more things to say, -we could have added more explanation in a new paragraph. - -#### Special sections - -Next, are special sections. These are indicated with a header, `#`. There -are four kinds of headers that are commonly used. They aren't special syntax, -just convention, for now. - -```rust -/// # Panics -# fn foo() {} -``` - -Unrecoverable misuses of a function (i.e. programming errors) in Rust are -usually indicated by panics, which kill the whole current thread at the very -least. If your function has a non-trivial contract like this, that is -detected/enforced by panics, documenting it is very important. - -```rust -/// # Errors -# fn foo() {} -``` - -If your function or method returns a `Result<T, E>`, then describing the -conditions under which it returns `Err(E)` is a nice thing to do. This is -slightly less important than `Panics`, because failure is encoded into the type -system, but it's still a good thing to do. - -```rust -/// # Safety -# fn foo() {} -``` - -If your function is `unsafe`, you should explain which invariants the caller is -responsible for upholding. - -```rust -/// # Examples -/// -/// ``` -/// use std::rc::Rc; -/// -/// let five = Rc::new(5); -/// ``` -# fn foo() {} -``` - -Fourth, `Examples`. Include one or more examples of using your function or -method, and your users will love you for it. These examples go inside of -code block annotations, which we'll talk about in a moment, and can have -more than one section: - -```rust -/// # Examples -/// -/// Simple `&str` patterns: -/// -/// ``` -/// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect(); -/// assert_eq!(v, vec!["Mary", "had", "a", "little", "lamb"]); -/// ``` -/// -/// More complex patterns with a lambda: -/// -/// ``` -/// let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_numeric()).collect(); -/// assert_eq!(v, vec!["abc", "def", "ghi"]); -/// ``` -# fn foo() {} -``` - -Let's discuss the details of these code blocks. - -#### Code block annotations - -To write some Rust code in a comment, use the triple graves: - -```rust -/// ``` -/// println!("Hello, world"); -/// ``` -# fn foo() {} -``` - -If you want something that's not Rust code, you can add an annotation: - -```rust -/// ```c -/// printf("Hello, world\n"); -/// ``` -# fn foo() {} -``` - -This will highlight according to whatever language you're showing off. -If you're only showing plain text, choose `text`. - -It's important to choose the correct annotation here, because `rustdoc` uses it -in an interesting way: It can be used to actually test your examples in a -library crate, so that they don't get out of date. If you have some C code but -`rustdoc` thinks it's Rust because you left off the annotation, `rustdoc` will -complain when trying to generate the documentation. - -## Documentation as tests - -Let's discuss our sample example documentation: - -```rust -/// ``` -/// println!("Hello, world"); -/// ``` -# fn foo() {} -``` - -You'll notice that you don't need a `fn main()` or anything here. `rustdoc` will -automatically add a `main()` wrapper around your code, using heuristics to attempt -to put it in the right place. For example: - -```rust -/// ``` -/// use std::rc::Rc; -/// -/// let five = Rc::new(5); -/// ``` -# fn foo() {} -``` - -This will end up testing: - -```rust -fn main() { - use std::rc::Rc; - let five = Rc::new(5); -} -``` - -Here's the full algorithm rustdoc uses to preprocess examples: - -1. Any leading `#![foo]` attributes are left intact as crate attributes. -2. Some common `allow` attributes are inserted, including - `unused_variables`, `unused_assignments`, `unused_mut`, - `unused_attributes`, and `dead_code`. Small examples often trigger - these lints. -3. If the example does not contain `extern crate`, then `extern crate - <mycrate>;` is inserted (note the lack of `#[macro_use]`). -4. Finally, if the example does not contain `fn main`, the remainder of the - text is wrapped in `fn main() { your_code }`. - -This generated `fn main` can be a problem! If you have `extern crate` or a `mod` -statements in the example code that are referred to by `use` statements, they will -fail to resolve unless you include at least `fn main() {}` to inhibit step 4. -`#[macro_use] extern crate` also does not work except at the crate root, so when -testing macros an explicit `main` is always required. It doesn't have to clutter -up your docs, though -- keep reading! - -Sometimes this algorithm isn't enough, though. For example, all of these code samples -with `///` we've been talking about? The raw text: - -```text -/// Some documentation. -# fn foo() {} -``` - -looks different than the output: - -```rust -/// Some documentation. -# fn foo() {} -``` - -Yes, that's right: you can add lines that start with `# `, and they will -be hidden from the output, but will be used when compiling your code. You -can use this to your advantage. In this case, documentation comments need -to apply to some kind of function, so if I want to show you just a -documentation comment, I need to add a little function definition below -it. At the same time, it's only there to satisfy the compiler, so hiding -it makes the example more clear. You can use this technique to explain -longer examples in detail, while still preserving the testability of your -documentation. - -For example, imagine that we wanted to document this code: - -```rust -let x = 5; -let y = 6; -println!("{}", x + y); -``` - -We might want the documentation to end up looking like this: - -> First, we set `x` to five: -> -> ```rust -> let x = 5; -> # let y = 6; -> # println!("{}", x + y); -> ``` -> -> Next, we set `y` to six: -> -> ```rust -> # let x = 5; -> let y = 6; -> # println!("{}", x + y); -> ``` -> -> Finally, we print the sum of `x` and `y`: -> -> ```rust -> # let x = 5; -> # let y = 6; -> println!("{}", x + y); -> ``` - -To keep each code block testable, we want the whole program in each block, but -we don't want the reader to see every line every time. Here's what we put in -our source code: - -```text - First, we set `x` to five: - - ```rust - let x = 5; - # let y = 6; - # println!("{}", x + y); - ``` - - Next, we set `y` to six: - - ```rust - # let x = 5; - let y = 6; - # println!("{}", x + y); - ``` - - Finally, we print the sum of `x` and `y`: - - ```rust - # let x = 5; - # let y = 6; - println!("{}", x + y); - ``` -``` - -By repeating all parts of the example, you can ensure that your example still -compiles, while only showing the parts that are relevant to that part of your -explanation. - -### Documenting macros - -Here’s an example of documenting a macro: - -```rust -/// Panic with a given message unless an expression evaluates to true. -/// -/// # Examples -/// -/// ``` -/// # #[macro_use] extern crate foo; -/// # fn main() { -/// panic_unless!(1 + 1 == 2, “Math is broken.”); -/// # } -/// ``` -/// -/// ```rust,should_panic -/// # #[macro_use] extern crate foo; -/// # fn main() { -/// panic_unless!(true == false, “I’m broken.”); -/// # } -/// ``` -#[macro_export] -macro_rules! panic_unless { - ($condition:expr, $($rest:expr),+) => ({ if ! $condition { panic!($($rest),+); } }); -} -# fn main() {} -``` - -You’ll note three things: we need to add our own `extern crate` line, so that -we can add the `#[macro_use]` attribute. Second, we’ll need to add our own -`main()` as well (for reasons discussed above). Finally, a judicious use of -`#` to comment out those two things, so they don’t show up in the output. - -Another case where the use of `#` is handy is when you want to ignore -error handling. Lets say you want the following, - -```rust,ignore -/// use std::io; -/// let mut input = String::new(); -/// try!(io::stdin().read_line(&mut input)); -``` - -The problem is that `try!` returns a `Result<T, E>` and test functions -don't return anything so this will give a mismatched types error. - -```rust,ignore -/// A doc test using try! -/// -/// ``` -/// use std::io; -/// # fn foo() -> io::Result<()> { -/// let mut input = String::new(); -/// try!(io::stdin().read_line(&mut input)); -/// # Ok(()) -/// # } -/// ``` -# fn foo() {} -``` - -You can get around this by wrapping the code in a function. This catches -and swallows the `Result<T, E>` when running tests on the docs. This -pattern appears regularly in the standard library. - -### Running documentation tests - -To run the tests, either: - -```bash -$ rustdoc --test path/to/my/crate/root.rs -# or -$ cargo test -``` - -That's right, `cargo test` tests embedded documentation too. **However, -`cargo test` will not test binary crates, only library ones.** This is -due to the way `rustdoc` works: it links against the library to be tested, -but with a binary, there’s nothing to link to. - -There are a few more annotations that are useful to help `rustdoc` do the right -thing when testing your code: - -```rust -/// ```rust,ignore -/// fn foo() { -/// ``` -# fn foo() {} -``` - -The `ignore` directive tells Rust to ignore your code. This is almost never -what you want, as it's the most generic. Instead, consider annotating it -with `text` if it's not code, or using `#`s to get a working example that -only shows the part you care about. - -```rust -/// ```rust,should_panic -/// assert!(false); -/// ``` -# fn foo() {} -``` - -`should_panic` tells `rustdoc` that the code should compile correctly, but -not actually pass as a test. - -```rust -/// ```rust,no_run -/// loop { -/// println!("Hello, world"); -/// } -/// ``` -# fn foo() {} -``` - -The `no_run` attribute will compile your code, but not run it. This is -important for examples such as "Here's how to retrieve a web page," -which you would want to ensure compiles, but might be run in a test -environment that has no network access. - -### Documenting modules - -Rust has another kind of doc comment, `//!`. This comment doesn't document the next item, but the enclosing item. In other words: - -```rust -mod foo { - //! This is documentation for the `foo` module. - //! - //! # Examples - - // ... -} -``` - -This is where you'll see `//!` used most often: for module documentation. If -you have a module in `foo.rs`, you'll often open its code and see this: - -```rust -//! A module for using `foo`s. -//! -//! The `foo` module contains a lot of useful functionality blah blah blah... -``` - -### Crate documentation - -Crates can be documented by placing an inner doc comment (`//!`) at the -beginning of the crate root, aka `lib.rs`: - -```rust -//! This is documentation for the `foo` crate. -//! -//! The foo crate is meant to be used for bar. -``` - -### Documentation comment style - -Check out [RFC 505][rfc505] for full conventions around the style and format of -documentation. - -[rfc505]: https://github.com/rust-lang/rfcs/blob/master/text/0505-api-comment-conventions.md - -## Other documentation - -All of this behavior works in non-Rust source files too. Because comments -are written in Markdown, they're often `.md` files. - -When you write documentation in Markdown files, you don't need to prefix -the documentation with comments. For example: - -```rust -/// # Examples -/// -/// ``` -/// use std::rc::Rc; -/// -/// let five = Rc::new(5); -/// ``` -# fn foo() {} -``` - -is: - -~~~markdown -# Examples - -``` -use std::rc::Rc; - -let five = Rc::new(5); -``` -~~~ - -when it's in a Markdown file. There is one wrinkle though: Markdown files need -to have a title like this: - -```markdown -% The title - -This is the example documentation. -``` - -This `%` line needs to be the very first line of the file. - -## `doc` attributes - -At a deeper level, documentation comments are syntactic sugar for documentation -attributes: - -```rust -/// this -# fn foo() {} - -#[doc="this"] -# fn bar() {} -``` - -are the same, as are these: - -```rust -//! this - -#![doc="this"] -``` - -You won't often see this attribute used for writing documentation, but it -can be useful when changing some options, or when writing a macro. - -### Re-exports - -`rustdoc` will show the documentation for a public re-export in both places: - -```rust,ignore -extern crate foo; - -pub use foo::bar; -``` - -This will create documentation for `bar` both inside the documentation for the -crate `foo`, as well as the documentation for your crate. It will use the same -documentation in both places. - -This behavior can be suppressed with `no_inline`: - -```rust,ignore -extern crate foo; - -#[doc(no_inline)] -pub use foo::bar; -``` - -## Missing documentation - -Sometimes you want to make sure that every single public thing in your project -is documented, especially when you are working on a library. Rust allows you to -to generate warnings or errors, when an item is missing documentation. -To generate warnings you use `warn`: - -```rust,ignore -#![warn(missing_docs)] -``` - -And to generate errors you use `deny`: - -```rust,ignore -#![deny(missing_docs)] -``` - -There are cases where you want to disable these warnings/errors to explicitly -leave something undocumented. This is done by using `allow`: - -```rust -#[allow(missing_docs)] -struct Undocumented; -``` - -You might even want to hide items from the documentation completely: - -```rust -#[doc(hidden)] -struct Hidden; -``` - -### Controlling HTML - -You can control a few aspects of the HTML that `rustdoc` generates through the -`#![doc]` version of the attribute: - -```rust,ignore -#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", - html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://doc.rust-lang.org/")] -``` - -This sets a few different options, with a logo, favicon, and a root URL. - -### Configuring documentation tests - -You can also configure the way that `rustdoc` tests your documentation examples -through the `#![doc(test(..))]` attribute. - -```rust -#![doc(test(attr(allow(unused_variables), deny(warnings))))] -``` - -This allows unused variables within the examples, but will fail the test for any -other lint warning thrown. - -## Generation options - -`rustdoc` also contains a few other options on the command line, for further customization: - -- `--html-in-header FILE`: includes the contents of FILE at the end of the - `<head>...</head>` section. -- `--html-before-content FILE`: includes the contents of FILE directly after - `<body>`, before the rendered content (including the search bar). -- `--html-after-content FILE`: includes the contents of FILE after all the rendered content. - -## Security note - -The Markdown in documentation comments is placed without processing into -the final webpage. Be careful with literal HTML: - -```rust -/// <script>alert(document.cookie)</script> -# fn foo() {} -``` diff --git a/src/doc/book/src/drop.md b/src/doc/book/src/drop.md deleted file mode 100644 index 53c507eba3f78..0000000000000 --- a/src/doc/book/src/drop.md +++ /dev/null @@ -1,67 +0,0 @@ -# Drop - -Now that we’ve discussed traits, let’s talk about a particular trait provided -by the Rust standard library, [`Drop`][drop]. The `Drop` trait provides a way -to run some code when a value goes out of scope. For example: - -[drop]: ../std/ops/trait.Drop.html - -```rust -struct HasDrop; - -impl Drop for HasDrop { - fn drop(&mut self) { - println!("Dropping!"); - } -} - -fn main() { - let x = HasDrop; - - // Do stuff. - -} // `x` goes out of scope here. -``` - -When `x` goes out of scope at the end of `main()`, the code for `Drop` will -run. `Drop` has one method, which is also called `drop()`. It takes a mutable -reference to `self`. - -That’s it! The mechanics of `Drop` are very simple, but there are some -subtleties. For example, values are dropped in the opposite order they are -declared. Here’s another example: - -```rust -struct Firework { - strength: i32, -} - -impl Drop for Firework { - fn drop(&mut self) { - println!("BOOM times {}!!!", self.strength); - } -} - -fn main() { - let firecracker = Firework { strength: 1 }; - let tnt = Firework { strength: 100 }; -} -``` - -This will output: - -```text -BOOM times 100!!! -BOOM times 1!!! -``` - -The `tnt` goes off before the `firecracker` does, because it was declared -afterwards. Last in, first out. - -So what is `Drop` good for? Generally, `Drop` is used to clean up any resources -associated with a `struct`. For example, the [`Arc<T>` type][arc] is a -reference-counted type. When `Drop` is called, it will decrement the reference -count, and if the total number of references is zero, will clean up the -underlying value. - -[arc]: ../std/sync/struct.Arc.html diff --git a/src/doc/book/src/effective-rust.md b/src/doc/book/src/effective-rust.md deleted file mode 100644 index ce2dfe4eae27e..0000000000000 --- a/src/doc/book/src/effective-rust.md +++ /dev/null @@ -1,8 +0,0 @@ -# Effective Rust - -So you’ve learned how to write some Rust code. But there’s a difference between -writing *any* Rust code and writing *good* Rust code. - -This chapter consists of relatively independent tutorials which show you how to -take your Rust to the next level. Common patterns and standard library features -will be introduced. Read these sections in any order of your choosing. diff --git a/src/doc/book/src/enums.md b/src/doc/book/src/enums.md deleted file mode 100644 index 9cf5e6bfa21ac..0000000000000 --- a/src/doc/book/src/enums.md +++ /dev/null @@ -1,107 +0,0 @@ -# Enums - -An `enum` in Rust is a type that represents data that is one of -several possible variants. Each variant in the `enum` can optionally -have data associated with it: - -```rust -enum Message { - Quit, - ChangeColor(i32, i32, i32), - Move { x: i32, y: i32 }, - Write(String), -} -``` - -The syntax for defining variants resembles the syntaxes used to define structs: -you can have variants with no data (like unit-like structs), variants with named -data, and variants with unnamed data (like tuple structs). Unlike -separate struct definitions, however, an `enum` is a single type. A -value of the enum can match any of the variants. For this reason, an -enum is sometimes called a ‘sum type’: the set of possible values of the -enum is the sum of the sets of possible values for each variant. - -We use the `::` syntax to use the name of each variant: they’re scoped by the name -of the `enum` itself. This allows both of these to work: - -```rust -# enum Message { -# Move { x: i32, y: i32 }, -# } -let x: Message = Message::Move { x: 3, y: 4 }; - -enum BoardGameTurn { - Move { squares: i32 }, - Pass, -} - -let y: BoardGameTurn = BoardGameTurn::Move { squares: 1 }; -``` - -Both variants are named `Move`, but since they’re scoped to the name of -the enum, they can both be used without conflict. - -A value of an `enum` type contains information about which variant it is, -in addition to any data associated with that variant. This is sometimes -referred to as a ‘tagged union’, since the data includes a ‘tag’ -indicating what type it is. The compiler uses this information to -enforce that you’re accessing the data in the enum safely. For instance, -you can’t simply try to destructure a value as if it were one of the -possible variants: - -```rust,ignore -fn process_color_change(msg: Message) { - let Message::ChangeColor(r, g, b) = msg; // This causes a compile-time error. -} -``` - -Not supporting these operations may seem rather limiting, but it’s a limitation -which we can overcome. There are two ways: by implementing equality ourselves, -or by pattern matching variants with [`match`][match] expressions, which you’ll -learn in the next section. We don’t know enough about Rust to implement -equality yet, but we’ll find out in the [`traits`][traits] section. - -[match]: match.html -[traits]: traits.html - -# Constructors as functions - -An `enum` constructor can also be used like a function. For example: - -```rust -# enum Message { -# Write(String), -# } -let m = Message::Write("Hello, world".to_string()); -``` - -is the same as - -```rust -# enum Message { -# Write(String), -# } -fn foo(x: String) -> Message { - Message::Write(x) -} - -let x = foo("Hello, world".to_string()); -``` - -This is not immediately useful to us, but when we get to -[`closures`][closures], we’ll talk about passing functions as arguments to -other functions. For example, with [`iterators`][iterators], we can do this -to convert a vector of `String`s into a vector of `Message::Write`s: - -```rust -# enum Message { -# Write(String), -# } - -let v = vec!["Hello".to_string(), "World".to_string()]; - -let v1: Vec<Message> = v.into_iter().map(Message::Write).collect(); -``` - -[closures]: closures.html -[iterators]: iterators.html diff --git a/src/doc/book/src/error-handling.md b/src/doc/book/src/error-handling.md deleted file mode 100644 index c823c32a135bb..0000000000000 --- a/src/doc/book/src/error-handling.md +++ /dev/null @@ -1,2213 +0,0 @@ -# Error Handling - -Like most programming languages, Rust encourages the programmer to handle -errors in a particular way. Generally speaking, error handling is divided into -two broad categories: exceptions and return values. Rust opts for return -values. - -In this section, we intend to provide a comprehensive treatment of how to deal -with errors in Rust. More than that, we will attempt to introduce error handling -one piece at a time so that you'll come away with a solid working knowledge of -how everything fits together. - -When done naïvely, error handling in Rust can be verbose and annoying. This -section will explore those stumbling blocks and demonstrate how to use the -standard library to make error handling concise and ergonomic. - -# Table of Contents - -This section is very long, mostly because we start at the very beginning with -sum types and combinators, and try to motivate the way Rust does error handling -incrementally. As such, programmers with experience in other expressive type -systems may want to jump around. - -* [The Basics](#the-basics) - * [Unwrapping explained](#unwrapping-explained) - * [The `Option` type](#the-option-type) - * [Composing `Option<T>` values](#composing-optiont-values) - * [The `Result` type](#the-result-type) - * [Parsing integers](#parsing-integers) - * [The `Result` type alias idiom](#the-result-type-alias-idiom) - * [A brief interlude: unwrapping isn't evil](#a-brief-interlude-unwrapping-isnt-evil) -* [Working with multiple error types](#working-with-multiple-error-types) - * [Composing `Option` and `Result`](#composing-option-and-result) - * [The limits of combinators](#the-limits-of-combinators) - * [Early returns](#early-returns) - * [The `try!` macro](#the-try-macro) - * [Defining your own error type](#defining-your-own-error-type) -* [Standard library traits used for error handling](#standard-library-traits-used-for-error-handling) - * [The `Error` trait](#the-error-trait) - * [The `From` trait](#the-from-trait) - * [The real `try!` macro](#the-real-try-macro) - * [Composing custom error types](#composing-custom-error-types) - * [Advice for library writers](#advice-for-library-writers) -* [Case study: A program to read population data](#case-study-a-program-to-read-population-data) - * [Initial setup](#initial-setup) - * [Argument parsing](#argument-parsing) - * [Writing the logic](#writing-the-logic) - * [Error handling with `Box<Error>`](#error-handling-with-boxerror) - * [Reading from stdin](#reading-from-stdin) - * [Error handling with a custom type](#error-handling-with-a-custom-type) - * [Adding functionality](#adding-functionality) -* [The short story](#the-short-story) - -# The Basics - -You can think of error handling as using *case analysis* to determine whether -a computation was successful or not. As you will see, the key to ergonomic error -handling is reducing the amount of explicit case analysis the programmer has to -do while keeping code composable. - -Keeping code composable is important, because without that requirement, we -could [`panic`](../std/macro.panic.html) whenever we -come across something unexpected. (`panic` causes the current task to unwind, -and in most cases, the entire program aborts.) Here's an example: - -```rust,should_panic -// Guess a number between 1 and 10. -// If it matches the number we had in mind, return `true`. Else, return `false`. -fn guess(n: i32) -> bool { - if n < 1 || n > 10 { - panic!("Invalid number: {}", n); - } - n == 5 -} - -fn main() { - guess(11); -} -``` - -If you try running this code, the program will crash with a message like this: - -```text -thread 'main' panicked at 'Invalid number: 11', src/bin/panic-simple.rs:5 -``` - -Here's another example that is slightly less contrived. A program that accepts -an integer as an argument, doubles it and prints it. - -<span id="code-unwrap-double"></span> - -```rust,should_panic -use std::env; - -fn main() { - let mut argv = env::args(); - let arg: String = argv.nth(1).unwrap(); // error 1 - let n: i32 = arg.parse().unwrap(); // error 2 - println!("{}", 2 * n); -} -``` - -If you give this program zero arguments (error 1) or if the first argument -isn't an integer (error 2), the program will panic just like in the first -example. - -You can think of this style of error handling as similar to a bull running -through a china shop. The bull will get to where it wants to go, but it will -trample everything in the process. - -## Unwrapping explained - -In the previous example, we claimed -that the program would simply panic if it reached one of the two error -conditions, yet, the program does not include an explicit call to `panic` like -the first example. This is because the -panic is embedded in the calls to `unwrap`. - -To “unwrap” something in Rust is to say, “Give me the result of the -computation, and if there was an error, panic and stop the program.” -It would be better if we showed the code for unwrapping because it is so -simple, but to do that, we will first need to explore the `Option` and `Result` -types. Both of these types have a method called `unwrap` defined on them. - -### The `Option` type - -The `Option` type is [defined in the standard library][5]: - -```rust -enum Option<T> { - None, - Some(T), -} -``` - -The `Option` type is a way to use Rust's type system to express the -*possibility of absence*. Encoding the possibility of absence into the type -system is an important concept because it will cause the compiler to force the -programmer to handle that absence. Let's take a look at an example that tries -to find a character in a string: - -<span id="code-option-ex-string-find"></span> - -```rust -// Searches `haystack` for the Unicode character `needle`. If one is found, the -// byte offset of the character is returned. Otherwise, `None` is returned. -fn find(haystack: &str, needle: char) -> Option<usize> { - for (offset, c) in haystack.char_indices() { - if c == needle { - return Some(offset); - } - } - None -} -``` - -Notice that when this function finds a matching character, it doesn't only -return the `offset`. Instead, it returns `Some(offset)`. `Some` is a variant or -a *value constructor* for the `Option` type. You can think of it as a function -with the type `fn<T>(value: T) -> Option<T>`. Correspondingly, `None` is also a -value constructor, except it has no arguments. You can think of `None` as a -function with the type `fn<T>() -> Option<T>`. - -This might seem like much ado about nothing, but this is only half of the -story. The other half is *using* the `find` function we've written. Let's try -to use it to find the extension in a file name. - -```rust -# fn find(haystack: &str, needle: char) -> Option<usize> { haystack.find(needle) } -fn main() { - let file_name = "foobar.rs"; - match find(file_name, '.') { - None => println!("No file extension found."), - Some(i) => println!("File extension: {}", &file_name[i+1..]), - } -} -``` - -This code uses [pattern matching][1] to do *case -analysis* on the `Option<usize>` returned by the `find` function. In fact, case -analysis is the only way to get at the value stored inside an `Option<T>`. This -means that you, as the programmer, must handle the case when an `Option<T>` is -`None` instead of `Some(t)`. - -But wait, what about `unwrap`, which we used [previously](#code-unwrap-double)? -There was no case analysis there! Instead, the case analysis was put inside the -`unwrap` method for you. You could define it yourself if you want: - -<span id="code-option-def-unwrap"></span> - -```rust -enum Option<T> { - None, - Some(T), -} - -impl<T> Option<T> { - fn unwrap(self) -> T { - match self { - Option::Some(val) => val, - Option::None => - panic!("called `Option::unwrap()` on a `None` value"), - } - } -} -``` - -The `unwrap` method *abstracts away the case analysis*. This is precisely the thing -that makes `unwrap` ergonomic to use. Unfortunately, that `panic!` means that -`unwrap` is not composable: it is the bull in the china shop. - -### Composing `Option<T>` values - -In an [example from before](#code-option-ex-string-find), -we saw how to use `find` to discover the extension in a file name. Of course, -not all file names have a `.` in them, so it's possible that the file name has -no extension. This *possibility of absence* is encoded into the types using -`Option<T>`. In other words, the compiler will force us to address the -possibility that an extension does not exist. In our case, we only print out a -message saying as such. - -Getting the extension of a file name is a pretty common operation, so it makes -sense to put it into a function: - -```rust -# fn find(haystack: &str, needle: char) -> Option<usize> { haystack.find(needle) } -// Returns the extension of the given file name, where the extension is defined -// as all characters following the first `.`. -// If `file_name` has no `.`, then `None` is returned. -fn extension_explicit(file_name: &str) -> Option<&str> { - match find(file_name, '.') { - None => None, - Some(i) => Some(&file_name[i+1..]), - } -} -``` - -(Pro-tip: don't use this code. Use the -[`extension`](../std/path/struct.Path.html#method.extension) -method in the standard library instead.) - -The code stays simple, but the important thing to notice is that the type of -`find` forces us to consider the possibility of absence. This is a good thing -because it means the compiler won't let us accidentally forget about the case -where a file name doesn't have an extension. On the other hand, doing explicit -case analysis like we've done in `extension_explicit` every time can get a bit -tiresome. - -In fact, the case analysis in `extension_explicit` follows a very common -pattern: *map* a function on to the value inside of an `Option<T>`, unless the -option is `None`, in which case, return `None`. - -Rust has parametric polymorphism, so it is very easy to define a combinator -that abstracts this pattern: - -<span id="code-option-map"></span> - -```rust -fn map<F, T, A>(option: Option<T>, f: F) -> Option<A> where F: FnOnce(T) -> A { - match option { - None => None, - Some(value) => Some(f(value)), - } -} -``` - -Indeed, `map` is [defined as a method][2] on `Option<T>` in the standard library. -As a method, it has a slightly different signature: methods take `self`, `&self`, -or `&mut self` as their first argument. - -Armed with our new combinator, we can rewrite our `extension_explicit` method -to get rid of the case analysis: - -```rust -# fn find(haystack: &str, needle: char) -> Option<usize> { haystack.find(needle) } -// Returns the extension of the given file name, where the extension is defined -// as all characters following the first `.`. -// If `file_name` has no `.`, then `None` is returned. -fn extension(file_name: &str) -> Option<&str> { - find(file_name, '.').map(|i| &file_name[i+1..]) -} -``` - -One other pattern we commonly find is assigning a default value to the case -when an `Option` value is `None`. For example, maybe your program assumes that -the extension of a file is `rs` even if none is present. As you might imagine, -the case analysis for this is not specific to file extensions - it can work -with any `Option<T>`: - -```rust -fn unwrap_or<T>(option: Option<T>, default: T) -> T { - match option { - None => default, - Some(value) => value, - } -} -``` - -Like with `map` above, the standard library implementation is a method instead -of a free function. - -The trick here is that the default value must have the same type as the value -that might be inside the `Option<T>`. Using it is dead simple in our case: - -```rust -# fn find(haystack: &str, needle: char) -> Option<usize> { -# for (offset, c) in haystack.char_indices() { -# if c == needle { -# return Some(offset); -# } -# } -# None -# } -# -# fn extension(file_name: &str) -> Option<&str> { -# find(file_name, '.').map(|i| &file_name[i+1..]) -# } -fn main() { - assert_eq!(extension("foobar.csv").unwrap_or("rs"), "csv"); - assert_eq!(extension("foobar").unwrap_or("rs"), "rs"); -} -``` - -(Note that `unwrap_or` is [defined as a method][3] on `Option<T>` in the -standard library, so we use that here instead of the free-standing function we -defined above. Don't forget to check out the more general [`unwrap_or_else`][4] -method.) - -There is one more combinator that we think is worth paying special attention to: -`and_then`. It makes it easy to compose distinct computations that admit the -*possibility of absence*. For example, much of the code in this section is -about finding an extension given a file name. In order to do this, you first -need the file name which is typically extracted from a file *path*. While most -file paths have a file name, not *all* of them do. For example, `.`, `..` or -`/`. - -So, we are tasked with the challenge of finding an extension given a file -*path*. Let's start with explicit case analysis: - -```rust -# fn extension(file_name: &str) -> Option<&str> { None } -fn file_path_ext_explicit(file_path: &str) -> Option<&str> { - match file_name(file_path) { - None => None, - Some(name) => match extension(name) { - None => None, - Some(ext) => Some(ext), - } - } -} - -fn file_name(file_path: &str) -> Option<&str> { - // Implementation elided. - unimplemented!() -} -``` - -You might think that we could use the `map` combinator to reduce the case -analysis, but its type doesn't quite fit... - -```rust,ignore -fn file_path_ext(file_path: &str) -> Option<&str> { - file_name(file_path).map(|x| extension(x)) // This causes a compilation error. -} -``` - -The `map` function here wraps the value returned by the `extension` function -inside an `Option<_>` and since the `extension` function itself returns an -`Option<&str>` the expression `file_name(file_path).map(|x| extension(x))` -actually returns an `Option<Option<&str>>`. - -But since `file_path_ext` just returns `Option<&str>` (and not -`Option<Option<&str>>`) we get a compilation error. - -The result of the function taken by map as input is *always* [rewrapped with -`Some`](#code-option-map). Instead, we need something like `map`, but which -allows the caller to return a `Option<_>` directly without wrapping it in -another `Option<_>`. - -Its generic implementation is even simpler than `map`: - -```rust -fn and_then<F, T, A>(option: Option<T>, f: F) -> Option<A> - where F: FnOnce(T) -> Option<A> { - match option { - None => None, - Some(value) => f(value), - } -} -``` - -Now we can rewrite our `file_path_ext` function without explicit case analysis: - -```rust -# fn extension(file_name: &str) -> Option<&str> { None } -# fn file_name(file_path: &str) -> Option<&str> { None } -fn file_path_ext(file_path: &str) -> Option<&str> { - file_name(file_path).and_then(extension) -} -``` - -Side note: Since `and_then` essentially works like `map` but returns an -`Option<_>` instead of an `Option<Option<_>>` it is known as `flatmap` in some -other languages. - -The `Option` type has many other combinators [defined in the standard -library][5]. It is a good idea to skim this list and familiarize -yourself with what's available—they can often reduce case analysis -for you. Familiarizing yourself with these combinators will pay -dividends because many of them are also defined (with similar -semantics) for `Result`, which we will talk about next. - -Combinators make using types like `Option` ergonomic because they reduce -explicit case analysis. They are also composable because they permit the caller -to handle the possibility of absence in their own way. Methods like `unwrap` -remove choices because they will panic if `Option<T>` is `None`. - -## The `Result` type - -The `Result` type is also -[defined in the standard library][6]: - -<span id="code-result-def"></span> - -```rust -enum Result<T, E> { - Ok(T), - Err(E), -} -``` - -The `Result` type is a richer version of `Option`. Instead of expressing the -possibility of *absence* like `Option` does, `Result` expresses the possibility -of *error*. Usually, the *error* is used to explain why the execution of some -computation failed. This is a strictly more general form of `Option`. Consider -the following type alias, which is semantically equivalent to the real -`Option<T>` in every way: - -```rust -type Option<T> = Result<T, ()>; -``` - -This fixes the second type parameter of `Result` to always be `()` (pronounced -“unit” or “empty tuple”). Exactly one value inhabits the `()` type: `()`. (Yup, -the type and value level terms have the same notation!) - -The `Result` type is a way of representing one of two possible outcomes in a -computation. By convention, one outcome is meant to be expected or “`Ok`” while -the other outcome is meant to be unexpected or “`Err`”. - -Just like `Option`, the `Result` type also has an -[`unwrap` method -defined][7] -in the standard library. Let's define it: - -```rust -# enum Result<T, E> { Ok(T), Err(E) } -impl<T, E: ::std::fmt::Debug> Result<T, E> { - fn unwrap(self) -> T { - match self { - Result::Ok(val) => val, - Result::Err(err) => - panic!("called `Result::unwrap()` on an `Err` value: {:?}", err), - } - } -} -``` - -This is effectively the same as our [definition for -`Option::unwrap`](#code-option-def-unwrap), except it includes the -error value in the `panic!` message. This makes debugging easier, but -it also requires us to add a [`Debug`][8] constraint on the `E` type -parameter (which represents our error type). Since the vast majority -of types should satisfy the `Debug` constraint, this tends to work out -in practice. (`Debug` on a type simply means that there's a reasonable -way to print a human readable description of values with that type.) - -OK, let's move on to an example. - -### Parsing integers - -The Rust standard library makes converting strings to integers dead simple. -It's so easy in fact, that it is very tempting to write something like the -following: - -```rust -fn double_number(number_str: &str) -> i32 { - 2 * number_str.parse::<i32>().unwrap() -} - -fn main() { - let n: i32 = double_number("10"); - assert_eq!(n, 20); -} -``` - -At this point, you should be skeptical of calling `unwrap`. For example, if -the string doesn't parse as a number, you'll get a panic: - -```text -thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ParseIntError { kind: InvalidDigit }', /home/rustbuild/src/rust-buildbot/slave/beta-dist-rustc-linux/build/src/libcore/result.rs:729 -``` - -This is rather unsightly, and if this happened inside a library you're -using, you might be understandably annoyed. Instead, we should try to -handle the error in our function and let the caller decide what to -do. This means changing the return type of `double_number`. But to -what? Well, that requires looking at the signature of the [`parse` -method][9] in the standard library: - -```rust,ignore -impl str { - fn parse<F: FromStr>(&self) -> Result<F, F::Err>; -} -``` - -Hmm. So we at least know that we need to use a `Result`. Certainly, it's -possible that this could have returned an `Option`. After all, a string either -parses as a number or it doesn't, right? That's certainly a reasonable way to -go, but the implementation internally distinguishes *why* the string didn't -parse as an integer. (Whether it's an empty string, an invalid digit, too big -or too small.) Therefore, using a `Result` makes sense because we want to -provide more information than simply “absence.” We want to say *why* the -parsing failed. You should try to emulate this line of reasoning when faced -with a choice between `Option` and `Result`. If you can provide detailed error -information, then you probably should. (We'll see more on this later.) - -OK, but how do we write our return type? The `parse` method as defined -above is generic over all the different number types defined in the -standard library. We could (and probably should) also make our -function generic, but let's favor explicitness for the moment. We only -care about `i32`, so we need to [find its implementation of -`FromStr`](../std/primitive.i32.html) (do a `CTRL-F` in your browser -for “FromStr”) and look at its [associated type][10] `Err`. We did -this so we can find the concrete error type. In this case, it's -[`std::num::ParseIntError`](../std/num/struct.ParseIntError.html). -Finally, we can rewrite our function: - -```rust -use std::num::ParseIntError; - -fn double_number(number_str: &str) -> Result<i32, ParseIntError> { - match number_str.parse::<i32>() { - Ok(n) => Ok(2 * n), - Err(err) => Err(err), - } -} - -fn main() { - match double_number("10") { - Ok(n) => assert_eq!(n, 20), - Err(err) => println!("Error: {:?}", err), - } -} -``` - -This is a little better, but now we've written a lot more code! The case -analysis has once again bitten us. - -Combinators to the rescue! Just like `Option`, `Result` has lots of combinators -defined as methods. There is a large intersection of common combinators between -`Result` and `Option`. In particular, `map` is part of that intersection: - -```rust -use std::num::ParseIntError; - -fn double_number(number_str: &str) -> Result<i32, ParseIntError> { - number_str.parse::<i32>().map(|n| 2 * n) -} - -fn main() { - match double_number("10") { - Ok(n) => assert_eq!(n, 20), - Err(err) => println!("Error: {:?}", err), - } -} -``` - -The usual suspects are all there for `Result`, including -[`unwrap_or`](../std/result/enum.Result.html#method.unwrap_or) and -[`and_then`](../std/result/enum.Result.html#method.and_then). -Additionally, since `Result` has a second type parameter, there are -combinators that affect only the error type, such as -[`map_err`](../std/result/enum.Result.html#method.map_err) (instead of -`map`) and [`or_else`](../std/result/enum.Result.html#method.or_else) -(instead of `and_then`). - -### The `Result` type alias idiom - -In the standard library, you may frequently see types like -`Result<i32>`. But wait, [we defined `Result`](#code-result-def) to -have two type parameters. How can we get away with only specifying -one? The key is to define a `Result` type alias that *fixes* one of -the type parameters to a particular type. Usually the fixed type is -the error type. For example, our previous example parsing integers -could be rewritten like this: - -```rust -use std::num::ParseIntError; -use std::result; - -type Result<T> = result::Result<T, ParseIntError>; - -fn double_number(number_str: &str) -> Result<i32> { - unimplemented!(); -} -``` - -Why would we do this? Well, if we have a lot of functions that could return -`ParseIntError`, then it's much more convenient to define an alias that always -uses `ParseIntError` so that we don't have to write it out all the time. - -The most prominent place this idiom is used in the standard library is -with [`io::Result`](../std/io/type.Result.html). Typically, one writes -`io::Result<T>`, which makes it clear that you're using the `io` -module's type alias instead of the plain definition from -`std::result`. (This idiom is also used for -[`fmt::Result`](../std/fmt/type.Result.html).) - -## A brief interlude: unwrapping isn't evil - -If you've been following along, you might have noticed that I've taken a pretty -hard line against calling methods like `unwrap` that could `panic` and abort -your program. *Generally speaking*, this is good advice. - -However, `unwrap` can still be used judiciously. What exactly justifies use of -`unwrap` is somewhat of a grey area and reasonable people can disagree. I'll -summarize some of my *opinions* on the matter. - -* **In examples and quick 'n' dirty code.** Sometimes you're writing examples - or a quick program, and error handling simply isn't important. Beating the - convenience of `unwrap` can be hard in such scenarios, so it is very - appealing. -* **When panicking indicates a bug in the program.** When the invariants of - your code should prevent a certain case from happening (like, say, popping - from an empty stack), then panicking can be permissible. This is because it - exposes a bug in your program. This can be explicit, like from an `assert!` - failing, or it could be because your index into an array was out of bounds. - -This is probably not an exhaustive list. Moreover, when using an -`Option`, it is often better to use its -[`expect`](../std/option/enum.Option.html#method.expect) -method. `expect` does exactly the same thing as `unwrap`, except it -prints a message you give to `expect`. This makes the resulting panic -a bit nicer to deal with, since it will show your message instead of -“called unwrap on a `None` value.” - -My advice boils down to this: use good judgment. There's a reason why the words -“never do X” or “Y is considered harmful” don't appear in my writing. There are -trade offs to all things, and it is up to you as the programmer to determine -what is acceptable for your use cases. My goal is only to help you evaluate -trade offs as accurately as possible. - -Now that we've covered the basics of error handling in Rust, and -explained unwrapping, let's start exploring more of the standard -library. - -# Working with multiple error types - -Thus far, we've looked at error handling where everything was either an -`Option<T>` or a `Result<T, SomeError>`. But what happens when you have both an -`Option` and a `Result`? Or what if you have a `Result<T, Error1>` and a -`Result<T, Error2>`? Handling *composition of distinct error types* is the next -challenge in front of us, and it will be the major theme throughout the rest of -this section. - -## Composing `Option` and `Result` - -So far, I've talked about combinators defined for `Option` and combinators -defined for `Result`. We can use these combinators to compose results of -different computations without doing explicit case analysis. - -Of course, in real code, things aren't always as clean. Sometimes you have a -mix of `Option` and `Result` types. Must we resort to explicit case analysis, -or can we continue using combinators? - -For now, let's revisit one of the first examples in this section: - -```rust,should_panic -use std::env; - -fn main() { - let mut argv = env::args(); - let arg: String = argv.nth(1).unwrap(); // error 1 - let n: i32 = arg.parse().unwrap(); // error 2 - println!("{}", 2 * n); -} -``` - -Given our new found knowledge of `Option`, `Result` and their various -combinators, we should try to rewrite this so that errors are handled properly -and the program doesn't panic if there's an error. - -The tricky aspect here is that `argv.nth(1)` produces an `Option` while -`arg.parse()` produces a `Result`. These aren't directly composable. When faced -with both an `Option` and a `Result`, the solution is *usually* to convert the -`Option` to a `Result`. In our case, the absence of a command line parameter -(from `env::args()`) means the user didn't invoke the program correctly. We -could use a `String` to describe the error. Let's try: - -<span id="code-error-double-string"></span> - -```rust -use std::env; - -fn double_arg(mut argv: env::Args) -> Result<i32, String> { - argv.nth(1) - .ok_or("Please give at least one argument".to_owned()) - .and_then(|arg| arg.parse::<i32>().map_err(|err| err.to_string())) - .map(|n| 2 * n) -} - -fn main() { - match double_arg(env::args()) { - Ok(n) => println!("{}", n), - Err(err) => println!("Error: {}", err), - } -} -``` - -There are a couple new things in this example. The first is the use of the -[`Option::ok_or`](../std/option/enum.Option.html#method.ok_or) -combinator. This is one way to convert an `Option` into a `Result`. The -conversion requires you to specify what error to use if `Option` is `None`. -Like the other combinators we've seen, its definition is very simple: - -```rust -fn ok_or<T, E>(option: Option<T>, err: E) -> Result<T, E> { - match option { - Some(val) => Ok(val), - None => Err(err), - } -} -``` - -The other new combinator used here is -[`Result::map_err`](../std/result/enum.Result.html#method.map_err). -This is like `Result::map`, except it maps a function on to the *error* -portion of a `Result` value. If the `Result` is an `Ok(...)` value, then it is -returned unmodified. - -We use `map_err` here because it is necessary for the error types to remain -the same (because of our use of `and_then`). Since we chose to convert the -`Option<String>` (from `argv.nth(1)`) to a `Result<String, String>`, we must -also convert the `ParseIntError` from `arg.parse()` to a `String`. - -## The limits of combinators - -Doing IO and parsing input is a very common task, and it's one that I -personally have done a lot of in Rust. Therefore, we will use (and continue to -use) IO and various parsing routines to exemplify error handling. - -Let's start simple. We are tasked with opening a file, reading all of its -contents and converting its contents to a number. Then we multiply it by `2` -and print the output. - -Although I've tried to convince you not to use `unwrap`, it can be useful -to first write your code using `unwrap`. It allows you to focus on your problem -instead of the error handling, and it exposes the points where proper error -handling need to occur. Let's start there so we can get a handle on the code, -and then refactor it to use better error handling. - -```rust,should_panic -use std::fs::File; -use std::io::Read; -use std::path::Path; - -fn file_double<P: AsRef<Path>>(file_path: P) -> i32 { - let mut file = File::open(file_path).unwrap(); // error 1 - let mut contents = String::new(); - file.read_to_string(&mut contents).unwrap(); // error 2 - let n: i32 = contents.trim().parse().unwrap(); // error 3 - 2 * n -} - -fn main() { - let doubled = file_double("foobar"); - println!("{}", doubled); -} -``` - -(N.B. The `AsRef<Path>` is used because those are the -[same bounds used on -`std::fs::File::open`](../std/fs/struct.File.html#method.open). -This makes it ergonomic to use any kind of string as a file path.) - -There are three different errors that can occur here: - -1. A problem opening the file. -2. A problem reading data from the file. -3. A problem parsing the data as a number. - -The first two problems are described via the -[`std::io::Error`](../std/io/struct.Error.html) type. We know this -because of the return types of -[`std::fs::File::open`](../std/fs/struct.File.html#method.open) and -[`std::io::Read::read_to_string`](../std/io/trait.Read.html#method.read_to_string). -(Note that they both use the [`Result` type alias -idiom](#the-result-type-alias-idiom) described previously. If you -click on the `Result` type, you'll [see the type -alias](../std/io/type.Result.html), and consequently, the underlying -`io::Error` type.) The third problem is described by the -[`std::num::ParseIntError`](../std/num/struct.ParseIntError.html) -type. The `io::Error` type in particular is *pervasive* throughout the -standard library. You will see it again and again. - -Let's start the process of refactoring the `file_double` function. To make this -function composable with other components of the program, it should *not* panic -if any of the above error conditions are met. Effectively, this means that the -function should *return an error* if any of its operations fail. Our problem is -that the return type of `file_double` is `i32`, which does not give us any -useful way of reporting an error. Thus, we must start by changing the return -type from `i32` to something else. - -The first thing we need to decide: should we use `Option` or `Result`? We -certainly could use `Option` very easily. If any of the three errors occur, we -could simply return `None`. This will work *and it is better than panicking*, -but we can do a lot better. Instead, we should pass some detail about the error -that occurred. Since we want to express the *possibility of error*, we should -use `Result<i32, E>`. But what should `E` be? Since two *different* types of -errors can occur, we need to convert them to a common type. One such type is -`String`. Let's see how that impacts our code: - -```rust -use std::fs::File; -use std::io::Read; -use std::path::Path; - -fn file_double<P: AsRef<Path>>(file_path: P) -> Result<i32, String> { - File::open(file_path) - .map_err(|err| err.to_string()) - .and_then(|mut file| { - let mut contents = String::new(); - file.read_to_string(&mut contents) - .map_err(|err| err.to_string()) - .map(|_| contents) - }) - .and_then(|contents| { - contents.trim().parse::<i32>() - .map_err(|err| err.to_string()) - }) - .map(|n| 2 * n) -} - -fn main() { - match file_double("foobar") { - Ok(n) => println!("{}", n), - Err(err) => println!("Error: {}", err), - } -} -``` - -This code looks a bit hairy. It can take quite a bit of practice before code -like this becomes easy to write. The way we write it is by *following the -types*. As soon as we changed the return type of `file_double` to -`Result<i32, String>`, we had to start looking for the right combinators. In -this case, we only used three different combinators: `and_then`, `map` and -`map_err`. - -`and_then` is used to chain multiple computations where each computation could -return an error. After opening the file, there are two more computations that -could fail: reading from the file and parsing the contents as a number. -Correspondingly, there are two calls to `and_then`. - -`map` is used to apply a function to the `Ok(...)` value of a `Result`. For -example, the very last call to `map` multiplies the `Ok(...)` value (which is -an `i32`) by `2`. If an error had occurred before that point, this operation -would have been skipped because of how `map` is defined. - -`map_err` is the trick that makes all of this work. `map_err` is like -`map`, except it applies a function to the `Err(...)` value of a `Result`. In -this case, we want to convert all of our errors to one type: `String`. Since -both `io::Error` and `num::ParseIntError` implement `ToString`, we can call the -`to_string()` method to convert them. - -With all of that said, the code is still hairy. Mastering use of combinators is -important, but they have their limits. Let's try a different approach: early -returns. - -## Early returns - -I'd like to take the code from the previous section and rewrite it using *early -returns*. Early returns let you exit the function early. We can't return early -in `file_double` from inside another closure, so we'll need to revert back to -explicit case analysis. - -```rust -use std::fs::File; -use std::io::Read; -use std::path::Path; - -fn file_double<P: AsRef<Path>>(file_path: P) -> Result<i32, String> { - let mut file = match File::open(file_path) { - Ok(file) => file, - Err(err) => return Err(err.to_string()), - }; - let mut contents = String::new(); - if let Err(err) = file.read_to_string(&mut contents) { - return Err(err.to_string()); - } - let n: i32 = match contents.trim().parse() { - Ok(n) => n, - Err(err) => return Err(err.to_string()), - }; - Ok(2 * n) -} - -fn main() { - match file_double("foobar") { - Ok(n) => println!("{}", n), - Err(err) => println!("Error: {}", err), - } -} -``` - -Reasonable people can disagree over whether this code is better than the code -that uses combinators, but if you aren't familiar with the combinator approach, -this code looks simpler to read to me. It uses explicit case analysis with -`match` and `if let`. If an error occurs, it simply stops executing the -function and returns the error (by converting it to a string). - -Isn't this a step backwards though? Previously, we said that the key to -ergonomic error handling is reducing explicit case analysis, yet we've reverted -back to explicit case analysis here. It turns out, there are *multiple* ways to -reduce explicit case analysis. Combinators aren't the only way. - -## The `try!` macro - -A cornerstone of error handling in Rust is the `try!` macro. The `try!` macro -abstracts case analysis like combinators, but unlike combinators, it also -abstracts *control flow*. Namely, it can abstract the *early return* pattern -seen above. - -Here is a simplified definition of a `try!` macro: - -<span id="code-try-def-simple"></span> - -```rust -macro_rules! try { - ($e:expr) => (match $e { - Ok(val) => val, - Err(err) => return Err(err), - }); -} -``` - -(The [real definition](../std/macro.try.html) is a bit more -sophisticated. We will address that later.) - -Using the `try!` macro makes it very easy to simplify our last example. Since -it does the case analysis and the early return for us, we get tighter code that -is easier to read: - -```rust -use std::fs::File; -use std::io::Read; -use std::path::Path; - -fn file_double<P: AsRef<Path>>(file_path: P) -> Result<i32, String> { - let mut file = try!(File::open(file_path).map_err(|e| e.to_string())); - let mut contents = String::new(); - try!(file.read_to_string(&mut contents).map_err(|e| e.to_string())); - let n = try!(contents.trim().parse::<i32>().map_err(|e| e.to_string())); - Ok(2 * n) -} - -fn main() { - match file_double("foobar") { - Ok(n) => println!("{}", n), - Err(err) => println!("Error: {}", err), - } -} -``` - -The `map_err` calls are still necessary given -[our definition of `try!`](#code-try-def-simple). -This is because the error types still need to be converted to `String`. -The good news is that we will soon learn how to remove those `map_err` calls! -The bad news is that we will need to learn a bit more about a couple important -traits in the standard library before we can remove the `map_err` calls. - -## Defining your own error type - -Before we dive into some of the standard library error traits, I'd like to wrap -up this section by removing the use of `String` as our error type in the -previous examples. - -Using `String` as we did in our previous examples is convenient because it's -easy to convert errors to strings, or even make up your own errors as strings -on the spot. However, using `String` for your errors has some downsides. - -The first downside is that the error messages tend to clutter your -code. It's possible to define the error messages elsewhere, but unless -you're unusually disciplined, it is very tempting to embed the error -message into your code. Indeed, we did exactly this in a [previous -example](#code-error-double-string). - -The second and more important downside is that `String`s are *lossy*. That is, -if all errors are converted to strings, then the errors we pass to the caller -become completely opaque. The only reasonable thing the caller can do with a -`String` error is show it to the user. Certainly, inspecting the string to -determine the type of error is not robust. (Admittedly, this downside is far -more important inside of a library as opposed to, say, an application.) - -For example, the `io::Error` type embeds an -[`io::ErrorKind`](../std/io/enum.ErrorKind.html), -which is *structured data* that represents what went wrong during an IO -operation. This is important because you might want to react differently -depending on the error. (e.g., A `BrokenPipe` error might mean quitting your -program gracefully while a `NotFound` error might mean exiting with an error -code and showing an error to the user.) With `io::ErrorKind`, the caller can -examine the type of an error with case analysis, which is strictly superior -to trying to tease out the details of an error inside of a `String`. - -Instead of using a `String` as an error type in our previous example of reading -an integer from a file, we can define our own error type that represents errors -with *structured data*. We endeavor to not drop information from underlying -errors in case the caller wants to inspect the details. - -The ideal way to represent *one of many possibilities* is to define our own -sum type using `enum`. In our case, an error is either an `io::Error` or a -`num::ParseIntError`, so a natural definition arises: - -```rust -use std::io; -use std::num; - -// We derive `Debug` because all types should probably derive `Debug`. -// This gives us a reasonable human readable description of `CliError` values. -#[derive(Debug)] -enum CliError { - Io(io::Error), - Parse(num::ParseIntError), -} -``` - -Tweaking our code is very easy. Instead of converting errors to strings, we -simply convert them to our `CliError` type using the corresponding value -constructor: - -```rust -# #[derive(Debug)] -# enum CliError { Io(::std::io::Error), Parse(::std::num::ParseIntError) } -use std::fs::File; -use std::io::Read; -use std::path::Path; - -fn file_double<P: AsRef<Path>>(file_path: P) -> Result<i32, CliError> { - let mut file = try!(File::open(file_path).map_err(CliError::Io)); - let mut contents = String::new(); - try!(file.read_to_string(&mut contents).map_err(CliError::Io)); - let n: i32 = try!(contents.trim().parse().map_err(CliError::Parse)); - Ok(2 * n) -} - -fn main() { - match file_double("foobar") { - Ok(n) => println!("{}", n), - Err(err) => println!("Error: {:?}", err), - } -} -``` - -The only change here is switching `map_err(|e| e.to_string())` (which converts -errors to strings) to `map_err(CliError::Io)` or `map_err(CliError::Parse)`. -The *caller* gets to decide the level of detail to report to the user. In -effect, using a `String` as an error type removes choices from the caller while -using a custom `enum` error type like `CliError` gives the caller all of the -conveniences as before in addition to *structured data* describing the error. - -A rule of thumb is to define your own error type, but a `String` error type -will do in a pinch, particularly if you're writing an application. If you're -writing a library, defining your own error type should be strongly preferred so -that you don't remove choices from the caller unnecessarily. - -# Standard library traits used for error handling - -The standard library defines two integral traits for error handling: -[`std::error::Error`](../std/error/trait.Error.html) and -[`std::convert::From`](../std/convert/trait.From.html). While `Error` -is designed specifically for generically describing errors, the `From` -trait serves a more general role for converting values between two -distinct types. - -## The `Error` trait - -The `Error` trait is [defined in the standard -library](../std/error/trait.Error.html): - -```rust -use std::fmt::{Debug, Display}; - -trait Error: Debug + Display { - /// A short description of the error. - fn description(&self) -> &str; - - /// The lower level cause of this error, if any. - fn cause(&self) -> Option<&Error> { None } -} -``` - -This trait is super generic because it is meant to be implemented for *all* -types that represent errors. This will prove useful for writing composable code -as we'll see later. Otherwise, the trait allows you to do at least the -following things: - -* Obtain a `Debug` representation of the error. -* Obtain a user-facing `Display` representation of the error. -* Obtain a short description of the error (via the `description` method). -* Inspect the causal chain of an error, if one exists (via the `cause` method). - -The first two are a result of `Error` requiring impls for both `Debug` and -`Display`. The latter two are from the two methods defined on `Error`. The -power of `Error` comes from the fact that all error types impl `Error`, which -means errors can be existentially quantified as a -[trait object](../book/trait-objects.html). -This manifests as either `Box<Error>` or `&Error`. Indeed, the `cause` method -returns an `&Error`, which is itself a trait object. We'll revisit the -`Error` trait's utility as a trait object later. - -For now, it suffices to show an example implementing the `Error` trait. Let's -use the error type we defined in the -[previous section](#defining-your-own-error-type): - -```rust -use std::io; -use std::num; - -// We derive `Debug` because all types should probably derive `Debug`. -// This gives us a reasonable human readable description of `CliError` values. -#[derive(Debug)] -enum CliError { - Io(io::Error), - Parse(num::ParseIntError), -} -``` - -This particular error type represents the possibility of two types of errors -occurring: an error dealing with I/O or an error converting a string to a -number. The error could represent as many error types as you want by adding new -variants to the `enum` definition. - -Implementing `Error` is pretty straight-forward. It's mostly going to be a lot -explicit case analysis. - -```rust,ignore -use std::error; -use std::fmt; - -impl fmt::Display for CliError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - // Both underlying errors already impl `Display`, so we defer to - // their implementations. - CliError::Io(ref err) => write!(f, "IO error: {}", err), - CliError::Parse(ref err) => write!(f, "Parse error: {}", err), - } - } -} - -impl error::Error for CliError { - fn description(&self) -> &str { - // Both underlying errors already impl `Error`, so we defer to their - // implementations. - match *self { - CliError::Io(ref err) => err.description(), - CliError::Parse(ref err) => err.description(), - } - } - - fn cause(&self) -> Option<&error::Error> { - match *self { - // N.B. Both of these implicitly cast `err` from their concrete - // types (either `&io::Error` or `&num::ParseIntError`) - // to a trait object `&Error`. This works because both error types - // implement `Error`. - CliError::Io(ref err) => Some(err), - CliError::Parse(ref err) => Some(err), - } - } -} -``` - -We note that this is a very typical implementation of `Error`: match on your -different error types and satisfy the contracts defined for `description` and -`cause`. - -## The `From` trait - -The `std::convert::From` trait is -[defined in the standard -library](../std/convert/trait.From.html): - -<span id="code-from-def"></span> - -```rust -trait From<T> { - fn from(T) -> Self; -} -``` - -Deliciously simple, yes? `From` is very useful because it gives us a generic -way to talk about conversion *from* a particular type `T` to some other type -(in this case, “some other type” is the subject of the impl, or `Self`). -The crux of `From` is the -[set of implementations provided by the standard -library](../std/convert/trait.From.html). - -Here are a few simple examples demonstrating how `From` works: - -```rust -let string: String = From::from("foo"); -let bytes: Vec<u8> = From::from("foo"); -let cow: ::std::borrow::Cow<str> = From::from("foo"); -``` - -OK, so `From` is useful for converting between strings. But what about errors? -It turns out, there is one critical impl: - -```rust,ignore -impl<'a, E: Error + 'a> From<E> for Box<Error + 'a> -``` - -This impl says that for *any* type that impls `Error`, we can convert it to a -trait object `Box<Error>`. This may not seem terribly surprising, but it is -useful in a generic context. - -Remember the two errors we were dealing with previously? Specifically, -`io::Error` and `num::ParseIntError`. Since both impl `Error`, they work with -`From`: - -```rust -use std::error::Error; -use std::fs; -use std::io; -use std::num; - -// We have to jump through some hoops to actually get error values: -let io_err: io::Error = io::Error::last_os_error(); -let parse_err: num::ParseIntError = "not a number".parse::<i32>().unwrap_err(); - -// OK, here are the conversions: -let err1: Box<Error> = From::from(io_err); -let err2: Box<Error> = From::from(parse_err); -``` - -There is a really important pattern to recognize here. Both `err1` and `err2` -have the *same type*. This is because they are existentially quantified types, -or trait objects. In particular, their underlying type is *erased* from the -compiler's knowledge, so it truly sees `err1` and `err2` as exactly the same. -Additionally, we constructed `err1` and `err2` using precisely the same -function call: `From::from`. This is because `From::from` is overloaded on both -its argument and its return type. - -This pattern is important because it solves a problem we had earlier: it gives -us a way to reliably convert errors to the same type using the same function. - -Time to revisit an old friend; the `try!` macro. - -## The real `try!` macro - -Previously, we presented this definition of `try!`: - -```rust -macro_rules! try { - ($e:expr) => (match $e { - Ok(val) => val, - Err(err) => return Err(err), - }); -} -``` - -This is not its real definition. Its real definition is -[in the standard library](../std/macro.try.html): - -<span id="code-try-def"></span> - -```rust -macro_rules! try { - ($e:expr) => (match $e { - Ok(val) => val, - Err(err) => return Err(::std::convert::From::from(err)), - }); -} -``` - -There's one tiny but powerful change: the error value is passed through -`From::from`. This makes the `try!` macro a lot more powerful because it gives -you automatic type conversion for free. - -Armed with our more powerful `try!` macro, let's take a look at code we wrote -previously to read a file and convert its contents to an integer: - -```rust -use std::fs::File; -use std::io::Read; -use std::path::Path; - -fn file_double<P: AsRef<Path>>(file_path: P) -> Result<i32, String> { - let mut file = try!(File::open(file_path).map_err(|e| e.to_string())); - let mut contents = String::new(); - try!(file.read_to_string(&mut contents).map_err(|e| e.to_string())); - let n = try!(contents.trim().parse::<i32>().map_err(|e| e.to_string())); - Ok(2 * n) -} -``` - -Earlier, we promised that we could get rid of the `map_err` calls. Indeed, all -we have to do is pick a type that `From` works with. As we saw in the previous -section, `From` has an impl that lets it convert any error type into a -`Box<Error>`: - -```rust -use std::error::Error; -use std::fs::File; -use std::io::Read; -use std::path::Path; - -fn file_double<P: AsRef<Path>>(file_path: P) -> Result<i32, Box<Error>> { - let mut file = try!(File::open(file_path)); - let mut contents = String::new(); - try!(file.read_to_string(&mut contents)); - let n = try!(contents.trim().parse::<i32>()); - Ok(2 * n) -} -``` - -We are getting very close to ideal error handling. Our code has very little -overhead as a result from error handling because the `try!` macro encapsulates -three things simultaneously: - -1. Case analysis. -2. Control flow. -3. Error type conversion. - -When all three things are combined, we get code that is unencumbered by -combinators, calls to `unwrap` or case analysis. - -There's one little nit left: the `Box<Error>` type is *opaque*. If we -return a `Box<Error>` to the caller, the caller can't (easily) inspect -underlying error type. The situation is certainly better than `String` -because the caller can call methods like -[`description`](../std/error/trait.Error.html#tymethod.description) -and [`cause`](../std/error/trait.Error.html#method.cause), but the -limitation remains: `Box<Error>` is opaque. (N.B. This isn't entirely -true because Rust does have runtime reflection, which is useful in -some scenarios that are [beyond the scope of this -section](https://crates.io/crates/error).) - -It's time to revisit our custom `CliError` type and tie everything together. - -## Composing custom error types - -In the last section, we looked at the real `try!` macro and how it does -automatic type conversion for us by calling `From::from` on the error value. -In particular, we converted errors to `Box<Error>`, which works, but the type -is opaque to callers. - -To fix this, we use the same remedy that we're already familiar with: a custom -error type. Once again, here is the code that reads the contents of a file and -converts it to an integer: - -```rust -use std::fs::File; -use std::io::{self, Read}; -use std::num; -use std::path::Path; - -// We derive `Debug` because all types should probably derive `Debug`. -// This gives us a reasonable human readable description of `CliError` values. -#[derive(Debug)] -enum CliError { - Io(io::Error), - Parse(num::ParseIntError), -} - -fn file_double_verbose<P: AsRef<Path>>(file_path: P) -> Result<i32, CliError> { - let mut file = try!(File::open(file_path).map_err(CliError::Io)); - let mut contents = String::new(); - try!(file.read_to_string(&mut contents).map_err(CliError::Io)); - let n: i32 = try!(contents.trim().parse().map_err(CliError::Parse)); - Ok(2 * n) -} -``` - -Notice that we still have the calls to `map_err`. Why? Well, recall the -definitions of [`try!`](#code-try-def) and [`From`](#code-from-def). The -problem is that there is no `From` impl that allows us to convert from error -types like `io::Error` and `num::ParseIntError` to our own custom `CliError`. -Of course, it is easy to fix this! Since we defined `CliError`, we can impl -`From` with it: - -```rust -# #[derive(Debug)] -# enum CliError { Io(io::Error), Parse(num::ParseIntError) } -use std::io; -use std::num; - -impl From<io::Error> for CliError { - fn from(err: io::Error) -> CliError { - CliError::Io(err) - } -} - -impl From<num::ParseIntError> for CliError { - fn from(err: num::ParseIntError) -> CliError { - CliError::Parse(err) - } -} -``` - -All these impls are doing is teaching `From` how to create a `CliError` from -other error types. In our case, construction is as simple as invoking the -corresponding value constructor. Indeed, it is *typically* this easy. - -We can finally rewrite `file_double`: - -```rust -# use std::io; -# use std::num; -# enum CliError { Io(::std::io::Error), Parse(::std::num::ParseIntError) } -# impl From<io::Error> for CliError { -# fn from(err: io::Error) -> CliError { CliError::Io(err) } -# } -# impl From<num::ParseIntError> for CliError { -# fn from(err: num::ParseIntError) -> CliError { CliError::Parse(err) } -# } - -use std::fs::File; -use std::io::Read; -use std::path::Path; - -fn file_double<P: AsRef<Path>>(file_path: P) -> Result<i32, CliError> { - let mut file = try!(File::open(file_path)); - let mut contents = String::new(); - try!(file.read_to_string(&mut contents)); - let n: i32 = try!(contents.trim().parse()); - Ok(2 * n) -} -``` - -The only thing we did here was remove the calls to `map_err`. They are no -longer needed because the `try!` macro invokes `From::from` on the error value. -This works because we've provided `From` impls for all the error types that -could appear. - -If we modified our `file_double` function to perform some other operation, say, -convert a string to a float, then we'd need to add a new variant to our error -type: - -```rust -use std::io; -use std::num; - -enum CliError { - Io(io::Error), - ParseInt(num::ParseIntError), - ParseFloat(num::ParseFloatError), -} -``` - -And add a new `From` impl: - -```rust -# enum CliError { -# Io(::std::io::Error), -# ParseInt(num::ParseIntError), -# ParseFloat(num::ParseFloatError), -# } - -use std::num; - -impl From<num::ParseFloatError> for CliError { - fn from(err: num::ParseFloatError) -> CliError { - CliError::ParseFloat(err) - } -} -``` - -And that's it! - -## Advice for library writers - -If your library needs to report custom errors, then you should -probably define your own error type. It's up to you whether or not to -expose its representation (like -[`ErrorKind`](../std/io/enum.ErrorKind.html)) or keep it hidden (like -[`ParseIntError`](../std/num/struct.ParseIntError.html)). Regardless -of how you do it, it's usually good practice to at least provide some -information about the error beyond its `String` -representation. But certainly, this will vary depending on use cases. - -At a minimum, you should probably implement the -[`Error`](../std/error/trait.Error.html) -trait. This will give users of your library some minimum flexibility for -[composing errors](#the-real-try-macro). Implementing the `Error` trait also -means that users are guaranteed the ability to obtain a string representation -of an error (because it requires impls for both `fmt::Debug` and -`fmt::Display`). - -Beyond that, it can also be useful to provide implementations of `From` on your -error types. This allows you (the library author) and your users to -[compose more detailed errors](#composing-custom-error-types). For example, -[`csv::Error`](http://burntsushi.net/rustdoc/csv/enum.Error.html) -provides `From` impls for both `io::Error` and `byteorder::Error`. - -Finally, depending on your tastes, you may also want to define a -[`Result` type alias](#the-result-type-alias-idiom), particularly if your -library defines a single error type. This is used in the standard library -for [`io::Result`](../std/io/type.Result.html) -and [`fmt::Result`](../std/fmt/type.Result.html). - -# Case study: A program to read population data - -This section was long, and depending on your background, it might be -rather dense. While there is plenty of example code to go along with -the prose, most of it was specifically designed to be pedagogical. So, -we're going to do something new: a case study. - -For this, we're going to build up a command line program that lets you -query world population data. The objective is simple: you give it a location -and it will tell you the population. Despite the simplicity, there is a lot -that can go wrong! - -The data we'll be using comes from the [Data Science -Toolkit][11]. I've prepared some data from it for this exercise. You -can either grab the [world population data][12] (41MB gzip compressed, -145MB uncompressed) or only the [US population data][13] (2.2MB gzip -compressed, 7.2MB uncompressed). - -Up until now, we've kept the code limited to Rust's standard library. For a real -task like this though, we'll want to at least use something to parse CSV data, -parse the program arguments and decode that stuff into Rust types automatically. For that, we'll use the -[`csv`](https://crates.io/crates/csv), -and [`rustc-serialize`](https://crates.io/crates/rustc-serialize) crates. - -## Initial setup - -We're not going to spend a lot of time on setting up a project with -Cargo because it is already covered well in [the Cargo -section](getting-started.html#hello-cargo) and [Cargo's documentation][14]. - -To get started from scratch, run `cargo new --bin city-pop` and make sure your -`Cargo.toml` looks something like this: - -```text -[package] -name = "city-pop" -version = "0.1.0" -authors = ["Andrew Gallant <jamslam@gmail.com>"] - -[[bin]] -name = "city-pop" - -[dependencies] -csv = "0.*" -rustc-serialize = "0.*" -getopts = "0.*" -``` - -You should already be able to run: - -```text -cargo build --release -./target/release/city-pop -# Outputs: Hello, world! -``` - -## Argument parsing - -Let's get argument parsing out of the way. We won't go into too much -detail on Getopts, but there is [some good documentation][15] -describing it. The short story is that Getopts generates an argument -parser and a help message from a vector of options (The fact that it -is a vector is hidden behind a struct and a set of methods). Once the -parsing is done, the parser returns a struct that records matches -for defined options, and remaining "free" arguments. -From there, we can get information about the flags, for -instance, whether they were passed in, and what arguments they -had. Here's our program with the appropriate `extern crate` -statements, and the basic argument setup for Getopts: - -```rust,ignore -extern crate getopts; -extern crate rustc_serialize; - -use getopts::Options; -use std::env; - -fn print_usage(program: &str, opts: Options) { - println!("{}", opts.usage(&format!("Usage: {} [options] <data-path> <city>", program))); -} - -fn main() { - let args: Vec<String> = env::args().collect(); - let program = &args[0]; - - let mut opts = Options::new(); - opts.optflag("h", "help", "Show this usage message."); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => { m } - Err(e) => { panic!(e.to_string()) } - }; - if matches.opt_present("h") { - print_usage(&program, opts); - return; - } - let data_path = &matches.free[0]; - let city: &str = &matches.free[1]; - - // Do stuff with information. -} -``` - -First, we get a vector of the arguments passed into our program. We -then store the first one, knowing that it is our program's name. Once -that's done, we set up our argument flags, in this case a simplistic -help message flag. Once we have the argument flags set up, we use -`Options.parse` to parse the argument vector (starting from index one, -because index 0 is the program name). If this was successful, we -assign matches to the parsed object, if not, we panic. Once past that, -we test if the user passed in the help flag, and if so print the usage -message. The option help messages are constructed by Getopts, so all -we have to do to print the usage message is tell it what we want it to -print for the program name and template. If the user has not passed in -the help flag, we assign the proper variables to their corresponding -arguments. - -## Writing the logic - -We all write code differently, but error handling is usually the last thing we -want to think about. This isn't great for the overall design of a program, but -it can be useful for rapid prototyping. Because Rust forces us to be explicit -about error handling (by making us call `unwrap`), it is easy to see which -parts of our program can cause errors. - -In this case study, the logic is really simple. All we need to do is parse the -CSV data given to us and print out a field in matching rows. Let's do it. (Make -sure to add `extern crate csv;` to the top of your file.) - -```rust,ignore -use std::fs::File; - -// This struct represents the data in each row of the CSV file. -// Type based decoding absolves us of a lot of the nitty gritty error -// handling, like parsing strings as integers or floats. -#[derive(Debug, RustcDecodable)] -struct Row { - country: String, - city: String, - accent_city: String, - region: String, - - // Not every row has data for the population, latitude or longitude! - // So we express them as `Option` types, which admits the possibility of - // absence. The CSV parser will fill in the correct value for us. - population: Option<u64>, - latitude: Option<f64>, - longitude: Option<f64>, -} - -fn print_usage(program: &str, opts: Options) { - println!("{}", opts.usage(&format!("Usage: {} [options] <data-path> <city>", program))); -} - -fn main() { - let args: Vec<String> = env::args().collect(); - let program = &args[0]; - - let mut opts = Options::new(); - opts.optflag("h", "help", "Show this usage message."); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => { m } - Err(e) => { panic!(e.to_string()) } - }; - - if matches.opt_present("h") { - print_usage(&program, opts); - return; - } - - let data_path = &matches.free[0]; - let city: &str = &matches.free[1]; - - let file = File::open(data_path).unwrap(); - let mut rdr = csv::Reader::from_reader(file); - - for row in rdr.decode::<Row>() { - let row = row.unwrap(); - - if row.city == city { - println!("{}, {}: {:?}", - row.city, row.country, - row.population.expect("population count")); - } - } -} -``` - -Let's outline the errors. We can start with the obvious: the three places that -`unwrap` is called: - -1. [`File::open`](../std/fs/struct.File.html#method.open) - can return an - [`io::Error`](../std/io/struct.Error.html). -2. [`csv::Reader::decode`](http://burntsushi.net/rustdoc/csv/struct.Reader.html#method.decode) - decodes one record at a time, and - [decoding a - record](http://burntsushi.net/rustdoc/csv/struct.DecodedRecords.html) - (look at the `Item` associated type on the `Iterator` impl) - can produce a - [`csv::Error`](http://burntsushi.net/rustdoc/csv/enum.Error.html). -3. If `row.population` is `None`, then calling `expect` will panic. - -Are there any others? What if we can't find a matching city? Tools like `grep` -will return an error code, so we probably should too. So we have logic errors -specific to our problem, IO errors and CSV parsing errors. We're going to -explore two different ways to approach handling these errors. - -I'd like to start with `Box<Error>`. Later, we'll see how defining our own -error type can be useful. - -## Error handling with `Box<Error>` - -`Box<Error>` is nice because it *just works*. You don't need to define your own -error types and you don't need any `From` implementations. The downside is that -since `Box<Error>` is a trait object, it *erases the type*, which means the -compiler can no longer reason about its underlying type. - -[Previously](#the-limits-of-combinators) we started refactoring our code by -changing the type of our function from `T` to `Result<T, OurErrorType>`. In -this case, `OurErrorType` is only `Box<Error>`. But what's `T`? And can we add -a return type to `main`? - -The answer to the second question is no, we can't. That means we'll need to -write a new function. But what is `T`? The simplest thing we can do is to -return a list of matching `Row` values as a `Vec<Row>`. (Better code would -return an iterator, but that is left as an exercise to the reader.) - -Let's refactor our code into its own function, but keep the calls to `unwrap`. -Note that we opt to handle the possibility of a missing population count by -simply ignoring that row. - -```rust,ignore -use std::path::Path; - -struct Row { - // This struct remains unchanged. -} - -struct PopulationCount { - city: String, - country: String, - // This is no longer an `Option` because values of this type are only - // constructed if they have a population count. - count: u64, -} - -fn print_usage(program: &str, opts: Options) { - println!("{}", opts.usage(&format!("Usage: {} [options] <data-path> <city>", program))); -} - -fn search<P: AsRef<Path>>(file_path: P, city: &str) -> Vec<PopulationCount> { - let mut found = vec![]; - let file = File::open(file_path).unwrap(); - let mut rdr = csv::Reader::from_reader(file); - for row in rdr.decode::<Row>() { - let row = row.unwrap(); - match row.population { - None => { } // Skip it. - Some(count) => if row.city == city { - found.push(PopulationCount { - city: row.city, - country: row.country, - count: count, - }); - }, - } - } - found -} - -fn main() { - let args: Vec<String> = env::args().collect(); - let program = &args[0]; - - let mut opts = Options::new(); - opts.optflag("h", "help", "Show this usage message."); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => { m } - Err(e) => { panic!(e.to_string()) } - }; - - if matches.opt_present("h") { - print_usage(&program, opts); - return; - } - - let data_path = &matches.free[0]; - let city: &str = &matches.free[1]; - - for pop in search(data_path, city) { - println!("{}, {}: {:?}", pop.city, pop.country, pop.count); - } -} - -``` - -While we got rid of one use of `expect` (which is a nicer variant of `unwrap`), -we still should handle the absence of any search results. - -To convert this to proper error handling, we need to do the following: - -1. Change the return type of `search` to be `Result<Vec<PopulationCount>, - Box<Error>>`. -2. Use the [`try!` macro](#code-try-def) so that errors are returned to the - caller instead of panicking the program. -3. Handle the error in `main`. - -Let's try it: - -```rust,ignore -use std::error::Error; - -// The rest of the code before this is unchanged. - -fn search<P: AsRef<Path>> - (file_path: P, city: &str) - -> Result<Vec<PopulationCount>, Box<Error>> { - let mut found = vec![]; - let file = try!(File::open(file_path)); - let mut rdr = csv::Reader::from_reader(file); - for row in rdr.decode::<Row>() { - let row = try!(row); - match row.population { - None => { } // Skip it. - Some(count) => if row.city == city { - found.push(PopulationCount { - city: row.city, - country: row.country, - count: count, - }); - }, - } - } - if found.is_empty() { - Err(From::from("No matching cities with a population were found.")) - } else { - Ok(found) - } -} -``` - -Instead of `x.unwrap()`, we now have `try!(x)`. Since our function returns a -`Result<T, E>`, the `try!` macro will return early from the function if an -error occurs. - -At the end of `search` we also convert a plain string to an error type -by using the [corresponding `From` impls](../std/convert/trait.From.html): - -```rust,ignore -// We are making use of this impl in the code above, since we call `From::from` -// on a `&'static str`. -impl<'a> From<&'a str> for Box<Error> - -// But this is also useful when you need to allocate a new string for an -// error message, usually with `format!`. -impl From<String> for Box<Error> -``` - -Since `search` now returns a `Result<T, E>`, `main` should use case analysis -when calling `search`: - -```rust,ignore -... - match search(data_path, city) { - Ok(pops) => { - for pop in pops { - println!("{}, {}: {:?}", pop.city, pop.country, pop.count); - } - } - Err(err) => println!("{}", err) - } -... -``` - -Now that we've seen how to do proper error handling with `Box<Error>`, let's -try a different approach with our own custom error type. But first, let's take -a quick break from error handling and add support for reading from `stdin`. - -## Reading from stdin - -In our program, we accept a single file for input and do one pass over the -data. This means we probably should be able to accept input on stdin. But maybe -we like the current format too—so let's have both! - -Adding support for stdin is actually quite easy. There are only three things we -have to do: - -1. Tweak the program arguments so that a single parameter—the - city—can be accepted while the population data is read from stdin. -2. Modify the program so that an option `-f` can take the file, if it - is not passed into stdin. -3. Modify the `search` function to take an *optional* file path. When `None`, - it should know to read from stdin. - -First, here's the new usage: - -```rust,ignore -fn print_usage(program: &str, opts: Options) { - println!("{}", opts.usage(&format!("Usage: {} [options] <city>", program))); -} -``` -Of course we need to adapt the argument handling code: - -```rust,ignore -... - let mut opts = Options::new(); - opts.optopt("f", "file", "Choose an input file, instead of using STDIN.", "NAME"); - opts.optflag("h", "help", "Show this usage message."); - ... - let data_path = matches.opt_str("f"); - - let city = if !matches.free.is_empty() { - &matches.free[0] - } else { - print_usage(&program, opts); - return; - }; - - match search(&data_path, city) { - Ok(pops) => { - for pop in pops { - println!("{}, {}: {:?}", pop.city, pop.country, pop.count); - } - } - Err(err) => println!("{}", err) - } -... -``` - -We've made the user experience a bit nicer by showing the usage message, -instead of a panic from an out-of-bounds index, when `city`, the -remaining free argument, is not present. - -Modifying `search` is slightly trickier. The `csv` crate can build a -parser out of -[any type that implements `io::Read`](http://burntsushi.net/rustdoc/csv/struct.Reader.html#method.from_reader). -But how can we use the same code over both types? There's actually a -couple ways we could go about this. One way is to write `search` such -that it is generic on some type parameter `R` that satisfies -`io::Read`. Another way is to use trait objects: - -```rust,ignore -use std::io; - -// The rest of the code before this is unchanged. - -fn search<P: AsRef<Path>> - (file_path: &Option<P>, city: &str) - -> Result<Vec<PopulationCount>, Box<Error>> { - let mut found = vec![]; - let input: Box<io::Read> = match *file_path { - None => Box::new(io::stdin()), - Some(ref file_path) => Box::new(try!(File::open(file_path))), - }; - let mut rdr = csv::Reader::from_reader(input); - // The rest remains unchanged! -} -``` - -## Error handling with a custom type - -Previously, we learned how to -[compose errors using a custom error type](#composing-custom-error-types). -We did this by defining our error type as an `enum` and implementing `Error` -and `From`. - -Since we have three distinct errors (IO, CSV parsing and not found), let's -define an `enum` with three variants: - -```rust,ignore -#[derive(Debug)] -enum CliError { - Io(io::Error), - Csv(csv::Error), - NotFound, -} -``` - -And now for impls on `Display` and `Error`: - -```rust,ignore -use std::fmt; - -impl fmt::Display for CliError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - CliError::Io(ref err) => err.fmt(f), - CliError::Csv(ref err) => err.fmt(f), - CliError::NotFound => write!(f, "No matching cities with a \ - population were found."), - } - } -} - -impl Error for CliError { - fn description(&self) -> &str { - match *self { - CliError::Io(ref err) => err.description(), - CliError::Csv(ref err) => err.description(), - CliError::NotFound => "not found", - } - } - - fn cause(&self) -> Option<&Error> { - match *self { - CliError::Io(ref err) => Some(err), - CliError::Csv(ref err) => Some(err), - // Our custom error doesn't have an underlying cause, - // but we could modify it so that it does. - CliError::NotFound => None, - } - } -} -``` - -Before we can use our `CliError` type in our `search` function, we need to -provide a couple `From` impls. How do we know which impls to provide? Well, -we'll need to convert from both `io::Error` and `csv::Error` to `CliError`. -Those are the only external errors, so we'll only need two `From` impls for -now: - -```rust,ignore -impl From<io::Error> for CliError { - fn from(err: io::Error) -> CliError { - CliError::Io(err) - } -} - -impl From<csv::Error> for CliError { - fn from(err: csv::Error) -> CliError { - CliError::Csv(err) - } -} -``` - -The `From` impls are important because of how -[`try!` is defined](#code-try-def). In particular, if an error occurs, -`From::from` is called on the error, which in this case, will convert it to our -own error type `CliError`. - -With the `From` impls done, we only need to make two small tweaks to our -`search` function: the return type and the “not found” error. Here it is in -full: - -```rust,ignore -fn search<P: AsRef<Path>> - (file_path: &Option<P>, city: &str) - -> Result<Vec<PopulationCount>, CliError> { - let mut found = vec![]; - let input: Box<io::Read> = match *file_path { - None => Box::new(io::stdin()), - Some(ref file_path) => Box::new(try!(File::open(file_path))), - }; - let mut rdr = csv::Reader::from_reader(input); - for row in rdr.decode::<Row>() { - let row = try!(row); - match row.population { - None => { } // Skip it. - Some(count) => if row.city == city { - found.push(PopulationCount { - city: row.city, - country: row.country, - count: count, - }); - }, - } - } - if found.is_empty() { - Err(CliError::NotFound) - } else { - Ok(found) - } -} -``` - -No other changes are necessary. - -## Adding functionality - -Writing generic code is great, because generalizing stuff is cool, and -it can then be useful later. But sometimes, the juice isn't worth the -squeeze. Look at what we just did in the previous step: - -1. Defined a new error type. -2. Added impls for `Error`, `Display` and two for `From`. - -The big downside here is that our program didn't improve a whole lot. -There is quite a bit of overhead to representing errors with `enum`s, -especially in short programs like this. - -*One* useful aspect of using a custom error type like we've done here is that -the `main` function can now choose to handle errors differently. Previously, -with `Box<Error>`, it didn't have much of a choice: just print the message. -We're still doing that here, but what if we wanted to, say, add a `--quiet` -flag? The `--quiet` flag should silence any verbose output. - -Right now, if the program doesn't find a match, it will output a message saying -so. This can be a little clumsy, especially if you intend for the program to -be used in shell scripts. - -So let's start by adding the flags. Like before, we need to tweak the usage -string and add a flag to the Option variable. Once we've done that, Getopts does the rest: - -```rust,ignore -... - let mut opts = Options::new(); - opts.optopt("f", "file", "Choose an input file, instead of using STDIN.", "NAME"); - opts.optflag("h", "help", "Show this usage message."); - opts.optflag("q", "quiet", "Silences errors and warnings."); -... -``` - -Now we only need to implement our “quiet” functionality. This requires us to -tweak the case analysis in `main`: - -```rust,ignore -use std::process; -... - match search(&data_path, city) { - Err(CliError::NotFound) if matches.opt_present("q") => process::exit(1), - Err(err) => panic!("{}", err), - Ok(pops) => for pop in pops { - println!("{}, {}: {:?}", pop.city, pop.country, pop.count); - } - } -... -``` - -Certainly, we don't want to be quiet if there was an IO error or if the data -failed to parse. Therefore, we use case analysis to check if the error type is -`NotFound` *and* if `--quiet` has been enabled. If the search failed, we still -quit with an exit code (following `grep`'s convention). - -If we had stuck with `Box<Error>`, then it would be pretty tricky to implement -the `--quiet` functionality. - -This pretty much sums up our case study. From here, you should be ready to go -out into the world and write your own programs and libraries with proper error -handling. - -# The Short Story - -Since this section is long, it is useful to have a quick summary for error -handling in Rust. These are some good “rules of thumb." They are emphatically -*not* commandments. There are probably good reasons to break every one of these -heuristics! - -* If you're writing short example code that would be overburdened by error - handling, it's probably fine to use `unwrap` (whether that's - [`Result::unwrap`](../std/result/enum.Result.html#method.unwrap), - [`Option::unwrap`](../std/option/enum.Option.html#method.unwrap) - or preferably - [`Option::expect`](../std/option/enum.Option.html#method.expect)). - Consumers of your code should know to use proper error handling. (If they - don't, send them here!) -* If you're writing a quick 'n' dirty program, don't feel ashamed if you use - `unwrap`. Be warned: if it winds up in someone else's hands, don't be - surprised if they are agitated by poor error messages! -* If you're writing a quick 'n' dirty program and feel ashamed about panicking - anyway, then use either a `String` or a `Box<Error>` for your - error type. -* Otherwise, in a program, define your own error types with appropriate - [`From`](../std/convert/trait.From.html) - and - [`Error`](../std/error/trait.Error.html) - impls to make the [`try!`](../std/macro.try.html) - macro more ergonomic. -* If you're writing a library and your code can produce errors, define your own - error type and implement the - [`std::error::Error`](../std/error/trait.Error.html) - trait. Where appropriate, implement - [`From`](../std/convert/trait.From.html) to make both - your library code and the caller's code easier to write. (Because of Rust's - coherence rules, callers will not be able to impl `From` on your error type, - so your library should do it.) -* Learn the combinators defined on - [`Option`](../std/option/enum.Option.html) - and - [`Result`](../std/result/enum.Result.html). - Using them exclusively can be a bit tiring at times, but I've personally - found a healthy mix of `try!` and combinators to be quite appealing. - `and_then`, `map` and `unwrap_or` are my favorites. - -[1]: ../book/patterns.html -[2]: ../std/option/enum.Option.html#method.map -[3]: ../std/option/enum.Option.html#method.unwrap_or -[4]: ../std/option/enum.Option.html#method.unwrap_or_else -[5]: ../std/option/enum.Option.html -[6]: ../std/result/index.html -[7]: ../std/result/enum.Result.html#method.unwrap -[8]: ../std/fmt/trait.Debug.html -[9]: ../std/primitive.str.html#method.parse -[10]: ../book/associated-types.html -[11]: https://github.com/petewarden/dstkdata -[12]: http://burntsushi.net/stuff/worldcitiespop.csv.gz -[13]: http://burntsushi.net/stuff/uscitiespop.csv.gz -[14]: http://doc.crates.io/guide.html -[15]: http://doc.rust-lang.org/getopts/getopts/index.html diff --git a/src/doc/book/src/ffi.md b/src/doc/book/src/ffi.md deleted file mode 100644 index e9e2dab73eff3..0000000000000 --- a/src/doc/book/src/ffi.md +++ /dev/null @@ -1,767 +0,0 @@ -# Foreign Function Interface - -# Introduction - -This guide will use the [snappy](https://github.com/google/snappy) -compression/decompression library as an introduction to writing bindings for -foreign code. Rust is currently unable to call directly into a C++ library, but -snappy includes a C interface (documented in -[`snappy-c.h`](https://github.com/google/snappy/blob/master/snappy-c.h)). - -## A note about libc - -Many of these examples use [the `libc` crate][libc], which provides various -type definitions for C types, among other things. If you’re trying these -examples yourself, you’ll need to add `libc` to your `Cargo.toml`: - -```toml -[dependencies] -libc = "0.2.0" -``` - -[libc]: https://crates.io/crates/libc - -and add `extern crate libc;` to your crate root. - -## Calling foreign functions - -The following is a minimal example of calling a foreign function which will -compile if snappy is installed: - -```rust,no_run -# #![feature(libc)] -extern crate libc; -use libc::size_t; - -#[link(name = "snappy")] -extern { - fn snappy_max_compressed_length(source_length: size_t) -> size_t; -} - -fn main() { - let x = unsafe { snappy_max_compressed_length(100) }; - println!("max compressed length of a 100 byte buffer: {}", x); -} -``` - -The `extern` block is a list of function signatures in a foreign library, in -this case with the platform's C ABI. The `#[link(...)]` attribute is used to -instruct the linker to link against the snappy library so the symbols are -resolved. - -Foreign functions are assumed to be unsafe so calls to them need to be wrapped -with `unsafe {}` as a promise to the compiler that everything contained within -truly is safe. C libraries often expose interfaces that aren't thread-safe, and -almost any function that takes a pointer argument isn't valid for all possible -inputs since the pointer could be dangling, and raw pointers fall outside of -Rust's safe memory model. - -When declaring the argument types to a foreign function, the Rust compiler -cannot check if the declaration is correct, so specifying it correctly is part -of keeping the binding correct at runtime. - -The `extern` block can be extended to cover the entire snappy API: - -```rust,no_run -# #![feature(libc)] -extern crate libc; -use libc::{c_int, size_t}; - -#[link(name = "snappy")] -extern { - fn snappy_compress(input: *const u8, - input_length: size_t, - compressed: *mut u8, - compressed_length: *mut size_t) -> c_int; - fn snappy_uncompress(compressed: *const u8, - compressed_length: size_t, - uncompressed: *mut u8, - uncompressed_length: *mut size_t) -> c_int; - fn snappy_max_compressed_length(source_length: size_t) -> size_t; - fn snappy_uncompressed_length(compressed: *const u8, - compressed_length: size_t, - result: *mut size_t) -> c_int; - fn snappy_validate_compressed_buffer(compressed: *const u8, - compressed_length: size_t) -> c_int; -} -# fn main() {} -``` - -# Creating a safe interface - -The raw C API needs to be wrapped to provide memory safety and make use of higher-level concepts -like vectors. A library can choose to expose only the safe, high-level interface and hide the unsafe -internal details. - -Wrapping the functions which expect buffers involves using the `slice::raw` module to manipulate Rust -vectors as pointers to memory. Rust's vectors are guaranteed to be a contiguous block of memory. The -length is the number of elements currently contained, and the capacity is the total size in elements of -the allocated memory. The length is less than or equal to the capacity. - -```rust -# #![feature(libc)] -# extern crate libc; -# use libc::{c_int, size_t}; -# unsafe fn snappy_validate_compressed_buffer(_: *const u8, _: size_t) -> c_int { 0 } -# fn main() {} -pub fn validate_compressed_buffer(src: &[u8]) -> bool { - unsafe { - snappy_validate_compressed_buffer(src.as_ptr(), src.len() as size_t) == 0 - } -} -``` - -The `validate_compressed_buffer` wrapper above makes use of an `unsafe` block, but it makes the -guarantee that calling it is safe for all inputs by leaving off `unsafe` from the function -signature. - -The `snappy_compress` and `snappy_uncompress` functions are more complex, since a buffer has to be -allocated to hold the output too. - -The `snappy_max_compressed_length` function can be used to allocate a vector with the maximum -required capacity to hold the compressed output. The vector can then be passed to the -`snappy_compress` function as an output parameter. An output parameter is also passed to retrieve -the true length after compression for setting the length. - -```rust -# #![feature(libc)] -# extern crate libc; -# use libc::{size_t, c_int}; -# unsafe fn snappy_compress(a: *const u8, b: size_t, c: *mut u8, -# d: *mut size_t) -> c_int { 0 } -# unsafe fn snappy_max_compressed_length(a: size_t) -> size_t { a } -# fn main() {} -pub fn compress(src: &[u8]) -> Vec<u8> { - unsafe { - let srclen = src.len() as size_t; - let psrc = src.as_ptr(); - - let mut dstlen = snappy_max_compressed_length(srclen); - let mut dst = Vec::with_capacity(dstlen as usize); - let pdst = dst.as_mut_ptr(); - - snappy_compress(psrc, srclen, pdst, &mut dstlen); - dst.set_len(dstlen as usize); - dst - } -} -``` - -Decompression is similar, because snappy stores the uncompressed size as part of the compression -format and `snappy_uncompressed_length` will retrieve the exact buffer size required. - -```rust -# #![feature(libc)] -# extern crate libc; -# use libc::{size_t, c_int}; -# unsafe fn snappy_uncompress(compressed: *const u8, -# compressed_length: size_t, -# uncompressed: *mut u8, -# uncompressed_length: *mut size_t) -> c_int { 0 } -# unsafe fn snappy_uncompressed_length(compressed: *const u8, -# compressed_length: size_t, -# result: *mut size_t) -> c_int { 0 } -# fn main() {} -pub fn uncompress(src: &[u8]) -> Option<Vec<u8>> { - unsafe { - let srclen = src.len() as size_t; - let psrc = src.as_ptr(); - - let mut dstlen: size_t = 0; - snappy_uncompressed_length(psrc, srclen, &mut dstlen); - - let mut dst = Vec::with_capacity(dstlen as usize); - let pdst = dst.as_mut_ptr(); - - if snappy_uncompress(psrc, srclen, pdst, &mut dstlen) == 0 { - dst.set_len(dstlen as usize); - Some(dst) - } else { - None // SNAPPY_INVALID_INPUT - } - } -} -``` - -Then, we can add some tests to show how to use them. - -```rust -# #![feature(libc)] -# extern crate libc; -# use libc::{c_int, size_t}; -# unsafe fn snappy_compress(input: *const u8, -# input_length: size_t, -# compressed: *mut u8, -# compressed_length: *mut size_t) -# -> c_int { 0 } -# unsafe fn snappy_uncompress(compressed: *const u8, -# compressed_length: size_t, -# uncompressed: *mut u8, -# uncompressed_length: *mut size_t) -# -> c_int { 0 } -# unsafe fn snappy_max_compressed_length(source_length: size_t) -> size_t { 0 } -# unsafe fn snappy_uncompressed_length(compressed: *const u8, -# compressed_length: size_t, -# result: *mut size_t) -# -> c_int { 0 } -# unsafe fn snappy_validate_compressed_buffer(compressed: *const u8, -# compressed_length: size_t) -# -> c_int { 0 } -# fn main() { } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn valid() { - let d = vec![0xde, 0xad, 0xd0, 0x0d]; - let c: &[u8] = &compress(&d); - assert!(validate_compressed_buffer(c)); - assert!(uncompress(c) == Some(d)); - } - - #[test] - fn invalid() { - let d = vec![0, 0, 0, 0]; - assert!(!validate_compressed_buffer(&d)); - assert!(uncompress(&d).is_none()); - } - - #[test] - fn empty() { - let d = vec![]; - assert!(!validate_compressed_buffer(&d)); - assert!(uncompress(&d).is_none()); - let c = compress(&d); - assert!(validate_compressed_buffer(&c)); - assert!(uncompress(&c) == Some(d)); - } -} -``` - -# Destructors - -Foreign libraries often hand off ownership of resources to the calling code. -When this occurs, we must use Rust's destructors to provide safety and guarantee -the release of these resources (especially in the case of panic). - -For more about destructors, see the [Drop trait](../std/ops/trait.Drop.html). - -# Callbacks from C code to Rust functions - -Some external libraries require the usage of callbacks to report back their -current state or intermediate data to the caller. -It is possible to pass functions defined in Rust to an external library. -The requirement for this is that the callback function is marked as `extern` -with the correct calling convention to make it callable from C code. - -The callback function can then be sent through a registration call -to the C library and afterwards be invoked from there. - -A basic example is: - -Rust code: - -```rust,no_run -extern fn callback(a: i32) { - println!("I'm called from C with value {0}", a); -} - -#[link(name = "extlib")] -extern { - fn register_callback(cb: extern fn(i32)) -> i32; - fn trigger_callback(); -} - -fn main() { - unsafe { - register_callback(callback); - trigger_callback(); // Triggers the callback. - } -} -``` - -C code: - -```c -typedef void (*rust_callback)(int32_t); -rust_callback cb; - -int32_t register_callback(rust_callback callback) { - cb = callback; - return 1; -} - -void trigger_callback() { - cb(7); // Will call callback(7) in Rust. -} -``` - -In this example Rust's `main()` will call `trigger_callback()` in C, -which would, in turn, call back to `callback()` in Rust. - - -## Targeting callbacks to Rust objects - -The former example showed how a global function can be called from C code. -However it is often desired that the callback is targeted to a special -Rust object. This could be the object that represents the wrapper for the -respective C object. - -This can be achieved by passing a raw pointer to the object down to the -C library. The C library can then include the pointer to the Rust object in -the notification. This will allow the callback to unsafely access the -referenced Rust object. - -Rust code: - -```rust,no_run -#[repr(C)] -struct RustObject { - a: i32, - // Other members... -} - -extern "C" fn callback(target: *mut RustObject, a: i32) { - println!("I'm called from C with value {0}", a); - unsafe { - // Update the value in RustObject with the value received from the callback: - (*target).a = a; - } -} - -#[link(name = "extlib")] -extern { - fn register_callback(target: *mut RustObject, - cb: extern fn(*mut RustObject, i32)) -> i32; - fn trigger_callback(); -} - -fn main() { - // Create the object that will be referenced in the callback: - let mut rust_object = Box::new(RustObject { a: 5 }); - - unsafe { - register_callback(&mut *rust_object, callback); - trigger_callback(); - } -} -``` - -C code: - -```c -typedef void (*rust_callback)(void*, int32_t); -void* cb_target; -rust_callback cb; - -int32_t register_callback(void* callback_target, rust_callback callback) { - cb_target = callback_target; - cb = callback; - return 1; -} - -void trigger_callback() { - cb(cb_target, 7); // Will call callback(&rustObject, 7) in Rust. -} -``` - -## Asynchronous callbacks - -In the previously given examples the callbacks are invoked as a direct reaction -to a function call to the external C library. -The control over the current thread is switched from Rust to C to Rust for the -execution of the callback, but in the end the callback is executed on the -same thread that called the function which triggered the callback. - -Things get more complicated when the external library spawns its own threads -and invokes callbacks from there. -In these cases access to Rust data structures inside the callbacks is -especially unsafe and proper synchronization mechanisms must be used. -Besides classical synchronization mechanisms like mutexes, one possibility in -Rust is to use channels (in `std::sync::mpsc`) to forward data from the C -thread that invoked the callback into a Rust thread. - -If an asynchronous callback targets a special object in the Rust address space -it is also absolutely necessary that no more callbacks are performed by the -C library after the respective Rust object gets destroyed. -This can be achieved by unregistering the callback in the object's -destructor and designing the library in a way that guarantees that no -callback will be performed after deregistration. - -# Linking - -The `link` attribute on `extern` blocks provides the basic building block for -instructing rustc how it will link to native libraries. There are two accepted -forms of the link attribute today: - -* `#[link(name = "foo")]` -* `#[link(name = "foo", kind = "bar")]` - -In both of these cases, `foo` is the name of the native library that we're -linking to, and in the second case `bar` is the type of native library that the -compiler is linking to. There are currently three known types of native -libraries: - -* Dynamic - `#[link(name = "readline")]` -* Static - `#[link(name = "my_build_dependency", kind = "static")]` -* Frameworks - `#[link(name = "CoreFoundation", kind = "framework")]` - -Note that frameworks are only available on macOS targets. - -The different `kind` values are meant to differentiate how the native library -participates in linkage. From a linkage perspective, the Rust compiler creates -two flavors of artifacts: partial (rlib/staticlib) and final (dylib/binary). -Native dynamic library and framework dependencies are propagated to the final -artifact boundary, while static library dependencies are not propagated at -all, because the static libraries are integrated directly into the subsequent -artifact. - -A few examples of how this model can be used are: - -* A native build dependency. Sometimes some C/C++ glue is needed when writing - some Rust code, but distribution of the C/C++ code in a library format is - a burden. In this case, the code will be archived into `libfoo.a` and then the - Rust crate would declare a dependency via `#[link(name = "foo", kind = - "static")]`. - - Regardless of the flavor of output for the crate, the native static library - will be included in the output, meaning that distribution of the native static - library is not necessary. - -* A normal dynamic dependency. Common system libraries (like `readline`) are - available on a large number of systems, and often a static copy of these - libraries cannot be found. When this dependency is included in a Rust crate, - partial targets (like rlibs) will not link to the library, but when the rlib - is included in a final target (like a binary), the native library will be - linked in. - -On macOS, frameworks behave with the same semantics as a dynamic library. - -# Unsafe blocks - -Some operations, like dereferencing raw pointers or calling functions that have been marked -unsafe are only allowed inside unsafe blocks. Unsafe blocks isolate unsafety and are a promise to -the compiler that the unsafety does not leak out of the block. - -Unsafe functions, on the other hand, advertise it to the world. An unsafe function is written like -this: - -```rust -unsafe fn kaboom(ptr: *const i32) -> i32 { *ptr } -``` - -This function can only be called from an `unsafe` block or another `unsafe` function. - -# Accessing foreign globals - -Foreign APIs often export a global variable which could do something like track -global state. In order to access these variables, you declare them in `extern` -blocks with the `static` keyword: - -```rust,no_run -# #![feature(libc)] -extern crate libc; - -#[link(name = "readline")] -extern { - static rl_readline_version: libc::c_int; -} - -fn main() { - println!("You have readline version {} installed.", - unsafe { rl_readline_version as i32 }); -} -``` - -Alternatively, you may need to alter global state provided by a foreign -interface. To do this, statics can be declared with `mut` so we can mutate -them. - -```rust,no_run -# #![feature(libc)] -extern crate libc; - -use std::ffi::CString; -use std::ptr; - -#[link(name = "readline")] -extern { - static mut rl_prompt: *const libc::c_char; -} - -fn main() { - let prompt = CString::new("[my-awesome-shell] $").unwrap(); - unsafe { - rl_prompt = prompt.as_ptr(); - - println!("{:?}", rl_prompt); - - rl_prompt = ptr::null(); - } -} -``` - -Note that all interaction with a `static mut` is unsafe, both reading and -writing. Dealing with global mutable state requires a great deal of care. - -# Foreign calling conventions - -Most foreign code exposes a C ABI, and Rust uses the platform's C calling convention by default when -calling foreign functions. Some foreign functions, most notably the Windows API, use other calling -conventions. Rust provides a way to tell the compiler which convention to use: - -```rust -# #![feature(libc)] -extern crate libc; - -#[cfg(all(target_os = "win32", target_arch = "x86"))] -#[link(name = "kernel32")] -#[allow(non_snake_case)] -extern "stdcall" { - fn SetEnvironmentVariableA(n: *const u8, v: *const u8) -> libc::c_int; -} -# fn main() { } -``` - -This applies to the entire `extern` block. The list of supported ABI constraints -are: - -* `stdcall` -* `aapcs` -* `cdecl` -* `fastcall` -* `vectorcall` -This is currently hidden behind the `abi_vectorcall` gate and is subject to change. -* `Rust` -* `rust-intrinsic` -* `system` -* `C` -* `win64` -* `sysv64` - -Most of the abis in this list are self-explanatory, but the `system` abi may -seem a little odd. This constraint selects whatever the appropriate ABI is for -interoperating with the target's libraries. For example, on win32 with a x86 -architecture, this means that the abi used would be `stdcall`. On x86_64, -however, windows uses the `C` calling convention, so `C` would be used. This -means that in our previous example, we could have used `extern "system" { ... }` -to define a block for all windows systems, not only x86 ones. - -# Interoperability with foreign code - -Rust guarantees that the layout of a `struct` is compatible with the platform's -representation in C only if the `#[repr(C)]` attribute is applied to it. -`#[repr(C, packed)]` can be used to lay out struct members without padding. -`#[repr(C)]` can also be applied to an enum. - -Rust's owned boxes (`Box<T>`) use non-nullable pointers as handles which point -to the contained object. However, they should not be manually created because -they are managed by internal allocators. References can safely be assumed to be -non-nullable pointers directly to the type. However, breaking the borrow -checking or mutability rules is not guaranteed to be safe, so prefer using raw -pointers (`*`) if that's needed because the compiler can't make as many -assumptions about them. - -Vectors and strings share the same basic memory layout, and utilities are -available in the `vec` and `str` modules for working with C APIs. However, -strings are not terminated with `\0`. If you need a NUL-terminated string for -interoperability with C, you should use the `CString` type in the `std::ffi` -module. - -The [`libc` crate on crates.io][libc] includes type aliases and function -definitions for the C standard library in the `libc` module, and Rust links -against `libc` and `libm` by default. - -# Variadic functions - -In C, functions can be 'variadic', meaning they accept a variable number of arguments. This can -be achieved in Rust by specifying `...` within the argument list of a foreign function declaration: - -```no_run -extern { - fn foo(x: i32, ...); -} - -fn main() { - unsafe { - foo(10, 20, 30, 40, 50); - } -} -``` - -Normal Rust functions can *not* be variadic: - -```ignore -// This will not compile - -fn foo(x: i32, ...) { } -``` - -# The "nullable pointer optimization" - -Certain Rust types are defined to never be `null`. This includes references (`&T`, -`&mut T`), boxes (`Box<T>`), and function pointers (`extern "abi" fn()`). When -interfacing with C, pointers that might be `null` are often used, which would seem to -require some messy `transmute`s and/or unsafe code to handle conversions to/from Rust types. -However, the language provides a workaround. - -As a special case, an `enum` is eligible for the "nullable pointer optimization" if it contains -exactly two variants, one of which contains no data and the other contains a field of one of the -non-nullable types listed above. This means no extra space is required for a discriminant; rather, -the empty variant is represented by putting a `null` value into the non-nullable field. This is -called an "optimization", but unlike other optimizations it is guaranteed to apply to eligible -types. - -The most common type that takes advantage of the nullable pointer optimization is `Option<T>`, -where `None` corresponds to `null`. So `Option<extern "C" fn(c_int) -> c_int>` is a correct way -to represent a nullable function pointer using the C ABI (corresponding to the C type -`int (*)(int)`). - -Here is a contrived example. Let's say some C library has a facility for registering a -callback, which gets called in certain situations. The callback is passed a function pointer -and an integer and it is supposed to run the function with the integer as a parameter. So -we have function pointers flying across the FFI boundary in both directions. - -```rust -# #![feature(libc)] -extern crate libc; -use libc::c_int; - -# #[cfg(hidden)] -extern "C" { - /// Registers the callback. - fn register(cb: Option<extern "C" fn(Option<extern "C" fn(c_int) -> c_int>, c_int) -> c_int>); -} -# unsafe fn register(_: Option<extern "C" fn(Option<extern "C" fn(c_int) -> c_int>, -# c_int) -> c_int>) -# {} - -/// This fairly useless function receives a function pointer and an integer -/// from C, and returns the result of calling the function with the integer. -/// In case no function is provided, it squares the integer by default. -extern "C" fn apply(process: Option<extern "C" fn(c_int) -> c_int>, int: c_int) -> c_int { - match process { - Some(f) => f(int), - None => int * int - } -} - -fn main() { - unsafe { - register(Some(apply)); - } -} -``` - -And the code on the C side looks like this: - -```c -void register(void (*f)(void (*)(int), int)) { - ... -} -``` - -No `transmute` required! - -# Calling Rust code from C - -You may wish to compile Rust code in a way so that it can be called from C. This is -fairly easy, but requires a few things: - -```rust -#[no_mangle] -pub extern fn hello_rust() -> *const u8 { - "Hello, world!\0".as_ptr() -} -# fn main() {} -``` - -The `extern` makes this function adhere to the C calling convention, as -discussed above in "[Foreign Calling -Conventions](ffi.html#foreign-calling-conventions)". The `no_mangle` -attribute turns off Rust's name mangling, so that it is easier to link to. - -# FFI and panics - -It’s important to be mindful of `panic!`s when working with FFI. A `panic!` -across an FFI boundary is undefined behavior. If you’re writing code that may -panic, you should run it in a closure with [`catch_unwind()`]: - -```rust -use std::panic::catch_unwind; - -#[no_mangle] -pub extern fn oh_no() -> i32 { - let result = catch_unwind(|| { - panic!("Oops!"); - }); - match result { - Ok(_) => 0, - Err(_) => 1, - } -} - -fn main() {} -``` - -Please note that [`catch_unwind()`] will only catch unwinding panics, not -those who abort the process. See the documentation of [`catch_unwind()`] -for more information. - -[`catch_unwind()`]: ../std/panic/fn.catch_unwind.html - -# Representing opaque structs - -Sometimes, a C library wants to provide a pointer to something, but not let you -know the internal details of the thing it wants. The simplest way is to use a -`void *` argument: - -```c -void foo(void *arg); -void bar(void *arg); -``` - -We can represent this in Rust with the `c_void` type: - -```rust -# #![feature(libc)] -extern crate libc; - -extern "C" { - pub fn foo(arg: *mut libc::c_void); - pub fn bar(arg: *mut libc::c_void); -} -# fn main() {} -``` - -This is a perfectly valid way of handling the situation. However, we can do a bit -better. To solve this, some C libraries will instead create a `struct`, where -the details and memory layout of the struct are private. This gives some amount -of type safety. These structures are called ‘opaque’. Here’s an example, in C: - -```c -struct Foo; /* Foo is a structure, but its contents are not part of the public interface */ -struct Bar; -void foo(struct Foo *arg); -void bar(struct Bar *arg); -``` - -To do this in Rust, let’s create our own opaque types with `enum`: - -```rust -pub enum Foo {} -pub enum Bar {} - -extern "C" { - pub fn foo(arg: *mut Foo); - pub fn bar(arg: *mut Bar); -} -# fn main() {} -``` - -By using an `enum` with no variants, we create an opaque type that we can’t -instantiate, as it has no variants. But because our `Foo` and `Bar` types are -different, we’ll get type safety between the two of them, so we cannot -accidentally pass a pointer to `Foo` to `bar()`. diff --git a/src/doc/book/src/functions.md b/src/doc/book/src/functions.md deleted file mode 100644 index 96c8e9f5d6834..0000000000000 --- a/src/doc/book/src/functions.md +++ /dev/null @@ -1,336 +0,0 @@ -# Functions - -Every Rust program has at least one function, the `main` function: - -```rust -fn main() { -} -``` - -This is the simplest possible function declaration. As we mentioned before, -`fn` says ‘this is a function’, followed by the name, some parentheses because -this function takes no arguments, and then some curly braces to indicate the -body. Here’s a function named `foo`: - -```rust -fn foo() { -} -``` - -So, what about taking arguments? Here’s a function that prints a number: - -```rust -fn print_number(x: i32) { - println!("x is: {}", x); -} -``` - -Here’s a complete program that uses `print_number`: - -```rust -fn main() { - print_number(5); -} - -fn print_number(x: i32) { - println!("x is: {}", x); -} -``` - -As you can see, function arguments work very similar to `let` declarations: -you add a type to the argument name, after a colon. - -Here’s a complete program that adds two numbers together and prints them: - -```rust -fn main() { - print_sum(5, 6); -} - -fn print_sum(x: i32, y: i32) { - println!("sum is: {}", x + y); -} -``` - -You separate arguments with a comma, both when you call the function, as well -as when you declare it. - -Unlike `let`, you _must_ declare the types of function arguments. This does -not work: - -```rust,ignore -fn print_sum(x, y) { - println!("sum is: {}", x + y); -} -``` - -You get this error: - -```text -expected one of `!`, `:`, or `@`, found `)` -fn print_sum(x, y) { -``` - -This is a deliberate design decision. While full-program inference is possible, -languages which have it, like Haskell, often suggest that documenting your -types explicitly is a best-practice. We agree that forcing functions to declare -types while allowing for inference inside of function bodies is a wonderful -sweet spot between full inference and no inference. - -What about returning a value? Here’s a function that adds one to an integer: - -```rust -fn add_one(x: i32) -> i32 { - x + 1 -} -``` - -Rust functions return exactly one value, and you declare the type after an -‘arrow’, which is a dash (`-`) followed by a greater-than sign (`>`). The last -line of a function determines what it returns. You’ll note the lack of a -semicolon here. If we added it in: - -```rust,ignore -fn add_one(x: i32) -> i32 { - x + 1; -} -``` - -We would get an error: - -```text -error: not all control paths return a value -fn add_one(x: i32) -> i32 { - x + 1; -} - -help: consider removing this semicolon: - x + 1; - ^ -``` - -This reveals two interesting things about Rust: it is an expression-based -language, and semicolons are different from semicolons in other ‘curly brace -and semicolon’-based languages. These two things are related. - -## Expressions vs. Statements - -Rust is primarily an expression-based language. There are only two kinds of -statements, and everything else is an expression. - -So what's the difference? Expressions return a value, and statements do not. -That’s why we end up with ‘not all control paths return a value’ here: the -statement `x + 1;` doesn’t return a value. There are two kinds of statements in -Rust: ‘declaration statements’ and ‘expression statements’. Everything else is -an expression. Let’s talk about declaration statements first. - -In some languages, variable bindings can be written as expressions, not -statements. Like Ruby: - -```ruby -x = y = 5 -``` - -In Rust, however, using `let` to introduce a binding is _not_ an expression. The -following will produce a compile-time error: - -```rust,ignore -let x = (let y = 5); // Expected identifier, found keyword `let`. -``` - -The compiler is telling us here that it was expecting to see the beginning of -an expression, and a `let` can only begin a statement, not an expression. - -Note that assigning to an already-bound variable (e.g. `y = 5`) is still an -expression, although its value is not particularly useful. Unlike other -languages where an assignment evaluates to the assigned value (e.g. `5` in the -previous example), in Rust the value of an assignment is an empty tuple `()` -because the assigned value can have [only one owner](ownership.html), and any -other returned value would be too surprising: - -```rust -let mut y = 5; - -let x = (y = 6); // `x` has the value `()`, not `6`. -``` - -The second kind of statement in Rust is the *expression statement*. Its -purpose is to turn any expression into a statement. In practical terms, Rust's -grammar expects statements to follow other statements. This means that you use -semicolons to separate expressions from each other. This means that Rust -looks a lot like most other languages that require you to use semicolons -at the end of every line, and you will see semicolons at the end of almost -every line of Rust code you see. - -What is this exception that makes us say "almost"? You saw it already, in this -code: - -```rust -fn add_one(x: i32) -> i32 { - x + 1 -} -``` - -Our function claims to return an `i32`, but with a semicolon, it would return -`()` instead. Rust realizes this probably isn’t what we want, and suggests -removing the semicolon in the error we saw before. - -## Early returns - -But what about early returns? Rust does have a keyword for that, `return`: - -```rust -fn foo(x: i32) -> i32 { - return x; - - // We never run this code! - x + 1 -} -``` - -Using a `return` as the last line of a function works, but is considered poor -style: - -```rust -fn foo(x: i32) -> i32 { - return x + 1; -} -``` - -The previous definition without `return` may look a bit strange if you haven’t -worked in an expression-based language before, but it becomes intuitive over -time. - -## Diverging functions - -Rust has some special syntax for ‘diverging functions’, which are functions that -do not return: - -```rust -fn diverges() -> ! { - panic!("This function never returns!"); -} -``` - -`panic!` is a macro, similar to `println!()` that we’ve already seen. Unlike -`println!()`, `panic!()` causes the current thread of execution to crash with -the given message. Because this function will cause a crash, it will never -return, and so it has the type ‘`!`’, which is read ‘diverges’. - -If you add a main function that calls `diverges()` and run it, you’ll get -some output that looks like this: - -```text -thread ‘main’ panicked at ‘This function never returns!’, hello.rs:2 -``` - -If you want more information, you can get a backtrace by setting the -`RUST_BACKTRACE` environment variable: - -```text -$ RUST_BACKTRACE=1 ./diverges -thread 'main' panicked at 'This function never returns!', hello.rs:2 -Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. -stack backtrace: - hello::diverges - at ./hello.rs:2 - hello::main - at ./hello.rs:6 -``` - -If you want the complete backtrace and filenames: - -```text -$ RUST_BACKTRACE=full ./diverges -thread 'main' panicked at 'This function never returns!', hello.rs:2 -stack backtrace: - 1: 0x7f402773a829 - sys::backtrace::write::h0942de78b6c02817K8r - 2: 0x7f402773d7fc - panicking::on_panic::h3f23f9d0b5f4c91bu9w - 3: 0x7f402773960e - rt::unwind::begin_unwind_inner::h2844b8c5e81e79558Bw - 4: 0x7f4027738893 - rt::unwind::begin_unwind::h4375279447423903650 - 5: 0x7f4027738809 - diverges::h2266b4c4b850236beaa - 6: 0x7f40277389e5 - main::h19bb1149c2f00ecfBaa - 7: 0x7f402773f514 - rt::unwind::try::try_fn::h13186883479104382231 - 8: 0x7f402773d1d8 - __rust_try - 9: 0x7f402773f201 - rt::lang_start::ha172a3ce74bb453aK5w - 10: 0x7f4027738a19 - main - 11: 0x7f402694ab44 - __libc_start_main - 12: 0x7f40277386c8 - <unknown> - 13: 0x0 - <unknown> -``` - -If you need to override an already set `RUST_BACKTRACE`, -in cases when you cannot just unset the variable, -then set it to `0` to avoid getting a backtrace. -Any other value (even no value at all) turns on backtrace. - -```text -$ export RUST_BACKTRACE=1 -... -$ RUST_BACKTRACE=0 ./diverges -thread 'main' panicked at 'This function never returns!', hello.rs:2 -note: Run with `RUST_BACKTRACE=1` for a backtrace. -``` - -`RUST_BACKTRACE` also works with Cargo’s `run` command: - -```text -$ RUST_BACKTRACE=full cargo run - Running `target/debug/diverges` -thread 'main' panicked at 'This function never returns!', hello.rs:2 -stack backtrace: - 1: 0x7f402773a829 - sys::backtrace::write::h0942de78b6c02817K8r - 2: 0x7f402773d7fc - panicking::on_panic::h3f23f9d0b5f4c91bu9w - 3: 0x7f402773960e - rt::unwind::begin_unwind_inner::h2844b8c5e81e79558Bw - 4: 0x7f4027738893 - rt::unwind::begin_unwind::h4375279447423903650 - 5: 0x7f4027738809 - diverges::h2266b4c4b850236beaa - 6: 0x7f40277389e5 - main::h19bb1149c2f00ecfBaa - 7: 0x7f402773f514 - rt::unwind::try::try_fn::h13186883479104382231 - 8: 0x7f402773d1d8 - __rust_try - 9: 0x7f402773f201 - rt::lang_start::ha172a3ce74bb453aK5w - 10: 0x7f4027738a19 - main - 11: 0x7f402694ab44 - __libc_start_main - 12: 0x7f40277386c8 - <unknown> - 13: 0x0 - <unknown> -``` - -A diverging function can be used as any type: - -```rust,should_panic -# fn diverges() -> ! { -# panic!("This function never returns!"); -# } -let x: i32 = diverges(); -let x: String = diverges(); -``` - -## Function pointers - -We can also create variable bindings which point to functions: - -```rust -let f: fn(i32) -> i32; -``` - -`f` is a variable binding which points to a function that takes an `i32` as -an argument and returns an `i32`. For example: - -```rust -fn plus_one(i: i32) -> i32 { - i + 1 -} - -// Without type inference: -let f: fn(i32) -> i32 = plus_one; - -// With type inference: -let f = plus_one; -``` - -We can then use `f` to call the function: - -```rust -# fn plus_one(i: i32) -> i32 { i + 1 } -# let f = plus_one; -let six = f(5); -``` diff --git a/src/doc/book/src/generics.md b/src/doc/book/src/generics.md deleted file mode 100644 index d02cd776d00e3..0000000000000 --- a/src/doc/book/src/generics.md +++ /dev/null @@ -1,190 +0,0 @@ -# Generics - -Sometimes, when writing a function or data type, we may want it to work for -multiple types of arguments. In Rust, we can do this with generics. -Generics are called ‘parametric polymorphism’ in type theory, -which means that they are types or functions that have multiple forms (‘poly’ -is multiple, ‘morph’ is form) over a given parameter (‘parametric’). - -Anyway, enough type theory, let’s check out some generic code. Rust’s -standard library provides a type, `Option<T>`, that’s generic: - -```rust -enum Option<T> { - Some(T), - None, -} -``` - -The `<T>` part, which you’ve seen a few times before, indicates that this is -a generic data type. Inside the declaration of our `enum`, wherever we see a `T`, -we substitute that type for the same type used in the generic. Here’s an -example of using `Option<T>`, with some extra type annotations: - -```rust -let x: Option<i32> = Some(5); -``` - -In the type declaration, we say `Option<i32>`. Note how similar this looks to -`Option<T>`. So, in this particular `Option`, `T` has the value of `i32`. On -the right-hand side of the binding, we make a `Some(T)`, where `T` is `5`. -Since that’s an `i32`, the two sides match, and Rust is happy. If they didn’t -match, we’d get an error: - -```rust,ignore -let x: Option<f64> = Some(5); -// error: mismatched types: expected `core::option::Option<f64>`, -// found `core::option::Option<_>` (expected f64 but found integral variable) -``` - -That doesn’t mean we can’t make `Option<T>`s that hold an `f64`! They have -to match up: - -```rust -let x: Option<i32> = Some(5); -let y: Option<f64> = Some(5.0f64); -``` - -This is just fine. One definition, multiple uses. - -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>`: - -```rust -enum Result<T, E> { - Ok(T), - Err(E), -} -``` - -This type is generic over _two_ types: `T` and `E`. By the way, the capital letters -can be any letter you’d like. We could define `Result<T, E>` as: - -```rust -enum Result<A, Z> { - Ok(A), - Err(Z), -} -``` - -if we wanted to. Convention says that the first generic parameter should be -`T`, for ‘type’, and that we use `E` for ‘error’. Rust doesn’t care, however. - -The `Result<T, E>` type is intended to be used to return the result of a -computation, and to have the ability to return an error if it didn’t work out. - -## Generic functions - -We can write functions that take generic types with a similar syntax: - -```rust -fn takes_anything<T>(x: T) { - // Do something with `x`. -} -``` - -The syntax has two parts: the `<T>` says “this function is generic over one -type, `T`”, and the `x: T` says “x has the type `T`.” - -Multiple arguments can have the same generic type: - -```rust -fn takes_two_of_the_same_things<T>(x: T, y: T) { - // ... -} -``` - -We could write a version that takes multiple types: - -```rust -fn takes_two_things<T, U>(x: T, y: U) { - // ... -} -``` - -## Generic structs - -You can store a generic type in a `struct` as well: - -```rust -struct Point<T> { - x: T, - y: T, -} - -let int_origin = Point { x: 0, y: 0 }; -let float_origin = Point { x: 0.0, y: 0.0 }; -``` - -Similar to functions, the `<T>` is where we declare the generic parameters, -and we then use `x: T` in the type declaration, too. - -When you want to add an implementation for the generic `struct`, you -declare the type parameter after the `impl`: - -```rust -# struct Point<T> { -# x: T, -# y: T, -# } -# -impl<T> Point<T> { - fn swap(&mut self) { - std::mem::swap(&mut self.x, &mut self.y); - } -} -``` - -So far you’ve seen generics that take absolutely any type. These are useful in -many cases: you’ve already seen `Option<T>`, and later you’ll meet universal -container types like [`Vec<T>`][Vec]. On the other hand, often you want to -trade that flexibility for increased expressive power. Read about [trait -bounds][traits] to see why and how. - -## Resolving ambiguities - -Most of the time when generics are involved, the compiler can infer the -generic parameters automatically: - -```rust -// v must be a Vec<T> but we don't know what T is yet -let mut v = Vec::new(); -// v just got a bool value, so T must be bool! -v.push(true); -// Debug-print v -println!("{:?}", v); -``` - -Sometimes though, the compiler needs a little help. For example, had we -omitted the last line, we would get a compile error: - -```rust,ignore -let v = Vec::new(); -// ^^^^^^^^ cannot infer type for `T` -// -// note: type annotations or generic parameter binding required -println!("{:?}", v); -``` - -We can solve this using either a type annotation: - -```rust -let v: Vec<bool> = Vec::new(); -println!("{:?}", v); -``` - -or by binding the generic parameter `T` via the so-called -[‘turbofish’][turbofish] `::<>` syntax: - -```rust -let v = Vec::<bool>::new(); -println!("{:?}", v); -``` - -The second approach is useful in situations where we don’t want to bind the -result to a variable. It can also be used to bind generic parameters in -functions or methods. See [Iterators § Consumers](iterators.html#consumers) -for an example. - -[traits]: traits.html -[Vec]: ../std/vec/struct.Vec.html -[turbofish]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.collect diff --git a/src/doc/book/src/getting-started.md b/src/doc/book/src/getting-started.md deleted file mode 100644 index 06ea24fef3c1d..0000000000000 --- a/src/doc/book/src/getting-started.md +++ /dev/null @@ -1,550 +0,0 @@ -# Getting Started - -This first chapter of the book will get us going with Rust and its tooling. -First, we’ll install Rust. Then, the classic ‘Hello World’ program. Finally, -we’ll talk about Cargo, Rust’s build system and package manager. - -We’ll be showing off a number of commands using a terminal, and those lines all -start with `$`. You don't need to type in the `$`s, they are there to indicate -the start of each command. We’ll see many tutorials and examples around the web -that follow this convention: `$` for commands run as our regular user, and `#` -for commands we should be running as an administrator. - -# Installing Rust - -The first step to using Rust is to install it. Generally speaking, you’ll need -an Internet connection to run the commands in this section, as we’ll be -downloading Rust from the Internet. - -The Rust compiler runs on, and compiles to, a great number of platforms, but is -best supported on Linux, Mac, and Windows, on the x86 and x86-64 CPU -architecture. There are official builds of the Rust compiler and standard -library for these platforms and more. [For full details on Rust platform support -see the website][platform-support]. - -[platform-support]: https://forge.rust-lang.org/platform-support.html - -## Installing Rust - -All you need to do on Unix systems like Linux and macOS is open a -terminal and type this: - -```bash -$ curl https://sh.rustup.rs -sSf | sh -``` - -It will download a script, and start the installation. If everything -goes well, you’ll see this appear: - -```text -Rust is installed now. Great! -``` - -Installing on Windows is nearly as easy: download and run -[rustup-init.exe]. It will start the installation in a console and -present the above message on success. - -For other installation options and information, visit the [install] -page of the Rust website. - -[rustup-init.exe]: https://win.rustup.rs -[install]: https://www.rust-lang.org/install.html - -## Uninstalling - -Uninstalling Rust is as easy as installing it: - -```bash -$ rustup self uninstall -``` - -## Troubleshooting - -If we've got Rust installed, we can open up a shell, and type this: - -```bash -$ rustc --version -``` - -You should see the version number, commit hash, and commit date. - -If you do, Rust has been installed successfully! Congrats! - -If you don't, that probably means that the `PATH` environment variable -doesn't include Cargo's binary directory, `~/.cargo/bin` on Unix, or -`%USERPROFILE%\.cargo\bin` on Windows. This is the directory where -Rust development tools live, and most Rust developers keep it in their -`PATH` environment variable, which makes it possible to run `rustc` on -the command line. Due to differences in operating systems, command -shells, and bugs in installation, you may need to restart your shell, -log out of the system, or configure `PATH` manually as appropriate for -your operating environment. - -Rust does not do its own linking, and so you’ll need to have a linker -installed. Doing so will depend on your specific system. For -Linux-based systems, Rust will attempt to call `cc` for linking. On -`windows-msvc` (Rust built on Windows with Microsoft Visual Studio), -this depends on having [Microsoft Visual C++ Build Tools][msvbt] -installed. These do not need to be in `%PATH%` as `rustc` will find -them automatically. In general, if you have your linker in a -non-traditional location you can call `rustc -linker=/path/to/cc`, where `/path/to/cc` should point to your linker path. - -[msvbt]: http://landinghub.visualstudio.com/visual-cpp-build-tools - -If you are still stuck, there are a number of places where we can get -help. The easiest is -[the #rust-beginners IRC channel on irc.mozilla.org][irc-beginners] -and for general discussion -[the #rust IRC channel on irc.mozilla.org][irc], which we -can access through [Mibbit][mibbit]. Then we'll be chatting with other -Rustaceans (a silly nickname we call ourselves) who can help us out. Other great -resources include [the user’s forum][users] and [Stack Overflow][stackoverflow]. - -[irc-beginners]: irc://irc.mozilla.org/#rust-beginners -[irc]: irc://irc.mozilla.org/#rust -[mibbit]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust-beginners,%23rust -[users]: https://users.rust-lang.org/ -[stackoverflow]: http://stackoverflow.com/questions/tagged/rust - -This installer also installs a copy of the documentation locally, so we can -read it offline. It's only a `rustup doc` away! - -# Hello, world! - -Now that you have Rust installed, we'll help you write your first Rust program. -It's traditional when learning a new language to write a little program to -print the text “Hello, world!” to the screen, and in this section, we'll follow -that tradition. - -The nice thing about starting with such a simple program is that you can -quickly verify that your compiler is installed, and that it's working properly. -Printing information to the screen is also a pretty common thing to do, so -practicing it early on is good. - -> Note: This book assumes basic familiarity with the command line. Rust itself -> makes no specific demands about your editing, tooling, or where your code -> lives, so if you prefer an IDE to the command line, that's an option. You may -> want to check out [SolidOak], which was built specifically with Rust in mind. -> There are a number of extensions in development by the community, and the -> Rust team ships plugins for [various editors]. Configuring your editor or -> IDE is out of the scope of this tutorial, so check the documentation for your -> specific setup. - -[SolidOak]: https://github.com/oakes/SolidOak -[various editors]: https://github.com/rust-lang/rust/blob/master/src/etc/CONFIGS.md - -## Creating a Project File - -First, make a file to put your Rust code in. Rust doesn't care where your code -lives, but for this book, I suggest making a *projects* directory in your home -directory, and keeping all your projects there. Open a terminal and enter the -following commands to make a directory for this particular project: - -```bash -$ mkdir ~/projects -$ cd ~/projects -$ mkdir hello_world -$ cd hello_world -``` - -> Note: If you’re on Windows and not using PowerShell, the `~` may not work. -> Consult the documentation for your shell for more details. - -## Writing and Running a Rust Program - -We need to create a source file for our Rust program. Rust files always end -in a *.rs* extension. If you are using more than one word in your filename, -use an underscore to separate them; for example, you would use -*my_program.rs* rather than *myprogram.rs*. - -Now, make a new file and call it *main.rs*. Open the file and type -the following code: - -```rust -fn main() { - println!("Hello, world!"); -} -``` - -Save the file, and go back to your terminal window. On Linux or macOS, enter the -following commands: - -```bash -$ rustc main.rs -$ ./main -Hello, world! -``` - -In Windows, replace `main` with `main.exe`. Regardless of your operating -system, you should see the string `Hello, world!` print to the terminal. If you -did, then congratulations! You've officially written a Rust program. That makes -you a Rust programmer! Welcome. - -## Anatomy of a Rust Program - -Now, let’s go over what just happened in your "Hello, world!" program in -detail. Here's the first piece of the puzzle: - -```rust -fn main() { - -} -``` - -These lines define a *function* in Rust. The `main` function is special: it's -the beginning of every Rust program. The first line says, “I’m declaring a -function named `main` that takes no arguments and returns nothing.” If there -were arguments, they would go inside the parentheses (`(` and `)`), and because -we aren’t returning anything from this function, we can omit the return type -entirely. - -Also note that the function body is wrapped in curly braces (`{` and `}`). Rust -requires these around all function bodies. It's considered good style to put -the opening curly brace on the same line as the function declaration, with one -space in between. - -Inside the `main()` function: - -```rust - println!("Hello, world!"); -``` - -This line does all of the work in this little program: it prints text to the -screen. There are a number of details that are important here. The first is -that it’s indented with four spaces, not tabs. - -The second important part is the `println!()` line. This is calling a Rust -*[macro]*, which is how metaprogramming is done in Rust. If it were calling a -function instead, it would look like this: `println()` (without the !). We'll -discuss Rust macros in more detail later, but for now you only need to -know that when you see a `!` that means that you’re calling a macro instead of -a normal function. - - -[macro]: macros.html - -Next is `"Hello, world!"` which is a *string*. Strings are a surprisingly -complicated topic in a systems programming language, and this is a *[statically -allocated]* string. We pass this string as an argument to `println!`, which -prints the string to the screen. Easy enough! - -[statically allocated]: the-stack-and-the-heap.html - -The line ends with a semicolon (`;`). Rust is an *[expression-oriented -language]*, which means that most things are expressions, rather than -statements. The `;` indicates that this expression is over, and the next one is -ready to begin. Most lines of Rust code end with a `;`. - -[expression-oriented language]: glossary.html#expression-oriented-language - -## Compiling and Running Are Separate Steps - -In "Writing and Running a Rust Program", we showed you how to run a newly -created program. We'll break that process down and examine each step now. - -Before running a Rust program, you have to compile it. You can use the Rust -compiler by entering the `rustc` command and passing it the name of your source -file, like this: - -```bash -$ rustc main.rs -``` - -If you come from a C or C++ background, you'll notice that this is similar to -`gcc` or `clang`. After compiling successfully, Rust should output a binary -executable, which you can see on Linux or macOS by entering the `ls` command in -your shell as follows: - -```bash -$ ls -main main.rs -``` - -On Windows, you'd enter: - -```bash -$ dir -main.exe -main.rs -``` - -This shows we have two files: the source code, with an `.rs` extension, and the -executable (`main.exe` on Windows, `main` everywhere else). All that's left to -do from here is run the `main` or `main.exe` file, like this: - -```bash -$ ./main # or .\main.exe on Windows -``` - -If *main.rs* were your "Hello, world!" program, this would print `Hello, -world!` to your terminal. - -If you come from a dynamic language like Ruby, Python, or JavaScript, you may -not be used to compiling and running a program being separate steps. Rust is an -*ahead-of-time compiled* language, which means that you can compile a program, -give it to someone else, and they can run it even without Rust installed. If -you give someone a `.rb` or `.py` or `.js` file, on the other hand, they need -to have a Ruby, Python, or JavaScript implementation installed (respectively), -but you only need one command to both compile and run your program. Everything -is a tradeoff in language design. - -Just compiling with `rustc` is fine for simple programs, but as your project -grows, you'll want to be able to manage all of the options your project has, -and make it easy to share your code with other people and projects. Next, I'll -introduce you to a tool called Cargo, which will help you write real-world Rust -programs. - -# Hello, Cargo! - -Cargo is Rust’s build system and package manager, and Rustaceans use Cargo to -manage their Rust projects. Cargo manages three things: building your code, -downloading the libraries your code depends on, and building those libraries. -We call libraries your code needs ‘dependencies’ since your code depends on -them. - -The simplest Rust programs don’t have any dependencies, so right now, you'd -only use the first part of its functionality. As you write more complex Rust -programs, you’ll want to add dependencies, and if you start off using Cargo, -that will be a lot easier to do. - -As the vast, vast majority of Rust projects use Cargo, we will assume that -you’re using it for the rest of the book. Cargo comes installed with Rust -itself, if you used the official installers. If you installed Rust through some -other means, you can check if you have Cargo installed by typing: - -```bash -$ cargo --version -``` - -Into a terminal. If you see a version number, great! If you see an error like -‘`command not found`’, then you should look at the documentation for the system -in which you installed Rust, to determine if Cargo is separate. - -## Converting to Cargo - -Let’s convert the Hello World program to Cargo. To Cargo-fy a project, you need -to do three things: - -1. Put your source file in the right directory. -2. Get rid of the old executable (`main.exe` on Windows, `main` everywhere - else). -3. Make a Cargo configuration file. - -Let's get started! - -### Creating a Source Directory and Removing the Old Executable - -First, go back to your terminal, move to your *hello_world* directory, and -enter the following commands: - -```bash -$ mkdir src -$ mv main.rs src/main.rs # or 'move main.rs src/main.rs' on Windows -$ rm main # or 'del main.exe' on Windows -``` - -Cargo expects your source files to live inside a *src* directory, so do that -first. This leaves the top-level project directory (in this case, -*hello_world*) for READMEs, license information, and anything else not related -to your code. In this way, using Cargo helps you keep your projects nice and -tidy. There's a place for everything, and everything is in its place. - -Now, move *main.rs* into the *src* directory, and delete the compiled file you -created with `rustc`. As usual, replace `main` with `main.exe` if you're on -Windows. - -This example retains `main.rs` as the source filename because it's creating an -executable. If you wanted to make a library instead, you'd name the file -`lib.rs`. This convention is used by Cargo to successfully compile your -projects, but it can be overridden if you wish. - -### Creating a Configuration File - -Next, create a new file inside your *hello_world* directory, and call it -`Cargo.toml`. - -Make sure to capitalize the `C` in `Cargo.toml`, or Cargo won't know what to do -with the configuration file. - -This file is in the *[TOML]* (Tom's Obvious, Minimal Language) format. TOML is -similar to INI, but has some extra goodies, and is used as Cargo’s -configuration format. - -[TOML]: https://github.com/toml-lang/toml - -Inside this file, type the following information: - -```toml -[package] - -name = "hello_world" -version = "0.0.1" -authors = [ "Your name <you@example.com>" ] -``` - -The first line, `[package]`, indicates that the following statements are -configuring a package. As we add more information to this file, we’ll add other -sections, but for now, we only have the package configuration. - -The other three lines set the three bits of configuration that Cargo needs to -know to compile your program: its name, what version it is, and who wrote it. - -Once you've added this information to the *Cargo.toml* file, save it to finish -creating the configuration file. - -## Building and Running a Cargo Project - -With your *Cargo.toml* file in place in your project's root directory, you -should be ready to build and run your Hello World program! To do so, enter the -following commands: - -```bash -$ cargo build - Compiling hello_world v0.0.1 (file:///home/yourname/projects/hello_world) -$ ./target/debug/hello_world -Hello, world! -``` - -Bam! If all goes well, `Hello, world!` should print to the terminal once more. - -You just built a project with `cargo build` and ran it with -`./target/debug/hello_world`, but you can actually do both in one step with -`cargo run` as follows: - -```bash -$ cargo run - Running `target/debug/hello_world` -Hello, world! -``` - -The `run` command comes in handy when you need to rapidly iterate on a -project. - -Notice that this example didn’t re-build the project. Cargo figured out that -the file hasn’t changed, and so it just ran the binary. If you'd modified your -source code, Cargo would have rebuilt the project before running it, and you -would have seen something like this: - -```bash -$ cargo run - Compiling hello_world v0.0.1 (file:///home/yourname/projects/hello_world) - Running `target/debug/hello_world` -Hello, world! -``` - -Cargo checks to see if any of your project’s files have been modified, and only -rebuilds your project if they’ve changed since the last time you built it. - -With simple projects, Cargo doesn't bring a whole lot over just using `rustc`, -but it will become useful in the future. This is especially true when you start -using crates; these are synonymous with a ‘library’ or ‘package’ in other -programming languages. For complex projects composed of multiple crates, it’s -much easier to let Cargo coordinate the build. Using Cargo, you can run `cargo -build`, and it should work the right way. - -### Building for Release - -When your project is ready for release, you can use `cargo build ---release` to compile your project with optimizations. These optimizations make -your Rust code run faster, but turning them on makes your program take longer -to compile. This is why there are two different profiles, one for development, -and one for building the final program you’ll give to a user. - -### What Is That `Cargo.lock`? - -Running `cargo build` also causes Cargo to create a new file called -*Cargo.lock*, which looks like this: - -```toml -[root] -name = "hello_world" -version = "0.0.1" -``` - -Cargo uses the *Cargo.lock* file to keep track of dependencies in your -application. This is the Hello World project's *Cargo.lock* file. This project -doesn't have dependencies, so the file is a bit sparse. Realistically, you -won't ever need to touch this file yourself; just let Cargo handle it. - -That’s it! If you've been following along, you should have successfully built -`hello_world` with Cargo. - -Even though the project is simple, it now uses much of the real tooling you’ll -use for the rest of your Rust career. In fact, you can expect to start -virtually all Rust projects with some variation on the following commands: - -```bash -$ git clone someurl.com/foo -$ cd foo -$ cargo build -``` - -## Making A New Cargo Project the Easy Way - -You don’t have to go through that previous process every time you want to start -a new project! Cargo can quickly make a bare-bones project directory that you -can start developing in right away. - -To start a new project with Cargo, enter `cargo new` at the command line: - -```bash -$ cargo new hello_world --bin -``` - -This command passes `--bin` because the goal is to get straight to making an -executable application, as opposed to a library. Executables are often called -*binaries* (as in `/usr/bin`, if you’re on a Unix system). - -Cargo has generated two files and one directory for us: a `Cargo.toml` and a -*src* directory with a *main.rs* file inside. These should look familiar, -they’re exactly what we created by hand, above. - -This output is all you need to get started. First, open `Cargo.toml`. It should -look something like this: - -```toml -[package] - -name = "hello_world" -version = "0.1.0" -authors = ["Your Name <you@example.com>"] - -[dependencies] -``` - -Do not worry about the `[dependencies]` line, we will come back to it later. - -Cargo has populated *Cargo.toml* with reasonable defaults based on the arguments -you gave it and your `git` global configuration. You may notice that Cargo has -also initialized the `hello_world` directory as a `git` repository. - -Here’s what should be in `src/main.rs`: - -```rust -fn main() { - println!("Hello, world!"); -} -``` - -Cargo has generated a "Hello World!" for you, and you’re ready to start coding! - -> Note: If you want to look at Cargo in more detail, check out the official [Cargo -guide], which covers all of its features. - -[Cargo guide]: http://doc.crates.io/guide.html - -# Closing Thoughts - -This chapter covered the basics that will serve you well through the rest of -this book, and the rest of your time with Rust. Now that you’ve got the tools -down, we'll cover more about the Rust language itself. - -You have two options: Dive into a project with ‘[Tutorial: Guessing Game][guessinggame]’, or -start from the bottom and work your way up with ‘[Syntax and -Semantics][syntax]’. More experienced systems programmers will probably prefer -‘Tutorial: Guessing Game’, while those from dynamic backgrounds may enjoy either. Different -people learn differently! Choose whatever’s right for you. - -[guessinggame]: guessing-game.html -[syntax]: syntax-and-semantics.html diff --git a/src/doc/book/src/glossary.md b/src/doc/book/src/glossary.md deleted file mode 100644 index b17b89633f356..0000000000000 --- a/src/doc/book/src/glossary.md +++ /dev/null @@ -1,85 +0,0 @@ -# Glossary - -Not every Rustacean has a background in systems programming, nor in computer -science, so we've added explanations of terms that might be unfamiliar. - -### Abstract Syntax Tree - -When a compiler is compiling your program, it does a number of different things. -One of the things that it does is turn the text of your program into an -‘abstract syntax tree’, or ‘AST’. This tree is a representation of the structure -of your program. For example, `2 + 3` can be turned into a tree: - -```text - + - / \ -2 3 -``` - -And `2 + (3 * 4)` would look like this: - -```text - + - / \ -2 * - / \ - 3 4 -``` - -### Arity - -Arity refers to the number of arguments a function or operation takes. - -```rust -let x = (2, 3); -let y = (4, 6); -let z = (8, 2, 6); -``` - -In the example above `x` and `y` have arity 2. `z` has arity 3. - -### Bounds - -Bounds are constraints on a type or [trait][traits]. For example, if a bound -is placed on the argument a function takes, types passed to that function -must abide by that constraint. - -[traits]: traits.html - -### Combinators - -Combinators are higher-order functions that apply only functions and -earlier defined combinators to provide a result from its arguments. -They can be used to manage control flow in a modular fashion. - -### DST (Dynamically Sized Type) - -A type without a statically known size or alignment. ([more info][link]) - -[link]: ../nomicon/exotic-sizes.html#dynamically-sized-types-dsts - -### Expression - -In computer programming, an expression is a combination of values, constants, -variables, operators and functions that evaluate to a single value. For example, -`2 + (3 * 4)` is an expression that returns the value 14. It is worth noting -that expressions can have side-effects. For example, a function included in an -expression might perform actions other than simply returning a value. - -### Expression-Oriented Language - -In early programming languages, [expressions][expression] and -[statements][statement] were two separate syntactic categories: expressions had -a value and statements did things. However, later languages blurred this -distinction, allowing expressions to do things and statements to have a value. -In an expression-oriented language, (nearly) every statement is an expression -and therefore returns a value. Consequently, these expression statements can -themselves form part of larger expressions. - -[expression]: glossary.html#expression -[statement]: glossary.html#statement - -### Statement - -In computer programming, a statement is the smallest standalone element of a -programming language that commands a computer to perform an action. diff --git a/src/doc/book/src/guessing-game.md b/src/doc/book/src/guessing-game.md deleted file mode 100644 index 4d81438b11dea..0000000000000 --- a/src/doc/book/src/guessing-game.md +++ /dev/null @@ -1,1010 +0,0 @@ -# Guessing Game - -Let’s learn some Rust! For our first project, we’ll implement a classic -beginner programming problem: the guessing game. Here’s how it works: Our -program will generate a random integer between one and a hundred. It will then -prompt us to enter a guess. Upon entering our guess, it will tell us if we’re -too low or too high. Once we guess correctly, it will congratulate us. Sounds -good? - -Along the way, we’ll learn a little bit about Rust. The next chapter, ‘Syntax -and Semantics’, will dive deeper into each part. - -# Set up - -Let’s set up a new project. Go to your projects directory. Remember how we had -to create our directory structure and a `Cargo.toml` for `hello_world`? Cargo -has a command that does that for us. Let’s give it a shot: - -```bash -$ cd ~/projects -$ cargo new guessing_game --bin - Created binary (application) `guessing_game` project -$ cd guessing_game -``` - -We pass the name of our project to `cargo new`, and then the `--bin` flag, -since we’re making a binary, rather than a library. - -Check out the generated `Cargo.toml`: - -```toml -[package] - -name = "guessing_game" -version = "0.1.0" -authors = ["Your Name <you@example.com>"] -``` - -Cargo gets this information from your environment. If it’s not correct, go ahead -and fix that. - -Finally, Cargo generated a ‘Hello, world!’ for us. Check out `src/main.rs`: - -```rust -fn main() { - println!("Hello, world!"); -} -``` - -Let’s try compiling what Cargo gave us: - -```{bash} -$ cargo build - Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game) - Finished debug [unoptimized + debuginfo] target(s) in 0.53 secs -``` - -Excellent! Open up your `src/main.rs` again. We’ll be writing all of -our code in this file. - -Remember the `run` command from last chapter? Try it out again here: - -```bash -$ cargo run - Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game) - Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs - Running `target/debug/guessing_game` -Hello, world! -``` - -Great! Our game is just the kind of project `run` is good for: we need -to quickly test each iteration before moving on to the next one. - -# Processing a Guess - -Let’s get to it! The first thing we need to do for our guessing game is -allow our player to input a guess. Put this in your `src/main.rs`: - -```rust,no_run -use std::io; - -fn main() { - println!("Guess the number!"); - - println!("Please input your guess."); - - let mut guess = String::new(); - - io::stdin().read_line(&mut guess) - .expect("Failed to read line"); - - println!("You guessed: {}", guess); -} -``` - -There’s a lot here! Let’s go over it, bit by bit. - -```rust,ignore -use std::io; -``` - -We’ll need to take user input, and then print the result as output. As such, we -need the `io` library from the standard library. Rust only imports a few things -by default into every program, [the ‘prelude’][prelude]. If it’s not in the -prelude, you’ll have to `use` it directly. There is also a second ‘prelude’, the -[`io` prelude][ioprelude], which serves a similar function: you import it, and it -imports a number of useful, `io`-related things. - -[prelude]: ../std/prelude/index.html -[ioprelude]: ../std/io/prelude/index.html - -```rust,ignore -fn main() { -``` - -As you’ve seen before, the `main()` function is the entry point into your -program. The `fn` syntax declares a new function, the `()`s indicate that -there are no arguments, and `{` starts the body of the function. Because -we didn’t include a return type, it’s assumed to be `()`, an empty -[tuple][tuples]. - -[tuples]: primitive-types.html#tuples - -```rust,ignore - println!("Guess the number!"); - - println!("Please input your guess."); -``` - -We previously learned that `println!()` is a [macro][macros] that -prints a [string][strings] to the screen. - -[macros]: macros.html -[strings]: strings.html - -```rust,ignore - let mut guess = String::new(); -``` - -Now we’re getting interesting! There’s a lot going on in this little line. -The first thing to notice is that this is a [let statement][let], which is -used to create ‘variable bindings’. They take this form: - -```rust,ignore -let foo = bar; -``` - -[let]: variable-bindings.html - -This will create a new binding named `foo`, and bind it to the value `bar`. In -many languages, this is called a ‘variable’, but Rust’s variable bindings have -a few tricks up their sleeves. - -For example, they’re [immutable][immutable] by default. That’s why our example -uses `mut`: it makes a binding mutable, rather than immutable. `let` doesn’t -take a name on the left hand side of the assignment, it actually accepts a -‘[pattern][patterns]’. We’ll use patterns later. It’s easy enough -to use for now: - -```rust -let foo = 5; // `foo` is immutable. -let mut bar = 5; // `bar` is mutable. -``` - -[immutable]: mutability.html -[patterns]: patterns.html - -Oh, and `//` will start a comment, until the end of the line. Rust ignores -everything in [comments][comments]. - -[comments]: comments.html - -So now we know that `let mut guess` will introduce a mutable binding named -`guess`, but we have to look at the other side of the `=` for what it’s -bound to: `String::new()`. - -`String` is a string type, provided by the standard library. A -[`String`][string] is a growable, UTF-8 encoded bit of text. - -[string]: ../std/string/struct.String.html - -The `::new()` syntax uses `::` because this is an ‘associated function’ of -a particular type. That is to say, it’s associated with `String` itself, -rather than a particular instance of a `String`. Some languages call this a -‘static method’. - -This function is named `new()`, because it creates a new, empty `String`. -You’ll find a `new()` function on many types, as it’s a common name for making -a new value of some kind. - -Let’s move forward: - -```rust,ignore - io::stdin().read_line(&mut guess) - .expect("Failed to read line"); -``` - -That’s a lot more! Let’s go bit-by-bit. The first line has two parts. Here’s -the first: - -```rust,ignore -io::stdin() -``` - -Remember how we `use`d `std::io` on the first line of the program? We’re now -calling an associated function on it. If we didn’t `use std::io`, we could -have written this line as `std::io::stdin()`. - -This particular function returns a handle to the standard input for your -terminal. More specifically, a [std::io::Stdin][iostdin]. - -[iostdin]: ../std/io/struct.Stdin.html - -The next part will use this handle to get input from the user: - -```rust,ignore -.read_line(&mut guess) -``` - -Here, we call the [`read_line()`][read_line] method on our handle. -[Methods][method] are like associated functions, but are only available on a -particular instance of a type, rather than the type itself. We’re also passing -one argument to `read_line()`: `&mut guess`. - -[read_line]: ../std/io/struct.Stdin.html#method.read_line -[method]: method-syntax.html - -Remember how we bound `guess` above? We said it was mutable. However, -`read_line` doesn’t take a `String` as an argument: it takes a `&mut String`. -Rust has a feature called ‘[references][references]’, which allows you to have -multiple references to one piece of data, which can reduce copying. References -are a complex feature, as one of Rust’s major selling points is how safe and -easy it is to use references. We don’t need to know a lot of those details to -finish our program right now, though. For now, all we need to know is that -like `let` bindings, references are immutable by default. Hence, we need to -write `&mut guess`, rather than `&guess`. - -Why does `read_line()` take a mutable reference to a string? Its job is -to take what the user types into standard input, and place that into a -string. So it takes that string as an argument, and in order to add -the input, it needs to be mutable. - -[references]: references-and-borrowing.html - -But we’re not quite done with this line of code, though. While it’s -a single line of text, it’s only the first part of the single logical line of -code: - -```rust,ignore - .expect("Failed to read line"); -``` - -When you call a method with the `.foo()` syntax, you may introduce a newline -and other whitespace. This helps you split up long lines. We _could_ have -done: - -```rust,ignore - io::stdin().read_line(&mut guess).expect("Failed to read line"); -``` - -But that gets hard to read. So we’ve split it up, two lines for two method -calls. We already talked about `read_line()`, but what about `expect()`? Well, -we already mentioned that `read_line()` puts what the user types into the `&mut -String` we pass it. But it also returns a value: in this case, an -[`io::Result`][ioresult]. Rust has a number of types named `Result` in its -standard library: a generic [`Result`][result], and then specific versions for -sub-libraries, like `io::Result`. - -[ioresult]: ../std/io/type.Result.html -[result]: ../std/result/enum.Result.html - -The purpose of these `Result` types is to encode error handling information. -Values of the `Result` type, like any type, have methods defined on them. In -this case, `io::Result` has an [`expect()` method][expect] that takes a value -it’s called on, and if it isn’t a successful one, [`panic!`][panic]s with a -message you passed it. A `panic!` like this will cause our program to crash, -displaying the message. - -[expect]: ../std/result/enum.Result.html#method.expect -[panic]: error-handling.html - -If we do not call `expect()`, our program will compile, but -we’ll get a warning: - -```bash -$ cargo build - Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game) -warning: unused result which must be used, #[warn(unused_must_use)] on by default - --> src/main.rs:10:5 - | -10 | io::stdin().read_line(&mut guess); - | ^ - - Finished debug [unoptimized + debuginfo] target(s) in 0.42 secs -``` - -Rust warns us that we haven’t used the `Result` value. This warning comes from -a special annotation that `io::Result` has. Rust is trying to tell you that -you haven’t handled a possible error. The right way to suppress the error is -to actually write error handling. Luckily, if we want to crash if there’s -a problem, we can use `expect()`. If we can recover from the -error somehow, we’d do something else, but we’ll save that for a future -project. - -There’s only one line of this first example left: - -```rust,ignore - println!("You guessed: {}", guess); -} -``` - -This prints out the string we saved our input in. The `{}`s are a placeholder, -and so we pass it `guess` as an argument. If we had multiple `{}`s, we would -pass multiple arguments: - -```rust -let x = 5; -let y = 10; - -println!("x and y: {} and {}", x, y); -``` - -Easy. - -Anyway, that’s the tour. We can run what we have with `cargo run`: - -```bash -$ cargo run - Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game) - Finished debug [unoptimized + debuginfo] target(s) in 0.44 secs - Running `target/debug/guessing_game` -Guess the number! -Please input your guess. -6 -You guessed: 6 -``` - -All right! Our first part is done: we can get input from the keyboard, -and then print it back out. - -# Generating a secret number - -Next, we need to generate a secret number. Rust does not yet include random -number functionality in its standard library. The Rust team does, however, -provide a [`rand` crate][randcrate]. A ‘crate’ is a package of Rust code. -We’ve been building a ‘binary crate’, which is an executable. `rand` is a -‘library crate’, which contains code that’s intended to be used with other -programs. - -[randcrate]: https://crates.io/crates/rand - -Using external crates is where Cargo really shines. Before we can write -the code using `rand`, we need to modify our `Cargo.toml`. Open it up, and -add these few lines at the bottom: - -```toml -[dependencies] - -rand="0.3.0" -``` - -The `[dependencies]` section of `Cargo.toml` is like the `[package]` section: -everything that follows it is part of it, until the next section starts. -Cargo uses the dependencies section to know what dependencies on external -crates you have, and what versions you require. In this case, we’ve specified version `0.3.0`, -which Cargo understands to be any release that’s compatible with this specific version. -Cargo understands [Semantic Versioning][semver], which is a standard for writing version -numbers. A bare number like above is actually shorthand for `^0.3.0`, -meaning "anything compatible with 0.3.0". -If we wanted to use only `0.3.0` exactly, we could say `rand="=0.3.0"` -(note the two equal signs). -We could also use a range of versions. -[Cargo’s documentation][cargodoc] contains more details. - -[semver]: http://semver.org -[cargodoc]: http://doc.crates.io/specifying-dependencies.html - -Now, without changing any of our code, let’s build our project: - -```bash -$ cargo build - Updating registry `https://github.com/rust-lang/crates.io-index` - Downloading rand v0.3.14 - Downloading libc v0.2.17 - Compiling libc v0.2.17 - Compiling rand v0.3.14 - Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game) - Finished debug [unoptimized + debuginfo] target(s) in 5.88 secs -``` - -(You may see different versions, of course.) - -Lots of new output! Now that we have an external dependency, Cargo fetches the -latest versions of everything from the registry, which is a copy of data from -[Crates.io][cratesio]. Crates.io is where people in the Rust ecosystem -post their open source Rust projects for others to use. - -[cratesio]: https://crates.io - -After updating the registry, Cargo checks our `[dependencies]` and downloads -any we don’t have yet. In this case, while we only said we wanted to depend on -`rand`, we’ve also grabbed a copy of `libc`. This is because `rand` depends on -`libc` to work. After downloading them, it compiles them, and then compiles -our project. - -If we run `cargo build` again, we’ll get different output: - -```bash -$ cargo build - Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs -``` - -That’s right, nothing was done! Cargo knows that our project has been built, and that -all of its dependencies are built, and so there’s no reason to do all that -stuff. With nothing to do, it simply exits. If we open up `src/main.rs` again, -make a trivial change, and then save it again, we’ll only see two lines: - -```bash -$ cargo build - Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game) - Finished debug [unoptimized + debuginfo] target(s) in 0.45 secs -``` - -So, we told Cargo we wanted any `0.3.x` version of `rand`, and so it fetched the latest -version at the time this was written, `v0.3.14`. But what happens when next -week, version `v0.3.15` comes out, with an important bugfix? While getting -bugfixes is important, what if `0.3.15` contains a regression that breaks our -code? - -The answer to this problem is the `Cargo.lock` file you’ll now find in your -project directory. When you build your project for the first time, Cargo -figures out all of the versions that fit your criteria, and then writes them -to the `Cargo.lock` file. When you build your project in the future, Cargo -will see that the `Cargo.lock` file exists, and then use that specific version -rather than do all the work of figuring out versions again. This lets you -have a repeatable build automatically. In other words, we’ll stay at `0.3.14` -until we explicitly upgrade, and so will anyone who we share our code with, -thanks to the lock file. - -What about when we _do_ want to use `v0.3.15`? Cargo has another command, -`update`, which says ‘ignore the lock, figure out all the latest versions that -fit what we’ve specified. If that works, write those versions out to the lock -file’. But, by default, Cargo will only look for versions larger than `0.3.0` -and smaller than `0.4.0`. If we want to move to `0.4.x`, we’d have to update -the `Cargo.toml` directly. When we do, the next time we `cargo build`, Cargo -will update the index and re-evaluate our `rand` requirements. - -There’s a lot more to say about [Cargo][doccargo] and [its -ecosystem][doccratesio], but for now, that’s all we need to know. Cargo makes -it really easy to re-use libraries, and so Rustaceans tend to write smaller -projects which are assembled out of a number of sub-packages. - -[doccargo]: http://doc.crates.io -[doccratesio]: http://doc.crates.io/crates-io.html - -Let’s get on to actually _using_ `rand`. Here’s our next step: - -```rust,ignore -extern crate rand; - -use std::io; -use rand::Rng; - -fn main() { - println!("Guess the number!"); - - let secret_number = rand::thread_rng().gen_range(1, 101); - - println!("The secret number is: {}", secret_number); - - println!("Please input your guess."); - - let mut guess = String::new(); - - io::stdin().read_line(&mut guess) - .expect("Failed to read line"); - - println!("You guessed: {}", guess); -} -``` - -The first thing we’ve done is change the first line. It now says -`extern crate rand`. Because we declared `rand` in our `[dependencies]`, we -can use `extern crate` to let Rust know we’ll be making use of it. This also -does the equivalent of a `use rand;` as well, so we can make use of anything -in the `rand` crate by prefixing it with `rand::`. - -Next, we added another `use` line: `use rand::Rng`. We’re going to use a -method in a moment, and it requires that `Rng` be in scope to work. The basic -idea is this: methods are defined on something called ‘traits’, and for the -method to work, it needs the trait to be in scope. For more about the -details, read the [traits][traits] section. - -[traits]: traits.html - -There are two other lines we added, in the middle: - -```rust,ignore - let secret_number = rand::thread_rng().gen_range(1, 101); - - println!("The secret number is: {}", secret_number); -``` - -We use the `rand::thread_rng()` function to get a copy of the random number -generator, which is local to the particular [thread][concurrency] of execution -we’re in. Because we `use rand::Rng`’d above, it has a `gen_range()` method -available. This method takes two arguments, and generates a number between -them. It’s inclusive on the lower bound, but exclusive on the upper bound, -so we need `1` and `101` to get a number ranging from one to a hundred. - -[concurrency]: concurrency.html - -The second line prints out the secret number. This is useful while -we’re developing our program, so we can easily test it out. But we’ll be -deleting it for the final version. It’s not much of a game if it prints out -the answer when you start it up! - -Try running our new program a few times: - -```bash -$ cargo run - Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game) - Finished debug [unoptimized + debuginfo] target(s) in 0.55 secs - Running `target/debug/guessing_game` -Guess the number! -The secret number is: 7 -Please input your guess. -4 -You guessed: 4 -$ cargo run - Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs - Running `target/debug/guessing_game` -Guess the number! -The secret number is: 83 -Please input your guess. -5 -You guessed: 5 -``` - -Great! Next up: comparing our guess to the secret number. - -# Comparing guesses - -Now that we’ve got user input, let’s compare our guess to the secret number. -Here’s our next step, though it doesn’t quite compile yet: - -```rust,ignore -extern crate rand; - -use std::io; -use std::cmp::Ordering; -use rand::Rng; - -fn main() { - println!("Guess the number!"); - - let secret_number = rand::thread_rng().gen_range(1, 101); - - println!("The secret number is: {}", secret_number); - - println!("Please input your guess."); - - let mut guess = String::new(); - - io::stdin().read_line(&mut guess) - .expect("Failed to read line"); - - println!("You guessed: {}", guess); - - match guess.cmp(&secret_number) { - Ordering::Less => println!("Too small!"), - Ordering::Greater => println!("Too big!"), - Ordering::Equal => println!("You win!"), - } -} -``` - -A few new bits here. The first is another `use`. We bring a type called -`std::cmp::Ordering` into scope. Then, five new lines at the bottom that use -it: - -```rust,ignore -match guess.cmp(&secret_number) { - Ordering::Less => println!("Too small!"), - Ordering::Greater => println!("Too big!"), - Ordering::Equal => println!("You win!"), -} -``` - -The `cmp()` method can be called on anything that can be compared, and it -takes a reference to the thing you want to compare it to. It returns the -`Ordering` type we `use`d earlier. We use a [`match`][match] statement to -determine exactly what kind of `Ordering` it is. `Ordering` is an -[`enum`][enum], short for ‘enumeration’, which looks like this: - -```rust -enum Foo { - Bar, - Baz, -} -``` - -[match]: match.html -[enum]: enums.html - -With this definition, anything of type `Foo` can be either a -`Foo::Bar` or a `Foo::Baz`. We use the `::` to indicate the -namespace for a particular `enum` variant. - -The [`Ordering`][ordering] `enum` has three possible variants: `Less`, `Equal`, -and `Greater`. The `match` statement takes a value of a type, and lets you -create an ‘arm’ for each possible value. Since we have three types of -`Ordering`, we have three arms: - -```rust,ignore -match guess.cmp(&secret_number) { - Ordering::Less => println!("Too small!"), - Ordering::Greater => println!("Too big!"), - Ordering::Equal => println!("You win!"), -} -``` - -[ordering]: ../std/cmp/enum.Ordering.html - -If it’s `Less`, we print `Too small!`, if it’s `Greater`, `Too big!`, and if -`Equal`, `You win!`. `match` is really useful, and is used often in Rust. - -I did mention that this won’t quite compile yet, though. Let’s try it: - -```bash -$ cargo build - Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game) -error[E0308]: mismatched types - --> src/main.rs:23:21 - | -23 | match guess.cmp(&secret_number) { - | ^^^^^^^^^^^^^^ expected struct `std::string::String`, found integral variable - | - = note: expected type `&std::string::String` - = note: found type `&{integer}` - -error: aborting due to previous error - -error: Could not compile `guessing_game`. - -To learn more, run the command again with --verbose. -``` - -Whew! This is a big error. The core of it is that we have ‘mismatched types’. -Rust has a strong, static type system. However, it also has type inference. -When we wrote `let guess = String::new()`, Rust was able to infer that `guess` -should be a `String`, and so it doesn’t make us write out the type. And with -our `secret_number`, there are a number of types which can have a value -between one and a hundred: `i32`, a thirty-two-bit number, or `u32`, an -unsigned thirty-two-bit number, or `i64`, a sixty-four-bit number or others. -So far, that hasn’t mattered, and so Rust defaults to an `i32`. However, here, -Rust doesn’t know how to compare the `guess` and the `secret_number`. They -need to be the same type. Ultimately, we want to convert the `String` we -read as input into a real number type, for comparison. We can do that -with two more lines. Here’s our new program: - -```rust,ignore -extern crate rand; - -use std::io; -use std::cmp::Ordering; -use rand::Rng; - -fn main() { - println!("Guess the number!"); - - let secret_number = rand::thread_rng().gen_range(1, 101); - - println!("The secret number is: {}", secret_number); - - println!("Please input your guess."); - - let mut guess = String::new(); - - io::stdin().read_line(&mut guess) - .expect("Failed to read line"); - - let guess: u32 = guess.trim().parse() - .expect("Please type a number!"); - - println!("You guessed: {}", guess); - - match guess.cmp(&secret_number) { - Ordering::Less => println!("Too small!"), - Ordering::Greater => println!("Too big!"), - Ordering::Equal => println!("You win!"), - } -} -``` - -The new two lines: - -```rust,ignore - let guess: u32 = guess.trim().parse() - .expect("Please type a number!"); -``` - -Wait a minute, I thought we already had a `guess`? We do, but Rust allows us -to ‘shadow’ the previous `guess` with a new one. This is often used in this -exact situation, where `guess` starts as a `String`, but we want to convert it -to an `u32`. Shadowing lets us re-use the `guess` name, rather than forcing us -to come up with two unique names like `guess_str` and `guess`, or something -else. - -We bind `guess` to an expression that looks like something we wrote earlier: - -```rust,ignore -guess.trim().parse() -``` - -Here, `guess` refers to the old `guess`, the one that was a `String` with our -input in it. The `trim()` method on `String`s will eliminate any white space at -the beginning and end of our string. This is important, as we had to press the -‘return’ key to satisfy `read_line()`. This means that if we type `5` and hit -return, `guess` looks like this: `5\n`. The `\n` represents ‘newline’, the -enter key. `trim()` gets rid of this, leaving our string with only the `5`. The -[`parse()` method on strings][parse] parses a string into some kind of number. -Since it can parse a variety of numbers, we need to give Rust a hint as to the -exact type of number we want. Hence, `let guess: u32`. The colon (`:`) after -`guess` tells Rust we’re going to annotate its type. `u32` is an unsigned, -thirty-two bit integer. Rust has [a number of built-in number types][number], -but we’ve chosen `u32`. It’s a good default choice for a small positive number. - -[parse]: ../std/primitive.str.html#method.parse -[number]: primitive-types.html#numeric-types - -Just like `read_line()`, our call to `parse()` could cause an error. What if -our string contained `A👍%`? There’d be no way to convert that to a number. As -such, we’ll do the same thing we did with `read_line()`: use the `expect()` -method to crash if there’s an error. - -Let’s try our program out! - -```bash -$ cargo run - Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game) - Finished debug [unoptimized + debuginfo] target(s) in 0.57 secs - Running `target/guessing_game` -Guess the number! -The secret number is: 58 -Please input your guess. - 76 -You guessed: 76 -Too big! -``` - -Nice! You can see I even added spaces before my guess, and it still figured -out that I guessed 76. Run the program a few times, and verify that guessing -the number works, as well as guessing a number too small. - -Now we’ve got most of the game working, but we can only make one guess. Let’s -change that by adding loops! - -# Looping - -The `loop` keyword gives us an infinite loop. Let’s add that in: - -```rust,ignore -extern crate rand; - -use std::io; -use std::cmp::Ordering; -use rand::Rng; - -fn main() { - println!("Guess the number!"); - - let secret_number = rand::thread_rng().gen_range(1, 101); - - println!("The secret number is: {}", secret_number); - - loop { - println!("Please input your guess."); - - let mut guess = String::new(); - - io::stdin().read_line(&mut guess) - .expect("Failed to read line"); - - let guess: u32 = guess.trim().parse() - .expect("Please type a number!"); - - println!("You guessed: {}", guess); - - match guess.cmp(&secret_number) { - Ordering::Less => println!("Too small!"), - Ordering::Greater => println!("Too big!"), - Ordering::Equal => println!("You win!"), - } - } -} -``` - -And try it out. But wait, didn’t we just add an infinite loop? Yup. Remember -our discussion about `parse()`? If we give a non-number answer, we’ll `panic!` -and quit. Observe: - -```bash -$ cargo run - Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game) - Finished debug [unoptimized + debuginfo] target(s) in 0.58 secs - Running `target/guessing_game` -Guess the number! -The secret number is: 59 -Please input your guess. -45 -You guessed: 45 -Too small! -Please input your guess. -60 -You guessed: 60 -Too big! -Please input your guess. -59 -You guessed: 59 -You win! -Please input your guess. -quit -thread 'main' panicked at 'Please type a number!' -``` - -Ha! `quit` actually quits. As does any other non-number input. Well, this is -suboptimal to say the least. First, let’s actually quit when you win the game: - -```rust,ignore -extern crate rand; - -use std::io; -use std::cmp::Ordering; -use rand::Rng; - -fn main() { - println!("Guess the number!"); - - let secret_number = rand::thread_rng().gen_range(1, 101); - - println!("The secret number is: {}", secret_number); - - loop { - println!("Please input your guess."); - - let mut guess = String::new(); - - io::stdin().read_line(&mut guess) - .expect("Failed to read line"); - - let guess: u32 = guess.trim().parse() - .expect("Please type a number!"); - - println!("You guessed: {}", guess); - - match guess.cmp(&secret_number) { - Ordering::Less => println!("Too small!"), - Ordering::Greater => println!("Too big!"), - Ordering::Equal => { - println!("You win!"); - break; - } - } - } -} -``` - -By adding the `break` line after the `You win!`, we’ll exit the loop when we -win. Exiting the loop also means exiting the program, since it’s the last -thing in `main()`. We have only one more tweak to make: when someone inputs a -non-number, we don’t want to quit, we want to ignore it. We can do that -like this: - -```rust,ignore -extern crate rand; - -use std::io; -use std::cmp::Ordering; -use rand::Rng; - -fn main() { - println!("Guess the number!"); - - let secret_number = rand::thread_rng().gen_range(1, 101); - - println!("The secret number is: {}", secret_number); - - loop { - println!("Please input your guess."); - - let mut guess = String::new(); - - io::stdin().read_line(&mut guess) - .expect("Failed to read line"); - - let guess: u32 = match guess.trim().parse() { - Ok(num) => num, - Err(_) => continue, - }; - - println!("You guessed: {}", guess); - - match guess.cmp(&secret_number) { - Ordering::Less => println!("Too small!"), - Ordering::Greater => println!("Too big!"), - Ordering::Equal => { - println!("You win!"); - break; - } - } - } -} -``` - -These are the lines that changed: - -```rust,ignore -let guess: u32 = match guess.trim().parse() { - Ok(num) => num, - Err(_) => continue, -}; -``` -This is how you generally move from ‘crash on error’ to ‘actually handle the -error’, by switching from `expect()` to a `match` statement. A `Result` is -returned by `parse()`, this is an `enum` like `Ordering`, but in this case, -each variant has some data associated with it: `Ok` is a success, and `Err` is a -failure. Each contains more information: the successfully parsed integer, or an -error type. In this case, we `match` on `Ok(num)`, which sets the name `num` to -the unwrapped `Ok` value (the integer), and then we return it on the -right-hand side. In the `Err` case, we don’t care what kind of error it is, so -we just use the catch all `_` instead of a name. This catches everything that -isn't `Ok`, and `continue` lets us move to the next iteration of the loop; in -effect, this enables us to ignore all errors and continue with our program. - -Now we should be good! Let’s try: - -```bash -$ cargo run - Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game) - Finished debug [unoptimized + debuginfo] target(s) in 0.57 secs - Running `target/guessing_game` -Guess the number! -The secret number is: 61 -Please input your guess. -10 -You guessed: 10 -Too small! -Please input your guess. -99 -You guessed: 99 -Too big! -Please input your guess. -foo -Please input your guess. -61 -You guessed: 61 -You win! -``` - -Awesome! With one tiny last tweak, we have finished the guessing game. Can you -think of what it is? That’s right, we don’t want to print out the secret -number. It was good for testing, but it kind of ruins the game. Here’s our -final source: - -```rust,ignore -extern crate rand; - -use std::io; -use std::cmp::Ordering; -use rand::Rng; - -fn main() { - println!("Guess the number!"); - - let secret_number = rand::thread_rng().gen_range(1, 101); - - loop { - println!("Please input your guess."); - - let mut guess = String::new(); - - io::stdin().read_line(&mut guess) - .expect("Failed to read line"); - - let guess: u32 = match guess.trim().parse() { - Ok(num) => num, - Err(_) => continue, - }; - - println!("You guessed: {}", guess); - - match guess.cmp(&secret_number) { - Ordering::Less => println!("Too small!"), - Ordering::Greater => println!("Too big!"), - Ordering::Equal => { - println!("You win!"); - break; - } - } - } -} -``` - -# Complete! - -This project showed you a lot: `let`, `match`, methods, associated -functions, using external crates, and more. - -At this point, you have successfully built the Guessing Game! Congratulations! diff --git a/src/doc/book/src/if-let.md b/src/doc/book/src/if-let.md deleted file mode 100644 index 9eeac3d687ebf..0000000000000 --- a/src/doc/book/src/if-let.md +++ /dev/null @@ -1,84 +0,0 @@ -# if let - -`if let` permits [patterns][patterns] matching within the condition of an [if][if] statement. -This allows us to reduce the overhead of certain kinds of [pattern][patterns] matches -and express them in a more convenient way. - -For example, let’s say we have some sort of `Option<T>`. We want to call a function -on it if it’s `Some<T>`, but do nothing if it’s `None`. That looks like this: - -```rust -# let option = Some(5); -# fn foo(x: i32) { } -match option { - Some(x) => { foo(x) }, - None => {}, -} -``` - -We don’t have to use `match` here, for example, we could use `if`: - -```rust -# let option = Some(5); -# fn foo(x: i32) { } -if option.is_some() { - let x = option.unwrap(); - foo(x); -} -``` - -Neither of these options is particularly appealing. We can use `if let` to -do the same thing in a nicer way: - -```rust -# let option = Some(5); -# fn foo(x: i32) { } -if let Some(x) = option { - foo(x); -} -``` - -If a [pattern][patterns] matches successfully, it binds any appropriate parts of -the value to the identifiers in the pattern, then evaluates the expression. If -the pattern doesn’t match, nothing happens. - -If you want to do something else when the pattern does not match, you can -use `else`: - -```rust -# let option = Some(5); -# fn foo(x: i32) { } -# fn bar() { } -if let Some(x) = option { - foo(x); -} else { - bar(); -} -``` - -## `while let` - -In a similar fashion, `while let` can be used when you want to conditionally -loop as long as a value matches a certain pattern. It turns code like this: - -```rust -let mut v = vec![1, 3, 5, 7, 11]; -loop { - match v.pop() { - Some(x) => println!("{}", x), - None => break, - } -} -``` - -Into code like this: - -```rust -let mut v = vec![1, 3, 5, 7, 11]; -while let Some(x) = v.pop() { - println!("{}", x); -} -``` - -[patterns]: patterns.html -[if]: if.html diff --git a/src/doc/book/src/if.md b/src/doc/book/src/if.md deleted file mode 100644 index d74503757bc48..0000000000000 --- a/src/doc/book/src/if.md +++ /dev/null @@ -1,73 +0,0 @@ -# if - -Rust’s take on `if` is not particularly complex, but it’s much more like the -`if` you’ll find in a dynamically typed language than in a more traditional -systems language. So let’s talk about it, to make sure you grasp the nuances. - -`if` is a specific form of a more general concept, the ‘branch’, whose name comes -from a branch in a tree: a decision point, where depending on a choice, -multiple paths can be taken. - -In the case of `if`, there is one choice that leads down two paths: - -```rust -let x = 5; - -if x == 5 { - println!("x is five!"); -} -``` - -If we changed the value of `x` to something else, this line would not print. -More specifically, if the expression after the `if` evaluates to `true`, then -the block is executed. If it’s `false`, then it is not. - -If you want something to happen in the `false` case, use an `else`: - -```rust -let x = 5; - -if x == 5 { - println!("x is five!"); -} else { - println!("x is not five :("); -} -``` - -If there is more than one case, use an `else if`: - -```rust -let x = 5; - -if x == 5 { - println!("x is five!"); -} else if x == 6 { - println!("x is six!"); -} else { - println!("x is not five or six :("); -} -``` - -This is all pretty standard. However, you can also do this: - -```rust -let x = 5; - -let y = if x == 5 { - 10 -} else { - 15 -}; // y: i32 -``` - -Which we can (and probably should) write like this: - -```rust -let x = 5; - -let y = if x == 5 { 10 } else { 15 }; // y: i32 -``` - -This works because `if` is an expression. The value of the expression is the -value of the last expression in whichever branch was chosen. An `if` without an -`else` always results in `()` as the value. diff --git a/src/doc/book/src/iterators.md b/src/doc/book/src/iterators.md deleted file mode 100644 index 8ee6c0828ad6b..0000000000000 --- a/src/doc/book/src/iterators.md +++ /dev/null @@ -1,344 +0,0 @@ -# Iterators - -Let's talk about loops. - -Remember Rust's `for` loop? Here's an example: - -```rust -for x in 0..10 { - println!("{}", x); -} -``` - -Now that you know more Rust, we can talk in detail about how this works. -Ranges (the `0..10`) are 'iterators'. An iterator is something that we can -call the `.next()` method on repeatedly, and it gives us a sequence of things. - -(By the way, a range with two dots like `0..10` is inclusive on the left (so it -starts at 0) and exclusive on the right (so it ends at 9). A mathematician -would write "[0, 10)". To get a range that goes all the way up to 10 you can -write `0...10`.) - -Like this: - -```rust -let mut range = 0..10; - -loop { - match range.next() { - Some(x) => { - println!("{}", x); - }, - None => { break } - } -} -``` - -We make a mutable binding to the range, which is our iterator. We then `loop`, -with an inner `match`. This `match` is used on the result of `range.next()`, -which gives us a reference to the next value of the iterator. `next` returns an -`Option<i32>`, in this case, which will be `Some(i32)` when we have a value and -`None` once we run out. If we get `Some(i32)`, we print it out, and if we get -`None`, we `break` out of the loop. - -This code sample is basically the same as our `for` loop version. The `for` -loop is a handy way to write this `loop`/`match`/`break` construct. - -`for` loops aren't the only thing that uses iterators, however. Writing your -own iterator involves implementing the `Iterator` trait. While doing that is -outside of the scope of this guide, Rust provides a number of useful iterators -to accomplish various tasks. But first, a few notes about limitations of ranges. - -Ranges are very primitive, and we often can use better alternatives. Consider the -following Rust anti-pattern: using ranges to emulate a C-style `for` loop. Let’s -suppose you needed to iterate over the contents of a vector. You may be tempted -to write this: - -```rust -let nums = vec![1, 2, 3]; - -for i in 0..nums.len() { - println!("{}", nums[i]); -} -``` - -This is strictly worse than using an actual iterator. You can iterate over vectors -directly, so write this: - -```rust -let nums = vec![1, 2, 3]; - -for num in &nums { - println!("{}", num); -} -``` - -There are two reasons for this. First, this more directly expresses what we -mean. We iterate through the entire vector, rather than iterating through -indexes, and then indexing the vector. Second, this version is more efficient: -the first version will have extra bounds checking because it used indexing, -`nums[i]`. But since we yield a reference to each element of the vector in turn -with the iterator, there's no bounds checking in the second example. This is -very common with iterators: we can ignore unnecessary bounds checks, but still -know that we're safe. - -There's another detail here that's not 100% clear because of how `println!` -works. `num` is actually of type `&i32`. That is, it's a reference to an `i32`, -not an `i32` itself. `println!` handles the dereferencing for us, so we don't -see it. This code works fine too: - -```rust -let nums = vec![1, 2, 3]; - -for num in &nums { - println!("{}", *num); -} -``` - -Now we're explicitly dereferencing `num`. Why does `&nums` give us -references? Firstly, because we explicitly asked it to with -`&`. Secondly, if it gave us the data itself, we would have to be its -owner, which would involve making a copy of the data and giving us the -copy. With references, we're only borrowing a reference to the data, -and so it's only passing a reference, without needing to do the move. - -So, now that we've established that ranges are often not what you want, let's -talk about what you do want instead. - -There are three broad classes of things that are relevant here: iterators, -*iterator adaptors*, and *consumers*. Here's some definitions: - -* *iterators* give you a sequence of values. -* *iterator adaptors* operate on an iterator, producing a new iterator with a - different output sequence. -* *consumers* operate on an iterator, producing some final set of values. - -Let's talk about consumers first, since you've already seen an iterator, ranges. - -## Consumers - -A *consumer* operates on an iterator, returning some kind of value or values. -The most common consumer is `collect()`. This code doesn't quite compile, -but it shows the intention: - -```rust,ignore -let one_to_one_hundred = (1..101).collect(); -``` - -As you can see, we call `collect()` on our iterator. `collect()` takes -as many values as the iterator will give it, and returns a collection -of the results. So why won't this compile? Rust can't determine what -type of things you want to collect, and so you need to let it know. -Here's the version that does compile: - -```rust -let one_to_one_hundred = (1..101).collect::<Vec<i32>>(); -``` - -If you remember, the [`::<>` syntax](generics.html#resolving-ambiguities) -allows us to give a type hint that tells the compiler we want a vector of -integers. You don't always need to use the whole type, though. Using a `_` -will let you provide a partial hint: - -```rust -let one_to_one_hundred = (1..101).collect::<Vec<_>>(); -``` - -This says "Collect into a `Vec<T>`, please, but infer what the `T` is for me." -`_` is sometimes called a "type placeholder" for this reason. - -`collect()` is the most common consumer, but there are others too. `find()` -is one: - -```rust -let greater_than_forty_two = (0..100) - .find(|x| *x > 42); - -match greater_than_forty_two { - Some(_) => println!("Found a match!"), - None => println!("No match found :("), -} -``` - -`find` takes a closure, and works on a reference to each element of an -iterator. This closure returns `true` if the element is the element we're -looking for, and `false` otherwise. `find` returns the first element satisfying -the specified predicate. Because we might not find a matching element, `find` -returns an `Option` rather than the element itself. - -Another important consumer is `fold`. Here's what it looks like: - -```rust -let sum = (1..4).fold(0, |sum, x| sum + x); -``` - -`fold()` is a consumer that looks like this: -`fold(base, |accumulator, element| ...)`. It takes two arguments: the first -is an element called the *base*. The second is a closure that itself takes two -arguments: the first is called the *accumulator*, and the second is an -*element*. Upon each iteration, the closure is called, and the result is the -value of the accumulator on the next iteration. On the first iteration, the -base is the value of the accumulator. - -Okay, that's a bit confusing. Let's examine the values of all of these things -in this iterator: - -| base | accumulator | element | closure result | -|------|-------------|---------|----------------| -| 0 | 0 | 1 | 1 | -| 0 | 1 | 2 | 3 | -| 0 | 3 | 3 | 6 | - -We called `fold()` with these arguments: - -```rust -# (1..4) -.fold(0, |sum, x| sum + x); -``` - -So, `0` is our base, `sum` is our accumulator, and `x` is our element. On the -first iteration, we set `sum` to `0`, and `x` is the first element of `nums`, -`1`. We then add `sum` and `x`, which gives us `0 + 1 = 1`. On the second -iteration, that value becomes our accumulator, `sum`, and the element is -the second element of the array, `2`. `1 + 2 = 3`, and so that becomes -the value of the accumulator for the last iteration. On that iteration, -`x` is the last element, `3`, and `3 + 3 = 6`, which is our final -result for our sum. `1 + 2 + 3 = 6`, and that's the result we got. - -Whew. `fold` can be a bit strange the first few times you see it, but once it -clicks, you can use it all over the place. Any time you have a list of things, -and you want a single result, `fold` is appropriate. - -Consumers are important due to one additional property of iterators we haven't -talked about yet: laziness. Let's talk some more about iterators, and you'll -see why consumers matter. - -## Iterators - -As we've said before, an iterator is something that we can call the -`.next()` method on repeatedly, and it gives us a sequence of things. -Because you need to call the method, this means that iterators -can be *lazy* and not generate all of the values upfront. This code, -for example, does not actually generate the numbers `1-99`, instead -creating a value that merely represents the sequence: - -```rust -let nums = 1..100; -``` - -Since we didn't do anything with the range, it didn't generate the sequence. -Let's add the consumer: - -```rust -let nums = (1..100).collect::<Vec<i32>>(); -``` - -Now, `collect()` will require that the range gives it some numbers, and so -it will do the work of generating the sequence. - -Ranges are one of two basic iterators that you'll see. The other is `iter()`. -`iter()` can turn a vector into a simple iterator that gives you each element -in turn: - -```rust -let nums = vec![1, 2, 3]; - -for num in nums.iter() { - println!("{}", num); -} -``` - -These two basic iterators should serve you well. There are some more -advanced iterators, including ones that are infinite. - -That's enough about iterators. Iterator adaptors are the last concept -we need to talk about with regards to iterators. Let's get to it! - -## Iterator adaptors - -*Iterator adaptors* take an iterator and modify it somehow, producing -a new iterator. The simplest one is called `map`: - -```rust,ignore -(1..100).map(|x| x + 1); -``` - -`map` is called upon another iterator, and produces a new iterator where each -element reference has the closure it's been given as an argument called on it. -So this would give us the numbers from `2-100`. Well, almost! If you -compile the example, you'll get a warning: - -```text -warning: unused result which must be used: iterator adaptors are lazy and - do nothing unless consumed, #[warn(unused_must_use)] on by default -(1..100).map(|x| x + 1); - ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -``` - -Laziness strikes again! That closure will never execute. This example -doesn't print any numbers: - -```rust,ignore -(1..100).map(|x| println!("{}", x)); -``` - -If you are trying to execute a closure on an iterator for its side effects, -use `for` instead. - -There are tons of interesting iterator adaptors. `take(n)` will return an -iterator over the next `n` elements of the original iterator. Let's try it out -with an infinite iterator: - -```rust -for i in (1..).take(5) { - println!("{}", i); -} -``` - -This will print - -```text -1 -2 -3 -4 -5 -``` - -`filter()` is an adapter that takes a closure as an argument. This closure -returns `true` or `false`. The new iterator `filter()` produces -only the elements that the closure returns `true` for: - -```rust -for i in (1..100).filter(|&x| x % 2 == 0) { - println!("{}", i); -} -``` - -This will print all of the even numbers between one and a hundred. -(Note that, unlike `map`, the closure passed to `filter` is passed a reference -to the element instead of the element itself. The filter predicate here uses -the `&x` pattern to extract the integer. The filter closure is passed a -reference because it returns `true` or `false` instead of the element, -so the `filter` implementation must retain ownership to put the elements -into the newly constructed iterator.) - -You can chain all three things together: start with an iterator, adapt it -a few times, and then consume the result. Check it out: - -```rust -(1..) - .filter(|&x| x % 2 == 0) - .filter(|&x| x % 3 == 0) - .take(5) - .collect::<Vec<i32>>(); -``` - -This will give you a vector containing `6`, `12`, `18`, `24`, and `30`. - -This is just a small taste of what iterators, iterator adaptors, and consumers -can help you with. There are a number of really useful iterators, and you can -write your own as well. Iterators provide a safe, efficient way to manipulate -all kinds of lists. They're a little unusual at first, but if you play with -them, you'll get hooked. For a full list of the different iterators and -consumers, check out the [iterator module documentation](../std/iter/index.html). diff --git a/src/doc/book/src/lifetimes.md b/src/doc/book/src/lifetimes.md deleted file mode 100644 index 042d9af9717d0..0000000000000 --- a/src/doc/book/src/lifetimes.md +++ /dev/null @@ -1,428 +0,0 @@ -# Lifetimes - -This is the last of three sections presenting Rust’s ownership system. This is one of -Rust’s most distinct and compelling features, with which Rust developers should -become quite acquainted. Ownership is how Rust achieves its largest goal, -memory safety. There are a few distinct concepts, each with its own chapter: - -* [ownership][ownership], the key concept -* [borrowing][borrowing], and their associated feature ‘references’ -* lifetimes, which you’re reading now - -These three chapters are related, and in order. You’ll need all three to fully -understand the ownership system. - -[ownership]: ownership.html -[borrowing]: references-and-borrowing.html - -# Meta - -Before we get to the details, two important notes about the ownership system. - -Rust has a focus on safety and speed. It accomplishes these goals through many -‘zero-cost abstractions’, which means that in Rust, abstractions cost as little -as possible in order to make them work. The ownership system is a prime example -of a zero-cost abstraction. All of the analysis we’ll talk about in this guide -is _done at compile time_. You do not pay any run-time cost for any of these -features. - -However, this system does have a certain cost: learning curve. Many new users -to Rust experience something we like to call ‘fighting with the borrow -checker’, where the Rust compiler refuses to compile a program that the author -thinks is valid. This often happens because the programmer’s mental model of -how ownership should work doesn’t match the actual rules that Rust implements. -You probably will experience similar things at first. There is good news, -however: more experienced Rust developers report that once they work with the -rules of the ownership system for a period of time, they fight the borrow -checker less and less. - -With that in mind, let’s learn about lifetimes. - -# Lifetimes - -Lending out a reference to a resource that someone else owns can be -complicated. For example, imagine this set of operations: - -1. I acquire a handle to some kind of resource. -2. I lend you a reference to the resource. -3. I decide I’m done with the resource, and deallocate it, while you still have - your reference. -4. You decide to use the resource. - -Uh oh! Your reference is pointing to an invalid resource. This is called a -dangling pointer or ‘use after free’, when the resource is memory. A small -example of such a situation would be: - -```rust,compile_fail -let r; // Introduce reference: `r`. -{ - let i = 1; // Introduce scoped value: `i`. - r = &i; // Store reference of `i` in `r`. -} // `i` goes out of scope and is dropped. - -println!("{}", r); // `r` still refers to `i`. -``` - -To fix this, we have to make sure that step four never happens after step -three. In the small example above the Rust compiler is able to report the issue -as it can see the lifetimes of the various values in the function. - -When we have a function that takes arguments by reference the situation becomes -more complex. Consider the following example: - -```rust,compile_fail,E0106 -fn skip_prefix(line: &str, prefix: &str) -> &str { - // ... -# line -} - -let line = "lang:en=Hello World!"; -let lang = "en"; - -let v; -{ - let p = format!("lang:{}=", lang); // -+ `p` comes into scope. - v = skip_prefix(line, p.as_str()); // | -} // -+ `p` goes out of scope. -println!("{}", v); -``` - -Here we have a function `skip_prefix` which takes two `&str` references -as parameters and returns a single `&str` reference. We call it -by passing in references to `line` and `p`: Two variables with different -lifetimes. Now the safety of the `println!`-line depends on whether the -reference returned by `skip_prefix` function references the still living -`line` or the already dropped `p` string. - -Because of the above ambiguity, Rust will refuse to compile the example -code. To get it to compile we need to tell the compiler more about the -lifetimes of the references. This can be done by making the lifetimes -explicit in the function declaration: - -```rust -fn skip_prefix<'a, 'b>(line: &'a str, prefix: &'b str) -> &'a str { - // ... -# line -} -``` - -Let's examine the changes without going too deep into the syntax for now - -we'll get to that later. The first change was adding the `<'a, 'b>` after the -method name. This introduces two lifetime parameters: `'a` and `'b`. Next, each -reference in the function signature was associated with one of the lifetime -parameters by adding the lifetime name after the `&`. This tells the compiler -how the lifetimes between different references are related. - -As a result the compiler is now able to deduce that the return value of -`skip_prefix` has the same lifetime as the `line` parameter, which makes the `v` -reference safe to use even after the `p` goes out of scope in the original -example. - -In addition to the compiler being able to validate the usage of `skip_prefix` -return value, it can also ensure that the implementation follows the contract -established by the function declaration. This is useful especially when you are -implementing traits that are introduced [later in the book][traits]. - -**Note** It's important to understand that lifetime annotations are -_descriptive_, not _prescriptive_. This means that how long a reference is valid -is determined by the code, not by the annotations. The annotations, however, -give information about lifetimes to the compiler that uses them to check the -validity of references. The compiler can do so without annotations in simple -cases, but needs the programmer's support in complex scenarios. - -[traits]: traits.html - -# Syntax - -The `'a` reads ‘the lifetime a’. Technically, every reference has some lifetime -associated with it, but the compiler lets you elide (i.e. omit, see -["Lifetime Elision"][lifetime-elision] below) them in common cases. Before we -get to that, though, let’s look at a short example with explicit lifetimes: - -[lifetime-elision]: #lifetime-elision - -```rust,ignore -fn bar<'a>(...) -``` - -We previously talked a little about [function syntax][functions], but we didn’t -discuss the `<>`s after a function’s name. A function can have ‘generic -parameters’ between the `<>`s, of which lifetimes are one kind. We’ll discuss -other kinds of generics [later in the book][generics], but for now, let’s -focus on the lifetimes aspect. - -[functions]: functions.html -[generics]: generics.html - -We use `<>` to declare our lifetimes. This says that `bar` has one lifetime, -`'a`. If we had two reference parameters with different lifetimes, it would -look like this: - - -```rust,ignore -fn bar<'a, 'b>(...) -``` - -Then in our parameter list, we use the lifetimes we’ve named: - -```rust,ignore -...(x: &'a i32) -``` - -If we wanted a `&mut` reference, we’d do this: - -```rust,ignore -...(x: &'a mut i32) -``` - -If you compare `&mut i32` to `&'a mut i32`, they’re the same, it’s that -the lifetime `'a` has snuck in between the `&` and the `mut i32`. We read `&mut -i32` as ‘a mutable reference to an `i32`’ and `&'a mut i32` as ‘a mutable -reference to an `i32` with the lifetime `'a`’. - -# In `struct`s - -You’ll also need explicit lifetimes when working with [`struct`][structs]s that -contain references: - -```rust -struct Foo<'a> { - x: &'a i32, -} - -fn main() { - let y = &5; // This is the same as `let _y = 5; let y = &_y;`. - let f = Foo { x: y }; - - println!("{}", f.x); -} -``` - -[structs]: structs.html - -As you can see, `struct`s can also have lifetimes. In a similar way to functions, - -```rust -struct Foo<'a> { -# x: &'a i32, -# } -``` - -declares a lifetime, and - -```rust -# struct Foo<'a> { -x: &'a i32, -# } -``` - -uses it. So why do we need a lifetime here? We need to ensure that any reference -to a `Foo` cannot outlive the reference to an `i32` it contains. - -## `impl` blocks - -Let’s implement a method on `Foo`: - -```rust -struct Foo<'a> { - x: &'a i32, -} - -impl<'a> Foo<'a> { - fn x(&self) -> &'a i32 { self.x } -} - -fn main() { - let y = &5; // This is the same as `let _y = 5; let y = &_y;`. - let f = Foo { x: y }; - - println!("x is: {}", f.x()); -} -``` - -As you can see, we need to declare a lifetime for `Foo` in the `impl` line. We repeat -`'a` twice, like on functions: `impl<'a>` defines a lifetime `'a`, and `Foo<'a>` -uses it. - -## Multiple lifetimes - -If you have multiple references, you can use the same lifetime multiple times: - -```rust -fn x_or_y<'a>(x: &'a str, y: &'a str) -> &'a str { -# x -# } -``` - -This says that `x` and `y` both are alive for the same scope, and that the -return value is also alive for that scope. If you wanted `x` and `y` to have -different lifetimes, you can use multiple lifetime parameters: - -```rust -fn x_or_y<'a, 'b>(x: &'a str, y: &'b str) -> &'a str { -# x -# } -``` - -In this example, `x` and `y` have different valid scopes, but the return value -has the same lifetime as `x`. - -## Thinking in scopes - -A way to think about lifetimes is to visualize the scope that a reference is -valid for. For example: - -```rust -fn main() { - let y = &5; // -+ `y` comes into scope. - // | - // Stuff... // | - // | -} // -+ `y` goes out of scope. -``` - -Adding in our `Foo`: - -```rust -struct Foo<'a> { - x: &'a i32, -} - -fn main() { - let y = &5; // -+ `y` comes into scope. - let f = Foo { x: y }; // -+ `f` comes into scope. - // | - // Stuff... // | - // | -} // -+ `f` and `y` go out of scope. -``` - -Our `f` lives within the scope of `y`, so everything works. What if it didn’t? -This code won’t work: - -```rust,ignore -struct Foo<'a> { - x: &'a i32, -} - -fn main() { - let x; // -+ `x` comes into scope. - // | - { // | - let y = &5; // ---+ `y` comes into scope. - let f = Foo { x: y }; // ---+ `f` comes into scope. - x = &f.x; // | | This causes an error. - } // ---+ `f` and y go out of scope. - // | - println!("{}", x); // | -} // -+ `x` goes out of scope. -``` - -Whew! As you can see here, the scopes of `f` and `y` are smaller than the scope -of `x`. But when we do `x = &f.x`, we make `x` a reference to something that’s -about to go out of scope. - -Named lifetimes are a way of giving these scopes a name. Giving something a -name is the first step towards being able to talk about it. - -## 'static - -The lifetime named ‘static’ is a special lifetime. It signals that something -has the lifetime of the entire program. Most Rust programmers first come across -`'static` when dealing with strings: - -```rust -let x: &'static str = "Hello, world."; -``` - -String literals have the type `&'static str` because the reference is always -alive: they are baked into the data segment of the final binary. Another -example are globals: - -```rust -static FOO: i32 = 5; -let x: &'static i32 = &FOO; -``` - -This adds an `i32` to the data segment of the binary, and `x` is a reference -to it. - -## Lifetime Elision - -Rust supports powerful local type inference in the bodies of functions, but it -deliberately does not perform any reasoning about types for item signatures. -However, for ergonomic reasons, a very restricted secondary inference algorithm called -“lifetime elision” does apply when judging lifetimes. Lifetime elision is concerned solely with inferring -lifetime parameters using three easily memorizable and unambiguous rules. This means lifetime elision -acts as a shorthand for writing an item signature, while not hiding -away the actual types involved as full local inference would if applied to it. - -When talking about lifetime elision, we use the terms *input lifetime* and -*output lifetime*. An *input lifetime* is a lifetime associated with a parameter -of a function, and an *output lifetime* is a lifetime associated with the return -value of a function. For example, this function has an input lifetime: - -```rust,ignore -fn foo<'a>(bar: &'a str) -``` - -This one has an output lifetime: - -```rust,ignore -fn foo<'a>() -> &'a str -``` - -This one has a lifetime in both positions: - -```rust,ignore -fn foo<'a>(bar: &'a str) -> &'a str -``` - -Here are the three rules: - -* Each elided lifetime in a function’s arguments becomes a distinct lifetime - parameter. - -* If there is exactly one input lifetime, elided or not, that lifetime is - assigned to all elided lifetimes in the return values of that function. - -* If there are multiple input lifetimes, but one of them is `&self` or `&mut - self`, the lifetime of `self` is assigned to all elided output lifetimes. - -Otherwise, it is an error to elide an output lifetime. - -### Examples - -Here are some examples of functions with elided lifetimes. We’ve paired each -example of an elided lifetime with its expanded form. - -```rust,ignore -fn print(s: &str); // elided -fn print<'a>(s: &'a str); // expanded - -fn debug(lvl: u32, s: &str); // elided -fn debug<'a>(lvl: u32, s: &'a str); // expanded -``` - -In the preceding example, `lvl` doesn’t need a lifetime because it’s not a -reference (`&`). Only things relating to references (such as a `struct` -which contains a reference) need lifetimes. - -```rust,ignore -fn substr(s: &str, until: u32) -> &str; // elided -fn substr<'a>(s: &'a str, until: u32) -> &'a str; // expanded - -fn get_str() -> &str; // ILLEGAL, no inputs - -fn frob(s: &str, t: &str) -> &str; // ILLEGAL, two inputs -fn frob<'a, 'b>(s: &'a str, t: &'b str) -> &str; // Expanded: Output lifetime is ambiguous - -fn get_mut(&mut self) -> &mut T; // elided -fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded - -fn args<T: ToCStr>(&mut self, args: &[T]) -> &mut Command; // elided -fn args<'a, 'b, T: ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command; // expanded - -fn new(buf: &mut [u8]) -> BufWriter; // elided -fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a>; // expanded -``` diff --git a/src/doc/book/src/loops.md b/src/doc/book/src/loops.md deleted file mode 100644 index b7658d57a9e16..0000000000000 --- a/src/doc/book/src/loops.md +++ /dev/null @@ -1,211 +0,0 @@ -# Loops - -Rust currently provides three approaches to performing some kind of iterative activity. They are: `loop`, `while` and `for`. Each approach has its own set of uses. - -## loop - -The infinite `loop` is the simplest form of loop available in Rust. Using the keyword `loop`, Rust provides a way to loop indefinitely until some terminating statement is reached. Rust's infinite `loop`s look like this: - -```rust,ignore -loop { - println!("Loop forever!"); -} -``` - -## while - -Rust also has a `while` loop. It looks like this: - -```rust -let mut x = 5; // mut x: i32 -let mut done = false; // mut done: bool - -while !done { - x += x - 3; - - println!("{}", x); - - if x % 5 == 0 { - done = true; - } -} -``` - -`while` loops are the correct choice when you’re not sure how many times -you need to loop. - -If you need an infinite loop, you may be tempted to write this: - -```rust,ignore -while true { -``` - -However, `loop` is far better suited to handle this case: - -```rust,ignore -loop { -``` - -Rust’s control-flow analysis treats this construct differently than a `while -true`, since we know that it will always loop. In general, the more information -we can give to the compiler, the better it can do with safety and code -generation, so you should always prefer `loop` when you plan to loop -infinitely. - -## for - -The `for` loop is used to loop a particular number of times. Rust’s `for` loops -work a bit differently than in other systems languages, however. Rust’s `for` -loop doesn’t look like this “C-style” `for` loop: - -```c -for (x = 0; x < 10; x++) { - printf( "%d\n", x ); -} -``` - -Instead, it looks like this: - -```rust -for x in 0..10 { - println!("{}", x); // x: i32 -} -``` - -In slightly more abstract terms, - -```rust,ignore -for var in expression { - code -} -``` - -The expression is an item that can be converted into an [iterator] using -[`IntoIterator`]. The iterator gives back a series of elements. Each element is -one iteration of the loop. That value is then bound to the name `var`, which is -valid for the loop body. Once the body is over, the next value is fetched from -the iterator, and we loop another time. When there are no more values, the `for` -loop is over. - -[iterator]: iterators.html -[`IntoIterator`]: ../std/iter/trait.IntoIterator.html - -In our example, `0..10` is an expression that takes a start and an end position, -and gives an iterator over those values. The upper bound is exclusive, though, -so our loop will print `0` through `9`, not `10`. - -Rust does not have the “C-style” `for` loop on purpose. Manually controlling -each element of the loop is complicated and error prone, even for experienced C -developers. - -### Enumerate - -When you need to keep track of how many times you have already looped, you can -use the `.enumerate()` function. - -#### On ranges: - -```rust -for (index, value) in (5..10).enumerate() { - println!("index = {} and value = {}", index, value); -} -``` - -Outputs: - -```text -index = 0 and value = 5 -index = 1 and value = 6 -index = 2 and value = 7 -index = 3 and value = 8 -index = 4 and value = 9 -``` - -Don't forget to add the parentheses around the range. - -#### On iterators: - -```rust -let lines = "hello\nworld".lines(); - -for (linenumber, line) in lines.enumerate() { - println!("{}: {}", linenumber, line); -} -``` - -Outputs: - -```text -0: hello -1: world -``` - -## Ending iteration early - -Let’s take a look at that `while` loop we had earlier: - -```rust -let mut x = 5; -let mut done = false; - -while !done { - x += x - 3; - - println!("{}", x); - - if x % 5 == 0 { - done = true; - } -} -``` - -We had to keep a dedicated `mut` boolean variable binding, `done`, to know -when we should exit out of the loop. Rust has two keywords to help us with -modifying iteration: `break` and `continue`. - -In this case, we can write the loop in a better way with `break`: - -```rust -let mut x = 5; - -loop { - x += x - 3; - - println!("{}", x); - - if x % 5 == 0 { break; } -} -``` - -We now loop forever with `loop` and use `break` to break out early. Issuing an explicit `return` statement will also serve to terminate the loop early. - -`continue` is similar, but instead of ending the loop, it goes to the next -iteration. This will only print the odd numbers: - -```rust -for x in 0..10 { - if x % 2 == 0 { continue; } - - println!("{}", x); -} -``` - -## Loop labels - -You may also encounter situations where you have nested loops and need to -specify which one your `break` or `continue` statement is for. Like most -other languages, by default a `break` or `continue` will apply to innermost -loop. In a situation where you would like to `break` or `continue` for one -of the outer loops, you can use labels to specify which loop the `break` or - `continue` statement applies to. This will only print when both `x` and `y` are - odd: - -```rust -'outer: for x in 0..10 { - 'inner: for y in 0..10 { - if x % 2 == 0 { continue 'outer; } // Continues the loop over `x`. - if y % 2 == 0 { continue 'inner; } // Continues the loop over `y`. - println!("x: {}, y: {}", x, y); - } -} -``` diff --git a/src/doc/book/src/macros.md b/src/doc/book/src/macros.md deleted file mode 100644 index fa8e8975a5b01..0000000000000 --- a/src/doc/book/src/macros.md +++ /dev/null @@ -1,763 +0,0 @@ -# Macros - -By now you’ve learned about many of the tools Rust provides for abstracting and -reusing code. These units of code reuse have a rich semantic structure. For -example, functions have a type signature, type parameters have trait bounds, -and overloaded functions must belong to a particular trait. - -This structure means that Rust’s core abstractions have powerful compile-time -correctness checking. But this comes at the price of reduced flexibility. If -you visually identify a pattern of repeated code, you may find it’s difficult -or cumbersome to express that pattern as a generic function, a trait, or -anything else within Rust’s semantics. - -Macros allow us to abstract at a syntactic level. A macro invocation is -shorthand for an "expanded" syntactic form. This expansion happens early in -compilation, before any static checking. As a result, macros can capture many -patterns of code reuse that Rust’s core abstractions cannot. - -The drawback is that macro-based code can be harder to understand, because -fewer of the built-in rules apply. Like an ordinary function, a well-behaved -macro can be used without understanding its implementation. However, it can be -difficult to design a well-behaved macro! Additionally, compiler errors in -macro code are harder to interpret, because they describe problems in the -expanded code, not the source-level form that developers use. - -These drawbacks make macros something of a "feature of last resort". That’s not -to say that macros are bad; they are part of Rust because sometimes they’re -needed for truly concise, well-abstracted code. Just keep this tradeoff in -mind. - -# Defining a macro - -You may have seen the `vec!` macro, used to initialize a [vector][vector] with -any number of elements. - -[vector]: vectors.html - -```rust -let x: Vec<u32> = vec![1, 2, 3]; -# assert_eq!(x, [1, 2, 3]); -``` - -This can’t be an ordinary function, because it takes any number of arguments. -But we can imagine it as syntactic shorthand for - -```rust -let x: Vec<u32> = { - let mut temp_vec = Vec::new(); - temp_vec.push(1); - temp_vec.push(2); - temp_vec.push(3); - temp_vec -}; -# assert_eq!(x, [1, 2, 3]); -``` - -We can implement this shorthand, using a macro: [^actual] - -[^actual]: The actual definition of `vec!` in libcollections differs from the - one presented here, for reasons of efficiency and reusability. - -```rust -macro_rules! vec { - ( $( $x:expr ),* ) => { - { - let mut temp_vec = Vec::new(); - $( - temp_vec.push($x); - )* - temp_vec - } - }; -} -# fn main() { -# assert_eq!(vec![1,2,3], [1, 2, 3]); -# } -``` - -Whoa, that’s a lot of new syntax! Let’s break it down. - -```rust,ignore -macro_rules! vec { ... } -``` - -This says we’re defining a macro named `vec`, much as `fn vec` would define a -function named `vec`. In prose, we informally write a macro’s name with an -exclamation point, e.g. `vec!`. The exclamation point is part of the invocation -syntax and serves to distinguish a macro from an ordinary function. - -## Matching - -The macro is defined through a series of rules, which are pattern-matching -cases. Above, we had - -```rust,ignore -( $( $x:expr ),* ) => { ... }; -``` - -This is like a `match` expression arm, but the matching happens on Rust syntax -trees, at compile time. The semicolon is optional on the last (here, only) -case. The "pattern" on the left-hand side of `=>` is known as a ‘matcher’. -These have [their own little grammar] within the language. - -[their own little grammar]: ../reference/macros.html - -The matcher `$x:expr` will match any Rust expression, binding that syntax tree -to the ‘metavariable’ `$x`. The identifier `expr` is a ‘fragment specifier’; -the full possibilities are enumerated later in this chapter. -Surrounding the matcher with `$(...),*` will match zero or more expressions, -separated by commas. - -Aside from the special matcher syntax, any Rust tokens that appear in a matcher -must match exactly. For example, - -```rust,ignore -macro_rules! foo { - (x => $e:expr) => (println!("mode X: {}", $e)); - (y => $e:expr) => (println!("mode Y: {}", $e)); -} - -fn main() { - foo!(y => 3); -} -``` - -will print - -```text -mode Y: 3 -``` - -With - -```rust,ignore -foo!(z => 3); -``` - -we get the compiler error - -```text -error: no rules expected the token `z` -``` - -## Expansion - -The right-hand side of a macro rule is ordinary Rust syntax, for the most part. -But we can splice in bits of syntax captured by the matcher. From the original -example: - -```rust,ignore -$( - temp_vec.push($x); -)* -``` - -Each matched expression `$x` will produce a single `push` statement in the -macro expansion. The repetition in the expansion proceeds in "lockstep" with -repetition in the matcher (more on this in a moment). - -Because `$x` was already declared as matching an expression, we don’t repeat -`:expr` on the right-hand side. Also, we don’t include a separating comma as -part of the repetition operator. Instead, we have a terminating semicolon -within the repeated block. - -Another detail: the `vec!` macro has *two* pairs of braces on the right-hand -side. They are often combined like so: - -```rust,ignore -macro_rules! foo { - () => {{ - ... - }} -} -``` - -The outer braces are part of the syntax of `macro_rules!`. In fact, you can use -`()` or `[]` instead. They simply delimit the right-hand side as a whole. - -The inner braces are part of the expanded syntax. Remember, the `vec!` macro is -used in an expression context. To write an expression with multiple statements, -including `let`-bindings, we use a block. If your macro expands to a single -expression, you don’t need this extra layer of braces. - -Note that we never *declared* that the macro produces an expression. In fact, -this is not determined until we use the macro as an expression. With care, you -can write a macro whose expansion works in several contexts. For example, -shorthand for a data type could be valid as either an expression or a pattern. - -## Repetition - -The repetition operator follows two principal rules: - -1. `$(...)*` walks through one "layer" of repetitions, for all of the `$name`s - it contains, in lockstep, and -2. each `$name` must be under at least as many `$(...)*`s as it was matched - against. If it is under more, it’ll be duplicated, as appropriate. - -This baroque macro illustrates the duplication of variables from outer -repetition levels. - -```rust -macro_rules! o_O { - ( - $( - $x:expr; [ $( $y:expr ),* ] - );* - ) => { - &[ $($( $x + $y ),*),* ] - } -} - -fn main() { - let a: &[i32] - = o_O!(10; [1, 2, 3]; - 20; [4, 5, 6]); - - assert_eq!(a, [11, 12, 13, 24, 25, 26]); -} -``` - -That’s most of the matcher syntax. These examples use `$(...)*`, which is a -"zero or more" match. Alternatively you can write `$(...)+` for a "one or -more" match. Both forms optionally include a separator, which can be any token -except `+` or `*`. - -This system is based on -"[Macro-by-Example](https://www.cs.indiana.edu/ftp/techreports/TR206.pdf)" -(PDF link). - -# Hygiene - -Some languages implement macros using simple text substitution, which leads to -various problems. For example, this C program prints `13` instead of the -expected `25`. - -```text -#define FIVE_TIMES(x) 5 * x - -int main() { - printf("%d\n", FIVE_TIMES(2 + 3)); - return 0; -} -``` - -After expansion we have `5 * 2 + 3`, and multiplication has greater precedence -than addition. If you’ve used C macros a lot, you probably know the standard -idioms for avoiding this problem, as well as five or six others. In Rust, we -don’t have to worry about it. - -```rust -macro_rules! five_times { - ($x:expr) => (5 * $x); -} - -fn main() { - assert_eq!(25, five_times!(2 + 3)); -} -``` - -The metavariable `$x` is parsed as a single expression node, and keeps its -place in the syntax tree even after substitution. - -Another common problem in macro systems is ‘variable capture’. Here’s a C -macro using a block with multiple statements. - -```text -#define LOG(msg) do { \ - int state = get_log_state(); \ - if (state > 0) { \ - printf("log(%d): %s\n", state, msg); \ - } \ -} while (0) -``` - -Here’s a simple use case that goes terribly wrong: - -```text -const char *state = "reticulating splines"; -LOG(state); -``` - -This expands to - -```text -const char *state = "reticulating splines"; -do { - int state = get_log_state(); - if (state > 0) { - printf("log(%d): %s\n", state, state); - } -} while (0); -``` - -The second variable named `state` shadows the first one. This is a problem -because the print statement should refer to both of them. - -The equivalent Rust macro has the desired behavior. - -```rust -# fn get_log_state() -> i32 { 3 } -macro_rules! log { - ($msg:expr) => {{ - let state: i32 = get_log_state(); - if state > 0 { - println!("log({}): {}", state, $msg); - } - }}; -} - -fn main() { - let state: &str = "reticulating splines"; - log!(state); -} -``` - -This works because Rust has a [hygienic macro system]. Each macro expansion -happens in a distinct ‘syntax context’, and each variable is tagged with the -syntax context where it was introduced. It’s as though the variable `state` -inside `main` is painted a different "color" from the variable `state` inside -the macro, and therefore they don’t conflict. - -[hygienic macro system]: https://en.wikipedia.org/wiki/Hygienic_macro - -This also restricts the ability of macros to introduce new bindings at the -invocation site. Code such as the following will not work: - -```rust,ignore -macro_rules! foo { - () => (let x = 3;); -} - -fn main() { - foo!(); - println!("{}", x); -} -``` - -Instead you need to pass the variable name into the invocation, so that it’s -tagged with the right syntax context. - -```rust -macro_rules! foo { - ($v:ident) => (let $v = 3;); -} - -fn main() { - foo!(x); - println!("{}", x); -} -``` - -This holds for `let` bindings and loop labels, but not for [items][items]. -So the following code does compile: - -```rust -macro_rules! foo { - () => (fn x() { }); -} - -fn main() { - foo!(); - x(); -} -``` - -[items]: ../reference/items.html - -# Recursive macros - -A macro’s expansion can include more macro invocations, including invocations -of the very same macro being expanded. These recursive macros are useful for -processing tree-structured input, as illustrated by this (simplistic) HTML -shorthand: - -```rust -# #![allow(unused_must_use)] -macro_rules! write_html { - ($w:expr, ) => (()); - - ($w:expr, $e:tt) => (write!($w, "{}", $e)); - - ($w:expr, $tag:ident [ $($inner:tt)* ] $($rest:tt)*) => {{ - write!($w, "<{}>", stringify!($tag)); - write_html!($w, $($inner)*); - write!($w, "</{}>", stringify!($tag)); - write_html!($w, $($rest)*); - }}; -} - -fn main() { -# // FIXME(#21826) - use std::fmt::Write; - let mut out = String::new(); - - write_html!(&mut out, - html[ - head[title["Macros guide"]] - body[h1["Macros are the best!"]] - ]); - - assert_eq!(out, - "<html><head><title>Macros guide</title></head>\ - <body><h1>Macros are the best!</h1></body></html>"); -} -``` - -# Debugging macro code - -To see the results of expanding macros, run `rustc --pretty expanded`. The -output represents a whole crate, so you can also feed it back in to `rustc`, -which will sometimes produce better error messages than the original -compilation. Note that the `--pretty expanded` output may have a different -meaning if multiple variables of the same name (but different syntax contexts) -are in play in the same scope. In this case `--pretty expanded,hygiene` will -tell you about the syntax contexts. - -`rustc` provides two syntax extensions that help with macro debugging. For now, -they are unstable and require feature gates. - -* `log_syntax!(...)` will print its arguments to standard output, at compile - time, and "expand" to nothing. - -* `trace_macros!(true)` will enable a compiler message every time a macro is - expanded. Use `trace_macros!(false)` later in expansion to turn it off. - -# Syntactic requirements - -Even when Rust code contains un-expanded macros, it can be parsed as a full -[syntax tree][ast]. This property can be very useful for editors and other -tools that process code. It also has a few consequences for the design of -Rust’s macro system. - -[ast]: glossary.html#abstract-syntax-tree - -One consequence is that Rust must determine, when it parses a macro invocation, -whether the macro stands in for - -* zero or more items, -* zero or more methods, -* an expression, -* a statement, or -* a pattern. - -A macro invocation within a block could stand for some items, or for an -expression / statement. Rust uses a simple rule to resolve this ambiguity. A -macro invocation that stands for items must be either - -* delimited by curly braces, e.g. `foo! { ... }`, or -* terminated by a semicolon, e.g. `foo!(...);` - -Another consequence of pre-expansion parsing is that the macro invocation must -consist of valid Rust tokens. Furthermore, parentheses, brackets, and braces -must be balanced within a macro invocation. For example, `foo!([)` is -forbidden. This allows Rust to know where the macro invocation ends. - -More formally, the macro invocation body must be a sequence of ‘token trees’. -A token tree is defined recursively as either - -* a sequence of token trees surrounded by matching `()`, `[]`, or `{}`, or -* any other single token. - -Within a matcher, each metavariable has a ‘fragment specifier’, identifying -which syntactic form it matches. - -* `ident`: an identifier. Examples: `x`; `foo`. -* `path`: a qualified name. Example: `T::SpecialA`. -* `expr`: an expression. Examples: `2 + 2`; `if true { 1 } else { 2 }`; `f(42)`. -* `ty`: a type. Examples: `i32`; `Vec<(char, String)>`; `&T`. -* `pat`: a pattern. Examples: `Some(t)`; `(17, 'a')`; `_`. -* `stmt`: a single statement. Example: `let x = 3`. -* `block`: a brace-delimited sequence of statements and optionally an expression. Example: - `{ log(error, "hi"); return 12; }`. -* `item`: an [item][item]. Examples: `fn foo() { }`; `struct Bar;`. -* `meta`: a "meta item", as found in attributes. Example: `cfg(target_os = "windows")`. -* `tt`: a single token tree. - -There are additional rules regarding the next token after a metavariable: - -* `expr` and `stmt` variables may only be followed by one of: `=> , ;` -* `ty` and `path` variables may only be followed by one of: `=> , = | ; : > [ { as where` -* `pat` variables may only be followed by one of: `=> , = | if in` -* Other variables may be followed by any token. - -These rules provide some flexibility for Rust’s syntax to evolve without -breaking existing macros. - -The macro system does not deal with parse ambiguity at all. For example, the -grammar `$($i:ident)* $e:expr` will always fail to parse, because the parser would -be forced to choose between parsing `$i` and parsing `$e`. Changing the -invocation syntax to put a distinctive token in front can solve the problem. In -this case, you can write `$(I $i:ident)* E $e:expr`. - -[item]: ../reference/items.html - -# Scoping and macro import/export - -Macros are expanded at an early stage in compilation, before name resolution. -One downside is that scoping works differently for macros, compared to other -constructs in the language. - -Definition and expansion of macros both happen in a single depth-first, -lexical-order traversal of a crate’s source. So a macro defined at module scope -is visible to any subsequent code in the same module, which includes the body -of any subsequent child `mod` items. - -A macro defined within the body of a single `fn`, or anywhere else not at -module scope, is visible only within that item. - -If a module has the `macro_use` attribute, its macros are also visible in its -parent module after the child’s `mod` item. If the parent also has `macro_use` -then the macros will be visible in the grandparent after the parent’s `mod` -item, and so forth. - -The `macro_use` attribute can also appear on `extern crate`. In this context -it controls which macros are loaded from the external crate, e.g. - -```rust,ignore -#[macro_use(foo, bar)] -extern crate baz; -``` - -If the attribute is given simply as `#[macro_use]`, all macros are loaded. If -there is no `#[macro_use]` attribute then no macros are loaded. Only macros -defined with the `#[macro_export]` attribute may be loaded. - -To load a crate’s macros without linking it into the output, use `#[no_link]` -as well. - -An example: - -```rust -macro_rules! m1 { () => (()) } - -// Visible here: `m1`. - -mod foo { - // Visible here: `m1`. - - #[macro_export] - macro_rules! m2 { () => (()) } - - // Visible here: `m1`, `m2`. -} - -// Visible here: `m1`. - -macro_rules! m3 { () => (()) } - -// Visible here: `m1`, `m3`. - -#[macro_use] -mod bar { - // Visible here: `m1`, `m3`. - - macro_rules! m4 { () => (()) } - - // Visible here: `m1`, `m3`, `m4`. -} - -// Visible here: `m1`, `m3`, `m4`. -# fn main() { } -``` - -When this library is loaded with `#[macro_use] extern crate`, only `m2` will -be imported. - -The Rust Reference has a [listing of macro-related -attributes](../reference/attributes.html#macro-related-attributes). - -# The variable `$crate` - -A further difficulty occurs when a macro is used in multiple crates. Say that -`mylib` defines - -```rust -pub fn increment(x: u32) -> u32 { - x + 1 -} - -#[macro_export] -macro_rules! inc_a { - ($x:expr) => ( ::increment($x) ) -} - -#[macro_export] -macro_rules! inc_b { - ($x:expr) => ( ::mylib::increment($x) ) -} -# fn main() { } -``` - -`inc_a` only works within `mylib`, while `inc_b` only works outside the -library. Furthermore, `inc_b` will break if the user imports `mylib` under -another name. - -Rust does not (yet) have a hygiene system for crate references, but it does -provide a simple workaround for this problem. Within a macro imported from a -crate named `foo`, the special macro variable `$crate` will expand to `::foo`. -By contrast, when a macro is defined and then used in the same crate, `$crate` -will expand to nothing. This means we can write - -```rust -#[macro_export] -macro_rules! inc { - ($x:expr) => ( $crate::increment($x) ) -} -# fn main() { } -``` - -to define a single macro that works both inside and outside our library. The -function name will expand to either `::increment` or `::mylib::increment`. - -To keep this system simple and correct, `#[macro_use] extern crate ...` may -only appear at the root of your crate, not inside `mod`. - -# The deep end - -The introductory chapter mentioned recursive macros, but it did not give the -full story. Recursive macros are useful for another reason: Each recursive -invocation gives you another opportunity to pattern-match the macro’s -arguments. - -As an extreme example, it is possible, though hardly advisable, to implement -the [Bitwise Cyclic Tag](https://esolangs.org/wiki/Bitwise_Cyclic_Tag) automaton -within Rust’s macro system. - -```rust -macro_rules! bct { - // cmd 0: d ... => ... - (0, $($ps:tt),* ; $_d:tt) - => (bct!($($ps),*, 0 ; )); - (0, $($ps:tt),* ; $_d:tt, $($ds:tt),*) - => (bct!($($ps),*, 0 ; $($ds),*)); - - // cmd 1p: 1 ... => 1 ... p - (1, $p:tt, $($ps:tt),* ; 1) - => (bct!($($ps),*, 1, $p ; 1, $p)); - (1, $p:tt, $($ps:tt),* ; 1, $($ds:tt),*) - => (bct!($($ps),*, 1, $p ; 1, $($ds),*, $p)); - - // cmd 1p: 0 ... => 0 ... - (1, $p:tt, $($ps:tt),* ; $($ds:tt),*) - => (bct!($($ps),*, 1, $p ; $($ds),*)); - - // Halt on empty data string: - ( $($ps:tt),* ; ) - => (()); -} -``` - -Exercise: use macros to reduce duplication in the above definition of the -`bct!` macro. - -# Common macros - -Here are some common macros you’ll see in Rust code. - -## panic! - -This macro causes the current thread to panic. You can give it a message -to panic with: - -```rust,should_panic -panic!("oh no!"); -``` - -## vec! - -The `vec!` macro is used throughout the book, so you’ve probably seen it -already. It creates `Vec<T>`s with ease: - -```rust -let v = vec![1, 2, 3, 4, 5]; -``` - -It also lets you make vectors with repeating values. For example, a hundred -zeroes: - -```rust -let v = vec![0; 100]; -``` - -## assert! and assert_eq! - -These two macros are used in tests. `assert!` takes a boolean. `assert_eq!` -takes two values and checks them for equality. `true` passes, `false` `panic!`s. -Like this: - -```rust,should_panic -// A-ok! - -assert!(true); -assert_eq!(5, 3 + 2); - -// Nope :( - -assert!(5 < 3); -assert_eq!(5, 3); -``` - -## try! - -`try!` is used for error handling. It takes something that can return a -`Result<T, E>`, and gives `T` if it’s a `Ok<T>`, and `return`s with the -`Err(E)` if it’s that. Like this: - -```rust,no_run -use std::fs::File; - -fn foo() -> std::io::Result<()> { - let f = try!(File::create("foo.txt")); - - Ok(()) -} -``` - -This is cleaner than doing this: - -```rust,no_run -use std::fs::File; - -fn foo() -> std::io::Result<()> { - let f = File::create("foo.txt"); - - let f = match f { - Ok(t) => t, - Err(e) => return Err(e), - }; - - Ok(()) -} -``` - -## unreachable! - -This macro is used when you think some code should never execute: - -```rust -if false { - unreachable!(); -} -``` - -Sometimes, the compiler may make you have a different branch that you know -will never, ever run. In these cases, use this macro, so that if you end -up wrong, you’ll get a `panic!` about it. - -```rust -let x: Option<i32> = None; - -match x { - Some(_) => unreachable!(), - None => println!("I know x is None!"), -} -``` - -## unimplemented! - -The `unimplemented!` macro can be used when you’re trying to get your functions -to typecheck, and don’t want to worry about writing out the body of the -function. One example of this situation is implementing a trait with multiple -required methods, where you want to tackle one at a time. Define the others -as `unimplemented!` until you’re ready to write them. diff --git a/src/doc/book/src/match.md b/src/doc/book/src/match.md deleted file mode 100644 index b1e26a9c9d3cd..0000000000000 --- a/src/doc/book/src/match.md +++ /dev/null @@ -1,100 +0,0 @@ -# Match - -Often, a simple [`if`][if]/`else` isn’t enough, because you have more than two -possible options. Also, conditions can get quite complex. Rust -has a keyword, `match`, that allows you to replace complicated `if`/`else` -groupings with something more powerful. Check it out: - -```rust -let x = 5; - -match x { - 1 => println!("one"), - 2 => println!("two"), - 3 => println!("three"), - 4 => println!("four"), - 5 => println!("five"), - _ => println!("something else"), -} -``` - -[if]: if.html - -`match` takes an expression and then branches based on its value. Each ‘arm’ of -the branch is of the form `val => expression`. When the value matches, that arm’s -expression will be evaluated. It’s called `match` because of the term ‘pattern -matching’, which `match` is an implementation of. There’s a [separate section on -patterns][patterns] that covers all the patterns that are possible here. - -[patterns]: patterns.html - -One of the many advantages of `match` is it enforces ‘exhaustiveness checking’. -For example if we remove the last arm with the underscore `_`, the compiler will -give us an error: - -```text -error: non-exhaustive patterns: `_` not covered -``` - -Rust is telling us that we forgot some value. The compiler infers from `x` that it -can have any 32bit integer value; for example -2,147,483,648 to 2,147,483,647. The `_` acts -as a 'catch-all', and will catch all possible values that *aren't* specified in -an arm of `match`. As you can see in the previous example, we provide `match` -arms for integers 1-5, if `x` is 6 or any other value, then it is caught by `_`. - -`match` is also an expression, which means we can use it on the right-hand -side of a `let` binding or directly where an expression is used: - -```rust -let x = 5; - -let number = match x { - 1 => "one", - 2 => "two", - 3 => "three", - 4 => "four", - 5 => "five", - _ => "something else", -}; -``` - -Sometimes it’s a nice way of converting something from one type to another; in -this example the integers are converted to `String`. - -# Matching on enums - -Another important use of the `match` keyword is to process the possible -variants of an enum: - -```rust -enum Message { - Quit, - ChangeColor(i32, i32, i32), - Move { x: i32, y: i32 }, - Write(String), -} - -fn quit() { /* ... */ } -fn change_color(r: i32, g: i32, b: i32) { /* ... */ } -fn move_cursor(x: i32, y: i32) { /* ... */ } - -fn process_message(msg: Message) { - match msg { - Message::Quit => quit(), - Message::ChangeColor(r, g, b) => change_color(r, g, b), - Message::Move { x, y: new_name_for_y } => move_cursor(x, new_name_for_y), - Message::Write(s) => println!("{}", s), - }; -} -``` - -Again, the Rust compiler checks exhaustiveness, so it demands that you -have a match arm for every variant of the enum. If you leave one off, it -will give you a compile-time error unless you use `_` or provide all possible -arms. - -Unlike the previous uses of `match`, you can’t use the normal `if` -statement to do this. You can use the [`if let`][if-let] statement, -which can be seen as an abbreviated form of `match`. - -[if-let]: if-let.html diff --git a/src/doc/book/src/method-syntax.md b/src/doc/book/src/method-syntax.md deleted file mode 100644 index 0404a5c992ba3..0000000000000 --- a/src/doc/book/src/method-syntax.md +++ /dev/null @@ -1,259 +0,0 @@ -# Method Syntax - -Functions are great, but if you want to call a bunch of them on some data, it -can be awkward. Consider this code: - -```rust,ignore -baz(bar(foo)); -``` - -We would read this left-to-right, and so we see ‘baz bar foo’. But this isn’t the -order that the functions would get called in, that’s inside-out: ‘foo bar baz’. -Wouldn’t it be nice if we could do this instead? - -```rust,ignore -foo.bar().baz(); -``` - -Luckily, as you may have guessed with the leading question, you can! Rust provides -the ability to use this ‘method call syntax’ via the `impl` keyword. - -# Method calls - -Here’s how it works: - -```rust -struct Circle { - x: f64, - y: f64, - radius: f64, -} - -impl Circle { - fn area(&self) -> f64 { - std::f64::consts::PI * (self.radius * self.radius) - } -} - -fn main() { - let c = Circle { x: 0.0, y: 0.0, radius: 2.0 }; - println!("{}", c.area()); -} -``` - -This will print `12.566371`. - -We’ve made a `struct` that represents a circle. We then write an `impl` block, -and inside it, define a method, `area`. - -Methods take a special first parameter, of which there are three variants: -`self`, `&self`, and `&mut self`. You can think of this first parameter as -being the `foo` in `foo.bar()`. The three variants correspond to the three -kinds of things `foo` could be: `self` if it’s a value on the stack, -`&self` if it’s a reference, and `&mut self` if it’s a mutable reference. -Because we took the `&self` parameter to `area`, we can use it like any -other parameter. Because we know it’s a `Circle`, we can access the `radius` -like we would with any other `struct`. - -We should default to using `&self`, as you should prefer borrowing over taking -ownership, as well as taking immutable references over mutable ones. Here’s an -example of all three variants: - -```rust -struct Circle { - x: f64, - y: f64, - radius: f64, -} - -impl Circle { - fn reference(&self) { - println!("taking self by reference!"); - } - - fn mutable_reference(&mut self) { - println!("taking self by mutable reference!"); - } - - fn takes_ownership(self) { - println!("taking ownership of self!"); - } -} -``` - -You can use as many `impl` blocks as you’d like. The previous example could -have also been written like this: - -```rust -struct Circle { - x: f64, - y: f64, - radius: f64, -} - -impl Circle { - fn reference(&self) { - println!("taking self by reference!"); - } -} - -impl Circle { - fn mutable_reference(&mut self) { - println!("taking self by mutable reference!"); - } -} - -impl Circle { - fn takes_ownership(self) { - println!("taking ownership of self!"); - } -} -``` - -# Chaining method calls - -So, now we know how to call a method, such as `foo.bar()`. But what about our -original example, `foo.bar().baz()`? This is called ‘method chaining’. Let’s -look at an example: - -```rust -struct Circle { - x: f64, - y: f64, - radius: f64, -} - -impl Circle { - fn area(&self) -> f64 { - std::f64::consts::PI * (self.radius * self.radius) - } - - fn grow(&self, increment: f64) -> Circle { - Circle { x: self.x, y: self.y, radius: self.radius + increment } - } -} - -fn main() { - let c = Circle { x: 0.0, y: 0.0, radius: 2.0 }; - println!("{}", c.area()); - - let d = c.grow(2.0).area(); - println!("{}", d); -} -``` - -Check the return type: - -```rust -# struct Circle; -# impl Circle { -fn grow(&self, increment: f64) -> Circle { -# Circle } } -``` - -We say we’re returning a `Circle`. With this method, we can grow a new -`Circle` to any arbitrary size. - -# Associated functions - -You can also define associated functions that do not take a `self` parameter. -Here’s a pattern that’s very common in Rust code: - -```rust -struct Circle { - x: f64, - y: f64, - radius: f64, -} - -impl Circle { - fn new(x: f64, y: f64, radius: f64) -> Circle { - Circle { - x: x, - y: y, - radius: radius, - } - } -} - -fn main() { - let c = Circle::new(0.0, 0.0, 2.0); -} -``` - -This ‘associated function’ builds a new `Circle` for us. Note that associated -functions are called with the `Struct::function()` syntax, rather than the -`ref.method()` syntax. Some other languages call associated functions ‘static -methods’. - -# Builder Pattern - -Let’s say that we want our users to be able to create `Circle`s, but we will -allow them to only set the properties they care about. Otherwise, the `x` -and `y` attributes will be `0.0`, and the `radius` will be `1.0`. Rust doesn’t -have method overloading, named arguments, or variable arguments. We employ -the builder pattern instead. It looks like this: - -```rust -struct Circle { - x: f64, - y: f64, - radius: f64, -} - -impl Circle { - fn area(&self) -> f64 { - std::f64::consts::PI * (self.radius * self.radius) - } -} - -struct CircleBuilder { - x: f64, - y: f64, - radius: f64, -} - -impl CircleBuilder { - fn new() -> CircleBuilder { - CircleBuilder { x: 0.0, y: 0.0, radius: 1.0, } - } - - fn x(&mut self, coordinate: f64) -> &mut CircleBuilder { - self.x = coordinate; - self - } - - fn y(&mut self, coordinate: f64) -> &mut CircleBuilder { - self.y = coordinate; - self - } - - fn radius(&mut self, radius: f64) -> &mut CircleBuilder { - self.radius = radius; - self - } - - fn finalize(&self) -> Circle { - Circle { x: self.x, y: self.y, radius: self.radius } - } -} - -fn main() { - let c = CircleBuilder::new() - .x(1.0) - .y(2.0) - .radius(2.0) - .finalize(); - - println!("area: {}", c.area()); - println!("x: {}", c.x); - println!("y: {}", c.y); -} -``` - -What we’ve done here is make another `struct`, `CircleBuilder`. We’ve defined our -builder methods on it. We’ve also defined our `area()` method on `Circle`. We -also made one more method on `CircleBuilder`: `finalize()`. This method creates -our final `Circle` from the builder. Now, we’ve used the type system to enforce -our concerns: we can use the methods on `CircleBuilder` to constrain making -`Circle`s in any way we choose. diff --git a/src/doc/book/src/mutability.md b/src/doc/book/src/mutability.md deleted file mode 100644 index fa7a259392a7e..0000000000000 --- a/src/doc/book/src/mutability.md +++ /dev/null @@ -1,181 +0,0 @@ -# Mutability - -Mutability, the ability to change something, works a bit differently in Rust -than in other languages. The first aspect of mutability is its non-default -status: - -```rust,ignore -let x = 5; -x = 6; // Error! -``` - -We can introduce mutability with the `mut` keyword: - -```rust -let mut x = 5; - -x = 6; // No problem! -``` - -This is a mutable [variable binding][vb]. When a binding is mutable, it means -you’re allowed to change what the binding points to. So in the above example, -it’s not so much that the value at `x` is changing, but that the binding -changed from one `i32` to another. - -[vb]: variable-bindings.html - -You can also create a [reference][ref] to it, using `&x`, but if you want to use the reference to change it, you will need a mutable reference: - -```rust -let mut x = 5; -let y = &mut x; -``` - -[ref]: references-and-borrowing.html - -`y` is an immutable binding to a mutable reference, which means that you can’t bind 'y' to something else (`y = &mut z`), but `y` can be used to bind `x` to something else (`*y = 5`). A subtle distinction. - -Of course, if you need both: - -```rust -let mut x = 5; -let mut y = &mut x; -``` - -Now `y` can be bound to another value, and the value it’s referencing can be -changed. - -It’s important to note that `mut` is part of a [pattern][pattern], so you -can do things like this: - -```rust -let (mut x, y) = (5, 6); - -fn foo(mut x: i32) { -# } -``` - -Note that here, the `x` is mutable, but not the `y`. - -[pattern]: patterns.html - -# Interior vs. Exterior Mutability - -However, when we say something is ‘immutable’ in Rust, that doesn’t mean that -it’s not able to be changed: we are referring to its ‘exterior mutability’ that -in this case is immutable. Consider, for example, [`Arc<T>`][arc]: - -```rust -use std::sync::Arc; - -let x = Arc::new(5); -let y = x.clone(); -``` - -[arc]: ../std/sync/struct.Arc.html - -When we call `clone()`, the `Arc<T>` needs to update the reference count. Yet -we’ve not used any `mut`s here, `x` is an immutable binding, and we didn’t take -`&mut 5` or anything. So what gives? - -To understand this, we have to go back to the core of Rust’s guiding -philosophy, memory safety, and the mechanism by which Rust guarantees it, the -[ownership][ownership] system, and more specifically, [borrowing][borrowing]: - -> You may have one or the other of these two kinds of borrows, but not both at -> the same time: -> -> * one or more references (`&T`) to a resource, -> * exactly one mutable reference (`&mut T`). - -[ownership]: ownership.html -[borrowing]: references-and-borrowing.html#borrowing - -So, that’s the real definition of ‘immutability’: is this safe to have two -pointers to? In `Arc<T>`’s case, yes: the mutation is entirely contained inside -the structure itself. It’s not user facing. For this reason, it hands out `&T` -with `clone()`. If it handed out `&mut T`s, though, that would be a problem. - -Other types, like the ones in the [`std::cell`][stdcell] module, have the -opposite: interior mutability. For example: - -```rust -use std::cell::RefCell; - -let x = RefCell::new(42); - -let y = x.borrow_mut(); -``` - -[stdcell]: ../std/cell/index.html - -RefCell hands out `&mut` references to what’s inside of it with the -`borrow_mut()` method. Isn’t that dangerous? What if we do: - -```rust,ignore -use std::cell::RefCell; - -let x = RefCell::new(42); - -let y = x.borrow_mut(); -let z = x.borrow_mut(); -# (y, z); -``` - -This will in fact panic, at runtime. This is what `RefCell` does: it enforces -Rust’s borrowing rules at runtime, and `panic!`s if they’re violated. This -allows us to get around another aspect of Rust’s mutability rules. Let’s talk -about it first. - -## Field-level mutability - -Mutability is a property of either a borrow (`&mut`) or a binding (`let mut`). -This means that, for example, you cannot have a [`struct`][struct] with -some fields mutable and some immutable: - -```rust,ignore -struct Point { - x: i32, - mut y: i32, // Nope. -} -``` - -The mutability of a struct is in its binding: - -```rust,ignore -struct Point { - x: i32, - y: i32, -} - -let mut a = Point { x: 5, y: 6 }; - -a.x = 10; - -let b = Point { x: 5, y: 6}; - -b.x = 10; // Error: cannot assign to immutable field `b.x`. -``` - -[struct]: structs.html - -However, by using [`Cell<T>`][cell], you can emulate field-level mutability: - -```rust -use std::cell::Cell; - -struct Point { - x: i32, - y: Cell<i32>, -} - -let point = Point { x: 5, y: Cell::new(6) }; - -point.y.set(7); - -println!("y: {:?}", point.y); -``` - -[cell]: ../std/cell/struct.Cell.html - -This will print `y: Cell { value: 7 }`. We’ve successfully updated `y`. diff --git a/src/doc/book/src/operators-and-overloading.md b/src/doc/book/src/operators-and-overloading.md deleted file mode 100644 index a69cd6adb3b1f..0000000000000 --- a/src/doc/book/src/operators-and-overloading.md +++ /dev/null @@ -1,135 +0,0 @@ -# Operators and Overloading - -Rust allows for a limited form of operator overloading. There are certain -operators that are able to be overloaded. To support a particular operator -between types, there’s a specific trait that you can implement, which then -overloads the operator. - -For example, the `+` operator can be overloaded with the `Add` trait: - -```rust -use std::ops::Add; - -#[derive(Debug)] -struct Point { - x: i32, - y: i32, -} - -impl Add for Point { - type Output = Point; - - fn add(self, other: Point) -> Point { - Point { x: self.x + other.x, y: self.y + other.y } - } -} - -fn main() { - let p1 = Point { x: 1, y: 0 }; - let p2 = Point { x: 2, y: 3 }; - - let p3 = p1 + p2; - - println!("{:?}", p3); -} -``` - -In `main`, we can use `+` on our two `Point`s, since we’ve implemented -`Add<Output=Point>` for `Point`. - -There are a number of operators that can be overloaded this way, and all of -their associated traits live in the [`std::ops`][stdops] module. Check out its -documentation for the full list. - -[stdops]: ../std/ops/index.html - -Implementing these traits follows a pattern. Let’s look at [`Add`][add] in more -detail: - -```rust -# mod foo { -pub trait Add<RHS = Self> { - type Output; - - fn add(self, rhs: RHS) -> Self::Output; -} -# } -``` - -[add]: ../std/ops/trait.Add.html - -There’s three types in total involved here: the type you `impl Add` for, `RHS`, -which defaults to `Self`, and `Output`. For an expression `let z = x + y`, `x` -is the `Self` type, `y` is the RHS, and `z` is the `Self::Output` type. - -```rust -# struct Point; -# use std::ops::Add; -impl Add<i32> for Point { - type Output = f64; - - fn add(self, rhs: i32) -> f64 { - // Add an i32 to a Point and get an f64. -# 1.0 - } -} -``` - -will let you do this: - -```rust,ignore -let p: Point = // ... -let x: f64 = p + 2i32; -``` - -# Using operator traits in generic structs - -Now that we know how operator traits are defined, we can define our `HasArea` -trait and `Square` struct from the [traits chapter][traits] more generically: - -[traits]: traits.html - -```rust -use std::ops::Mul; - -trait HasArea<T> { - fn area(&self) -> T; -} - -struct Square<T> { - x: T, - y: T, - side: T, -} - -impl<T> HasArea<T> for Square<T> - where T: Mul<Output=T> + Copy { - fn area(&self) -> T { - self.side * self.side - } -} - -fn main() { - let s = Square { - x: 0.0f64, - y: 0.0f64, - side: 12.0f64, - }; - - println!("Area of s: {}", s.area()); -} -``` - -For `HasArea` and `Square`, we declare a type parameter `T` and replace -`f64` with it. The `impl` needs more involved modifications: - -```rust,ignore -impl<T> HasArea<T> for Square<T> - where T: Mul<Output=T> + Copy { ... } -``` - -The `area` method requires that we can multiply the sides, so we declare that -type `T` must implement `std::ops::Mul`. Like `Add`, mentioned above, `Mul` -itself takes an `Output` parameter: since we know that numbers don't change -type when multiplied, we also set it to `T`. `T` must also support copying, so -Rust doesn't try to move `self.side` into the return value. diff --git a/src/doc/book/src/ownership.md b/src/doc/book/src/ownership.md deleted file mode 100644 index 21ebd6333f710..0000000000000 --- a/src/doc/book/src/ownership.md +++ /dev/null @@ -1,295 +0,0 @@ -# Ownership - -This is the first of three sections presenting Rust’s ownership system. This is one of -Rust’s most distinct and compelling features, with which Rust developers should -become quite acquainted. Ownership is how Rust achieves its largest goal, -memory safety. There are a few distinct concepts, each with its own -chapter: - -* ownership, which you’re reading now -* [borrowing][borrowing], and their associated feature ‘references’ -* [lifetimes][lifetimes], an advanced concept of borrowing - -These three chapters are related, and in order. You’ll need all three to fully -understand the ownership system. - -[borrowing]: references-and-borrowing.html -[lifetimes]: lifetimes.html - -# Meta - -Before we get to the details, two important notes about the ownership system. - -Rust has a focus on safety and speed. It accomplishes these goals through many -‘zero-cost abstractions’, which means that in Rust, abstractions cost as little -as possible in order to make them work. The ownership system is a prime example -of a zero-cost abstraction. All of the analysis we’ll talk about in this guide -is _done at compile time_. You do not pay any run-time cost for any of these -features. - -However, this system does have a certain cost: learning curve. Many new users -to Rust experience something we like to call ‘fighting with the borrow -checker’, where the Rust compiler refuses to compile a program that the author -thinks is valid. This often happens because the programmer’s mental model of -how ownership should work doesn’t match the actual rules that Rust implements. -You probably will experience similar things at first. There is good news, -however: more experienced Rust developers report that once they work with the -rules of the ownership system for a period of time, they fight the borrow -checker less and less. - -With that in mind, let’s learn about ownership. - -# Ownership - -[Variable bindings][bindings] have a property in Rust: they ‘have ownership’ -of what they’re bound to. This means that when a binding goes out of scope, -Rust will free the bound resources. For example: - -```rust -fn foo() { - let v = vec![1, 2, 3]; -} -``` - -When `v` comes into scope, a new [vector][vectors] is created on [the stack][stack], -and it allocates space on [the heap][heap] for its elements. When `v` goes out -of scope at the end of `foo()`, Rust will clean up everything related to the -vector, even the heap-allocated memory. This happens deterministically, at the -end of the scope. - -We covered [vectors] in the previous chapter; we use them -here as an example of a type that allocates space on the heap at runtime. They -behave like [arrays], except their size may change by `push()`ing more -elements onto them. - -Vectors have a [generic type][generics] `Vec<T>`, so in this example `v` will have type -`Vec<i32>`. We'll cover [generics] in detail in a later chapter. - -[arrays]: primitive-types.html#arrays -[vectors]: vectors.html -[heap]: the-stack-and-the-heap.html#the-heap -[stack]: the-stack-and-the-heap.html#the-stack -[bindings]: variable-bindings.html -[generics]: generics.html - -# Move semantics - -There’s some more subtlety here, though: Rust ensures that there is _exactly -one_ binding to any given resource. For example, if we have a vector, we can -assign it to another binding: - -```rust -let v = vec![1, 2, 3]; - -let v2 = v; -``` - -But, if we try to use `v` afterwards, we get an error: - -```rust,ignore -let v = vec![1, 2, 3]; - -let v2 = v; - -println!("v[0] is: {}", v[0]); -``` - -It looks like this: - -```text -error: use of moved value: `v` -println!("v[0] is: {}", v[0]); - ^ -``` - -A similar thing happens if we define a function which takes ownership, and -try to use something after we’ve passed it as an argument: - -```rust,ignore -fn take(v: Vec<i32>) { - // What happens here isn’t important. -} - -let v = vec![1, 2, 3]; - -take(v); - -println!("v[0] is: {}", v[0]); -``` - -Same error: ‘use of moved value’. When we transfer ownership to something else, -we say that we’ve ‘moved’ the thing we refer to. You don’t need some sort of -special annotation here, it’s the default thing that Rust does. - -## The details - -The reason that we cannot use a binding after we’ve moved it is subtle, but -important. - -When we write code like this: - -```rust -let x = 10; -``` - -Rust allocates memory for an integer [i32] on the [stack][sh], copies the bit -pattern representing the value of 10 to the allocated memory and binds the -variable name x to this memory region for future reference. - -[i32]: primitive-types.html#numeric-types - -Now consider the following code fragment: - -```rust -let v = vec![1, 2, 3]; - -let mut v2 = v; -``` - -The first line allocates memory for the vector object `v` on the stack like -it does for `x` above. But in addition to that it also allocates some memory -on the [heap][sh] for the actual data (`[1, 2, 3]`). Rust copies the address -of this heap allocation to an internal pointer, which is part of the vector -object placed on the stack (let's call it the data pointer). - -It is worth pointing out (even at the risk of stating the obvious) that the -vector object and its data live in separate memory regions instead of being a -single contiguous memory allocation (due to reasons we will not go into at -this point of time). These two parts of the vector (the one on the stack and -one on the heap) must agree with each other at all times with regards to -things like the length, capacity, etc. - -When we move `v` to `v2`, Rust actually does a bitwise copy of the vector -object `v` into the stack allocation represented by `v2`. This shallow copy -does not create a copy of the heap allocation containing the actual data. -Which means that there would be two pointers to the contents of the vector -both pointing to the same memory allocation on the heap. It would violate -Rust’s safety guarantees by introducing a data race if one could access both -`v` and `v2` at the same time. - -For example if we truncated the vector to just two elements through `v2`: - -```rust -# let v = vec![1, 2, 3]; -# let mut v2 = v; -v2.truncate(2); -``` - -and `v` were still accessible we'd end up with an invalid vector since `v` -would not know that the heap data has been truncated. Now, the part of the -vector `v` on the stack does not agree with the corresponding part on the -heap. `v` still thinks there are three elements in the vector and will -happily let us access the non existent element `v[2]` but as you might -already know this is a recipe for disaster. Especially because it might lead -to a segmentation fault or worse allow an unauthorized user to read from -memory to which they don't have access. - -This is why Rust forbids using `v` after we’ve done the move. - -[sh]: the-stack-and-the-heap.html - -It’s also important to note that optimizations may remove the actual copy of -the bytes on the stack, depending on circumstances. So it may not be as -inefficient as it initially seems. - -## `Copy` types - -We’ve established that when ownership is transferred to another binding, you -cannot use the original binding. However, there’s a [trait][traits] that changes this -behavior, and it’s called `Copy`. We haven’t discussed traits yet, but for now, -you can think of them as an annotation to a particular type that adds extra -behavior. For example: - -```rust -let v = 1; - -let v2 = v; - -println!("v is: {}", v); -``` - -In this case, `v` is an `i32`, which implements the `Copy` trait. This means -that, just like a move, when we assign `v` to `v2`, a copy of the data is made. -But, unlike a move, we can still use `v` afterward. This is because an `i32` -has no pointers to data somewhere else, copying it is a full copy. - -All primitive types implement the `Copy` trait and their ownership is -therefore not moved like one would assume, following the ‘ownership rules’. -To give an example, the two following snippets of code only compile because the -`i32` and `bool` types implement the `Copy` trait. - -```rust -fn main() { - let a = 5; - - let _y = double(a); - println!("{}", a); -} - -fn double(x: i32) -> i32 { - x * 2 -} -``` - -```rust -fn main() { - let a = true; - - let _y = change_truth(a); - println!("{}", a); -} - -fn change_truth(x: bool) -> bool { - !x -} -``` - -If we had used types that do not implement the `Copy` trait, -we would have gotten a compile error because we tried to use a moved value. - -```text -error: use of moved value: `a` -println!("{}", a); - ^ -``` - -We will discuss how to make your own types `Copy` in the [traits][traits] -section. - -[traits]: traits.html - -# More than ownership - -Of course, if we had to hand ownership back with every function we wrote: - -```rust -fn foo(v: Vec<i32>) -> Vec<i32> { - // Do stuff with `v`. - - // Hand back ownership. - v -} -``` - -This would get very tedious. It gets worse the more things we want to take ownership of: - -```rust -fn foo(v1: Vec<i32>, v2: Vec<i32>) -> (Vec<i32>, Vec<i32>, i32) { - // Do stuff with `v1` and `v2`. - - // Hand back ownership, and the result of our function. - (v1, v2, 42) -} - -let v1 = vec![1, 2, 3]; -let v2 = vec![1, 2, 3]; - -let (v1, v2, answer) = foo(v1, v2); -``` - -Ugh! The return type, return line, and calling the function gets way more -complicated. - -Luckily, Rust offers a feature which helps us solve this problem. -It’s called borrowing and is the topic of the next section! - diff --git a/src/doc/book/src/patterns.md b/src/doc/book/src/patterns.md deleted file mode 100644 index 1983927085c14..0000000000000 --- a/src/doc/book/src/patterns.md +++ /dev/null @@ -1,411 +0,0 @@ -# Patterns - -Patterns are quite common in Rust. We use them in [variable -bindings][bindings], [match expressions][match], and other places, too. Let’s go -on a whirlwind tour of all of the things patterns can do! - -[bindings]: variable-bindings.html -[match]: match.html - -A quick refresher: you can match against literals directly, and `_` acts as an -‘any’ case: - -```rust -let x = 1; - -match x { - 1 => println!("one"), - 2 => println!("two"), - 3 => println!("three"), - _ => println!("anything"), -} -``` - -This prints `one`. - -It's possible to create a binding for the value in the any case: - -```rust -let x = 1; - -match x { - y => println!("x: {} y: {}", x, y), -} -``` - -This prints: - -```text -x: 1 y: 1 -``` - -Note it is an error to have both a catch-all `_` and a catch-all binding in the same match block: - -```rust -let x = 1; - -match x { - y => println!("x: {} y: {}", x, y), - _ => println!("anything"), // this causes an error as it is unreachable -} -``` - -There’s one pitfall with patterns: like anything that introduces a new binding, -they introduce shadowing. For example: - -```rust -let x = 1; -let c = 'c'; - -match c { - x => println!("x: {} c: {}", x, c), -} - -println!("x: {}", x) -``` - -This prints: - -```text -x: c c: c -x: 1 -``` - -In other words, `x =>` matches the pattern and introduces a new binding named -`x`. This new binding is in scope for the match arm and takes on the value of -`c`. Notice that the value of `x` outside the scope of the match has no bearing -on the value of `x` within it. Because we already have a binding named `x`, this -new `x` shadows it. - -# Multiple patterns - -You can match multiple patterns with `|`: - -```rust -let x = 1; - -match x { - 1 | 2 => println!("one or two"), - 3 => println!("three"), - _ => println!("anything"), -} -``` - -This prints `one or two`. - -# Destructuring - -If you have a compound data type, like a [`struct`][struct], you can destructure it -inside of a pattern: - -```rust -struct Point { - x: i32, - y: i32, -} - -let origin = Point { x: 0, y: 0 }; - -match origin { - Point { x, y } => println!("({},{})", x, y), -} -``` - -[struct]: structs.html - -We can use `:` to give a value a different name. - -```rust -struct Point { - x: i32, - y: i32, -} - -let origin = Point { x: 0, y: 0 }; - -match origin { - Point { x: x1, y: y1 } => println!("({},{})", x1, y1), -} -``` - -If we only care about some of the values, we don’t have to give them all names: - -```rust -struct Point { - x: i32, - y: i32, -} - -let point = Point { x: 2, y: 3 }; - -match point { - Point { x, .. } => println!("x is {}", x), -} -``` - -This prints `x is 2`. - -You can do this kind of match on any member, not only the first: - -```rust -struct Point { - x: i32, - y: i32, -} - -let point = Point { x: 2, y: 3 }; - -match point { - Point { y, .. } => println!("y is {}", y), -} -``` - -This prints `y is 3`. - -This ‘destructuring’ behavior works on any compound data type, like -[tuples][tuples] or [enums][enums]. - -[tuples]: primitive-types.html#tuples -[enums]: enums.html - -# Ignoring bindings - -You can use `_` in a pattern to disregard the type and value. -For example, here’s a `match` against a `Result<T, E>`: - -```rust -# let some_value: Result<i32, &'static str> = Err("There was an error"); -match some_value { - Ok(value) => println!("got a value: {}", value), - Err(_) => println!("an error occurred"), -} -``` - -In the first arm, we bind the value inside the `Ok` variant to `value`. But -in the `Err` arm, we use `_` to disregard the specific error, and print -a general error message. - -`_` is valid in any pattern that creates a binding. This can be useful to -ignore parts of a larger structure: - -```rust -fn coordinate() -> (i32, i32, i32) { - // Generate and return some sort of triple tuple. -# (1, 2, 3) -} - -let (x, _, z) = coordinate(); -``` - -Here, we bind the first and last element of the tuple to `x` and `z`, but -ignore the middle element. - -It’s worth noting that using `_` never binds the value in the first place, -which means that the value does not move: - -```rust -let tuple: (u32, String) = (5, String::from("five")); - -// Here, tuple is moved, because the String moved: -let (x, _s) = tuple; - -// The next line would give "error: use of partially moved value: `tuple`". -// println!("Tuple is: {:?}", tuple); - -// However, - -let tuple = (5, String::from("five")); - -// Here, tuple is _not_ moved, as the String was never moved, and u32 is Copy: -let (x, _) = tuple; - -// That means this works: -println!("Tuple is: {:?}", tuple); -``` - -This also means that any temporary variables will be dropped at the end of the -statement: - -```rust -// Here, the String created will be dropped immediately, as it’s not bound: - -let _ = String::from(" hello ").trim(); -``` - -You can also use `..` in a pattern to disregard multiple values: - -```rust -enum OptionalTuple { - Value(i32, i32, i32), - Missing, -} - -let x = OptionalTuple::Value(5, -2, 3); - -match x { - OptionalTuple::Value(..) => println!("Got a tuple!"), - OptionalTuple::Missing => println!("No such luck."), -} -``` - -This prints `Got a tuple!`. - -# ref and ref mut - -If you want to get a [reference][ref], use the `ref` keyword: - -```rust -let x = 5; - -match x { - ref r => println!("Got a reference to {}", r), -} -``` - -This prints `Got a reference to 5`. - -[ref]: references-and-borrowing.html - -Here, the `r` inside the `match` has the type `&i32`. In other words, the `ref` -keyword _creates_ a reference, for use in the pattern. If you need a mutable -reference, `ref mut` will work in the same way: - -```rust -let mut x = 5; - -match x { - ref mut mr => println!("Got a mutable reference to {}", mr), -} -``` - -# Ranges - -You can match a range of values with `...`: - -```rust -let x = 1; - -match x { - 1 ... 5 => println!("one through five"), - _ => println!("anything"), -} -``` - -This prints `one through five`. - -Ranges are mostly used with integers and `char`s: - -```rust -let x = '💅'; - -match x { - 'a' ... 'j' => println!("early letter"), - 'k' ... 'z' => println!("late letter"), - _ => println!("something else"), -} -``` - -This prints `something else`. - -# Bindings - -You can bind values to names with `@`: - -```rust -let x = 1; - -match x { - e @ 1 ... 5 => println!("got a range element {}", e), - _ => println!("anything"), -} -``` - -This prints `got a range element 1`. This is useful when you want to -do a complicated match of part of a data structure: - -```rust -#[derive(Debug)] -struct Person { - name: Option<String>, -} - -let name = "Steve".to_string(); -let x: Option<Person> = Some(Person { name: Some(name) }); -match x { - Some(Person { name: ref a @ Some(_), .. }) => println!("{:?}", a), - _ => {} -} -``` - -This prints `Some("Steve")`: we’ve bound the inner `name` to `a`. - -If you use `@` with `|`, you need to make sure the name is bound in each part -of the pattern: - -```rust -let x = 5; - -match x { - e @ 1 ... 5 | e @ 8 ... 10 => println!("got a range element {}", e), - _ => println!("anything"), -} -``` - -# Guards - -You can introduce ‘match guards’ with `if`: - -```rust -enum OptionalInt { - Value(i32), - Missing, -} - -let x = OptionalInt::Value(5); - -match x { - OptionalInt::Value(i) if i > 5 => println!("Got an int bigger than five!"), - OptionalInt::Value(..) => println!("Got an int!"), - OptionalInt::Missing => println!("No such luck."), -} -``` - -This prints `Got an int!`. - -If you’re using `if` with multiple patterns, the `if` applies to both sides: - -```rust -let x = 4; -let y = false; - -match x { - 4 | 5 if y => println!("yes"), - _ => println!("no"), -} -``` - -This prints `no`, because the `if` applies to the whole of `4 | 5`, and not to -only the `5`. In other words, the precedence of `if` behaves like this: - -```text -(4 | 5) if y => ... -``` - -not this: - -```text -4 | (5 if y) => ... -``` - -# Mix and Match - -Whew! That’s a lot of different ways to match things, and they can all be -mixed and matched, depending on what you’re doing: - -```rust,ignore -match x { - Foo { x: Some(ref name), y: None } => ... -} -``` - -Patterns are very powerful. Make good use of them. diff --git a/src/doc/book/src/primitive-types.md b/src/doc/book/src/primitive-types.md deleted file mode 100644 index 8fd3d17c15e57..0000000000000 --- a/src/doc/book/src/primitive-types.md +++ /dev/null @@ -1,305 +0,0 @@ -# Primitive Types - -The Rust language has a number of types that are considered ‘primitive’. This -means that they’re built-in to the language. Rust is structured in such a way -that the standard library also provides a number of useful types built on top -of these ones, as well, but these are the most primitive. - -# Booleans - -Rust has a built-in boolean type, named `bool`. It has two values, `true` and `false`: - -```rust -let x = true; - -let y: bool = false; -``` - -A common use of booleans is in [`if` conditionals][if]. - -[if]: if.html - -You can find more documentation for `bool`s [in the standard library -documentation][bool]. - -[bool]: ../std/primitive.bool.html - -# `char` - -The `char` type represents a single Unicode scalar value. You can create `char`s -with a single tick: (`'`) - -```rust -let x = 'x'; -let two_hearts = '💕'; -``` - -Unlike some other languages, this means that Rust’s `char` is not a single byte, -but four. - -You can find more documentation for `char`s [in the standard library -documentation][char]. - -[char]: ../std/primitive.char.html - -# Numeric types - -Rust has a variety of numeric types in a few categories: signed and unsigned, -fixed and variable, floating-point and integer. - -These types consist of two parts: the category, and the size. For example, -`u16` is an unsigned type with sixteen bits of size. More bits lets you have -bigger numbers. - -If a number literal has nothing to cause its type to be inferred, it defaults: - -```rust -let x = 42; // `x` has type `i32`. - -let y = 1.0; // `y` has type `f64`. -``` - -Here’s a list of the different numeric types, with links to their documentation -in the standard library: - -* [i8](../std/primitive.i8.html) -* [i16](../std/primitive.i16.html) -* [i32](../std/primitive.i32.html) -* [i64](../std/primitive.i64.html) -* [u8](../std/primitive.u8.html) -* [u16](../std/primitive.u16.html) -* [u32](../std/primitive.u32.html) -* [u64](../std/primitive.u64.html) -* [isize](../std/primitive.isize.html) -* [usize](../std/primitive.usize.html) -* [f32](../std/primitive.f32.html) -* [f64](../std/primitive.f64.html) - -Let’s go over them by category: - -## Signed and Unsigned - -Integer types come in two varieties: signed and unsigned. To understand the -difference, let’s consider a number with four bits of size. A signed, four-bit -number would let you store numbers from `-8` to `+7`. Signed numbers use -“two’s complement representation”. An unsigned four bit number, since it does -not need to store negatives, can store values from `0` to `+15`. - -Unsigned types use a `u` for their category, and signed types use `i`. The `i` -is for ‘integer’. So `u8` is an eight-bit unsigned number, and `i8` is an -eight-bit signed number. - -## Fixed-size types - -Fixed-size types have a specific number of bits in their representation. Valid -bit sizes are `8`, `16`, `32`, and `64`. So, `u32` is an unsigned, 32-bit integer, -and `i64` is a signed, 64-bit integer. - -## Variable-size types - -Rust also provides types whose particular size depends on the underlying machine -architecture. Their range is sufficient to express the size of any collection, so -these types have ‘size’ as the category. They come in signed and unsigned varieties -which account for two types: `isize` and `usize`. - -## Floating-point types - -Rust also has two floating point types: `f32` and `f64`. These correspond to -IEEE-754 single and double precision numbers. - -# Arrays - -Like many programming languages, Rust has list types to represent a sequence of -things. The most basic is the *array*, a fixed-size list of elements of the -same type. By default, arrays are immutable. - -```rust -let a = [1, 2, 3]; // a: [i32; 3] -let mut m = [1, 2, 3]; // m: [i32; 3] -``` - -Arrays have type `[T; N]`. We’ll talk about this `T` notation [in the generics -section][generics]. The `N` is a compile-time constant, for the length of the -array. - -There’s a shorthand for initializing each element of an array to the same -value. In this example, each element of `a` will be initialized to `0`: - -```rust -let a = [0; 20]; // a: [i32; 20] -``` - -You can get the number of elements in an array `a` with `a.len()`: - -```rust -let a = [1, 2, 3]; - -println!("a has {} elements", a.len()); -``` - -You can access a particular element of an array with *subscript notation*: - -```rust -let names = ["Graydon", "Brian", "Niko"]; // names: [&str; 3] - -println!("The second name is: {}", names[1]); -``` - -Subscripts start at zero, like in most programming languages, so the first name -is `names[0]` and the second name is `names[1]`. The above example prints -`The second name is: Brian`. If you try to use a subscript that is not in the -array, you will get an error: array access is bounds-checked at run-time. Such -errant access is the source of many bugs in other systems programming -languages. - -You can find more documentation for `array`s [in the standard library -documentation][array]. - -[array]: ../std/primitive.array.html - -# Slices - -A ‘slice’ is a reference to (or “view” into) another data structure. They are -useful for allowing safe, efficient access to a portion of an array without -copying. For example, you might want to reference only one line of a file read -into memory. By nature, a slice is not created directly, but from an existing -variable binding. Slices have a defined length, and can be mutable or immutable. - -Internally, slices are represented as a pointer to the beginning of the data -and a length. - -## Slicing syntax - -You can use a combo of `&` and `[]` to create a slice from various things. The -`&` indicates that slices are similar to [references], which we will cover in -detail later in this section. The `[]`s, with a range, let you define the -length of the slice: - -```rust -let a = [0, 1, 2, 3, 4]; -let complete = &a[..]; // A slice containing all of the elements in `a`. -let middle = &a[1..4]; // A slice of `a`: only the elements `1`, `2`, and `3`. -``` - -Slices have type `&[T]`. We’ll talk about that `T` when we cover -[generics][generics]. - -[generics]: generics.html - -You can find more documentation for slices [in the standard library -documentation][slice]. - -[slice]: ../std/primitive.slice.html - -# `str` - -Rust’s `str` type is the most primitive string type. As an [unsized type][dst], -it’s not very useful by itself, but becomes useful when placed behind a -reference, like `&str`. We'll elaborate further when we cover -[Strings][strings] and [references]. - -[dst]: unsized-types.html -[strings]: strings.html -[references]: references-and-borrowing.html - -You can find more documentation for `str` [in the standard library -documentation][str]. - -[str]: ../std/primitive.str.html - -# Tuples - -A tuple is an ordered list of fixed size. Like this: - -```rust -let x = (1, "hello"); -``` - -The parentheses and commas form this two-length tuple. Here’s the same code, but -with the type annotated: - -```rust -let x: (i32, &str) = (1, "hello"); -``` - -As you can see, the type of a tuple looks like the tuple, but with each -position having a type name rather than the value. Careful readers will also -note that tuples are heterogeneous: we have an `i32` and a `&str` in this tuple. -In systems programming languages, strings are a bit more complex than in other -languages. For now, read `&str` as a *string slice*, and we’ll learn more -soon. - -You can assign one tuple into another, if they have the same contained types -and [arity]. Tuples have the same arity when they have the same length. - -[arity]: glossary.html#arity - -```rust -let mut x = (1, 2); // x: (i32, i32) -let y = (2, 3); // y: (i32, i32) - -x = y; -``` - -You can access the fields in a tuple through a *destructuring let*. Here’s -an example: - -```rust -let (x, y, z) = (1, 2, 3); - -println!("x is {}", x); -``` - -Remember [before][let] when I said the left-hand side of a `let` statement was more -powerful than assigning a binding? Here we are. We can put a pattern on -the left-hand side of the `let`, and if it matches up to the right-hand side, -we can assign multiple bindings at once. In this case, `let` “destructures” -or “breaks up” the tuple, and assigns the bits to three bindings. - -[let]: variable-bindings.html - -This pattern is very powerful, and we’ll see it repeated more later. - -You can disambiguate a single-element tuple from a value in parentheses with a -comma: - -```rust -(0,); // A single-element tuple. -(0); // A zero in parentheses. -``` - -## Tuple Indexing - -You can also access fields of a tuple with indexing syntax: - - -```rust -let tuple = (1, 2, 3); - -let x = tuple.0; -let y = tuple.1; -let z = tuple.2; - -println!("x is {}", x); -``` - -Like array indexing, it starts at zero, but unlike array indexing, it uses a -`.`, rather than `[]`s. - -You can find more documentation for tuples [in the standard library -documentation][tuple]. - -[tuple]: ../std/primitive.tuple.html - -# Functions - -Functions also have a type! They look like this: - -```rust -fn foo(x: i32) -> i32 { x } - -let x: fn(i32) -> i32 = foo; -``` - -In this case, `x` is a ‘function pointer’ to a function that takes an `i32` and -returns an `i32`. diff --git a/src/doc/book/src/procedural-macros.md b/src/doc/book/src/procedural-macros.md deleted file mode 100644 index e02b5a6cdd79b..0000000000000 --- a/src/doc/book/src/procedural-macros.md +++ /dev/null @@ -1,286 +0,0 @@ -# Procedural Macros (and custom Derive) - -As you've seen throughout the rest of the book, Rust provides a mechanism -called "derive" that lets you implement traits easily. For example, - -```rust -#[derive(Debug)] -struct Point { - x: i32, - y: i32, -} -``` - -is a lot simpler than - -```rust -struct Point { - x: i32, - y: i32, -} - -use std::fmt; - -impl fmt::Debug for Point { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Point {{ x: {}, y: {} }}", self.x, self.y) - } -} -``` - -Rust includes several traits that you can derive, but it also lets you define -your own. We can accomplish this task through a feature of Rust called -"procedural macros." Eventually, procedural macros will allow for all sorts of -advanced metaprogramming in Rust, but today, they're only for custom derive. - -Let's build a very simple trait, and derive it with custom derive. - -## Hello World - -So the first thing we need to do is start a new crate for our project. - -```bash -$ cargo new --bin hello-world -``` - -All we want is to be able to call `hello_world()` on a derived type. Something -like this: - -```rust,ignore -#[derive(HelloWorld)] -struct Pancakes; - -fn main() { - Pancakes::hello_world(); -} -``` - -With some kind of nice output, like `Hello, World! My name is Pancakes.`. - -Let's go ahead and write up what we think our macro will look like from a user -perspective. In `src/main.rs` we write: - -```rust,ignore -#[macro_use] -extern crate hello_world_derive; - -trait HelloWorld { - fn hello_world(); -} - -#[derive(HelloWorld)] -struct FrenchToast; - -#[derive(HelloWorld)] -struct Waffles; - -fn main() { - FrenchToast::hello_world(); - Waffles::hello_world(); -} -``` - -Great. So now we just need to actually write the procedural macro. At the -moment, procedural macros need to be in their own crate. Eventually, this -restriction may be lifted, but for now, it's required. As such, there's a -convention; for a crate named `foo`, a custom derive procedural macro is called -`foo-derive`. Let's start a new crate called `hello-world-derive` inside our -`hello-world` project. - -```bash -$ cargo new hello-world-derive -``` - -To make sure that our `hello-world` crate is able to find this new crate we've -created, we'll add it to our toml: - -```toml -[dependencies] -hello-world-derive = { path = "hello-world-derive" } -``` - -As for the source of our `hello-world-derive` crate, here's an example: - -```rust,ignore -extern crate proc_macro; -extern crate syn; -#[macro_use] -extern crate quote; - -use proc_macro::TokenStream; - -#[proc_macro_derive(HelloWorld)] -pub fn hello_world(input: TokenStream) -> TokenStream { - // Construct a string representation of the type definition - let s = input.to_string(); - - // Parse the string representation - let ast = syn::parse_macro_input(&s).unwrap(); - - // Build the impl - let gen = impl_hello_world(&ast); - - // Return the generated impl - gen.parse().unwrap() -} -``` - -So there is a lot going on here. We have introduced two new crates: [`syn`] and -[`quote`]. As you may have noticed, `input: TokenSteam` is immediately converted -to a `String`. This `String` is a string representation of the Rust code for which -we are deriving `HelloWorld`. At the moment, the only thing you can do with a -`TokenStream` is convert it to a string. A richer API will exist in the future. - -So what we really need is to be able to _parse_ Rust code into something -usable. This is where `syn` comes to play. `syn` is a crate for parsing Rust -code. The other crate we've introduced is `quote`. It's essentially the dual of -`syn` as it will make generating Rust code really easy. We could write this -stuff on our own, but it's much simpler to use these libraries. Writing a full -parser for Rust code is no simple task. - -[`syn`]: https://crates.io/crates/syn -[`quote`]: https://crates.io/crates/quote - -The comments seem to give us a pretty good idea of our overall strategy. We -are going to take a `String` of the Rust code for the type we are deriving, parse -it using `syn`, construct the implementation of `hello_world` (using `quote`), -then pass it back to Rust compiler. - -One last note: you'll see some `unwrap()`s there. If you want to provide an -error for a procedural macro, then you should `panic!` with the error message. -In this case, we're keeping it as simple as possible. - -Great, so let's write `impl_hello_world(&ast)`. - -```rust,ignore -fn impl_hello_world(ast: &syn::MacroInput) -> quote::Tokens { - let name = &ast.ident; - quote! { - impl HelloWorld for #name { - fn hello_world() { - println!("Hello, World! My name is {}", stringify!(#name)); - } - } - } -} -``` - -So this is where quotes comes in. The `ast` argument is a struct that gives us -a representation of our type (which can be either a `struct` or an `enum`). -Check out the [docs](https://docs.rs/syn/0.10.5/syn/struct.MacroInput.html), -there is some useful information there. We are able to get the name of the -type using `ast.ident`. The `quote!` macro lets us write up the Rust code -that we wish to return and convert it into `Tokens`. `quote!` lets us use some -really cool templating mechanics; we simply write `#name` and `quote!` will -replace it with the variable named `name`. You can even do some repetition -similar to regular macros work. You should check out the -[docs](https://docs.rs/quote) for a good introduction. - -So I think that's it. Oh, well, we do need to add dependencies for `syn` and -`quote` in the `cargo.toml` for `hello-world-derive`. - -```toml -[dependencies] -syn = "0.10.5" -quote = "0.3.10" -``` - -That should be it. Let's try to compile `hello-world`. - -```bash -error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type - --> hello-world-derive/src/lib.rs:8:3 - | -8 | #[proc_macro_derive(HelloWorld)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -``` - -Oh, so it appears that we need to declare that our `hello-world-derive` crate is -a `proc-macro` crate type. How do we do this? Like this: - -```toml -[lib] -proc-macro = true -``` - -Ok so now, let's compile `hello-world`. Executing `cargo run` now yields: - -```bash -Hello, World! My name is FrenchToast -Hello, World! My name is Waffles -``` - -We've done it! - -## Custom Attributes - -In some cases it might make sense to allow users some kind of configuration. -For example, the user might want to overwrite the name that is printed in the `hello_world()` method. - -This can be achieved with custom attributes: - -```rust,ignore -#[derive(HelloWorld)] -#[HelloWorldName = "the best Pancakes"] -struct Pancakes; - -fn main() { - Pancakes::hello_world(); -} -``` - -If we try to compile this though, the compiler will respond with an error: - -```bash -error: The attribute `HelloWorldName` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) -``` - -The compiler needs to know that we're handling this attribute and to not respond with an error. -This is done in the `hello-world-derive` crate by adding `attributes` to the `proc_macro_derive` attribute: - -```rust,ignore -#[proc_macro_derive(HelloWorld, attributes(HelloWorldName))] -pub fn hello_world(input: TokenStream) -> TokenStream -``` - -Multiple attributes can be specified that way. - -## Raising Errors - -Let's assume that we do not want to accept enums as input to our custom derive method. - -This condition can be easily checked with the help of `syn`. -But how do we tell the user, that we do not accept enums? -The idiomatic way to report errors in procedural macros is to panic: - -```rust,ignore -fn impl_hello_world(ast: &syn::MacroInput) -> quote::Tokens { - let name = &ast.ident; - // Check if derive(HelloWorld) was specified for a struct - if let syn::Body::Struct(_) = ast.body { - // Yes, this is a struct - quote! { - impl HelloWorld for #name { - fn hello_world() { - println!("Hello, World! My name is {}", stringify!(#name)); - } - } - } - } else { - //Nope. This is an Enum. We cannot handle these! - panic!("#[derive(HelloWorld)] is only defined for structs, not for enums!"); - } -} -``` - -If a user now tries to derive `HelloWorld` from an enum they will be greeted with following, hopefully helpful, error: - -```bash -error: custom derive attribute panicked - --> src/main.rs - | - | #[derive(HelloWorld)] - | ^^^^^^^^^^ - | - = help: message: #[derive(HelloWorld)] is only defined for structs, not for enums! -``` diff --git a/src/doc/book/src/raw-pointers.md b/src/doc/book/src/raw-pointers.md deleted file mode 100644 index 1f75665f4b8c3..0000000000000 --- a/src/doc/book/src/raw-pointers.md +++ /dev/null @@ -1,121 +0,0 @@ -# Raw Pointers - -Rust has a number of different smart pointer types in its standard library, but -there are two types that are extra-special. Much of Rust’s safety comes from -compile-time checks, but raw pointers don’t have such guarantees, and are -[unsafe][unsafe] to use. - -`*const T` and `*mut T` are called ‘raw pointers’ in Rust. Sometimes, when -writing certain kinds of libraries, you’ll need to get around Rust’s safety -guarantees for some reason. In this case, you can use raw pointers to implement -your library, while exposing a safe interface for your users. For example, `*` -pointers are allowed to alias, allowing them to be used to write -shared-ownership types, and even thread-safe shared memory types (the `Rc<T>` -and `Arc<T>` types are both implemented entirely in Rust). - -Here are some things to remember about raw pointers that are different than -other pointer types. They: - -- are not guaranteed to point to valid memory and are not even - guaranteed to be non-NULL (unlike both `Box` and `&`); -- do not have any automatic clean-up, unlike `Box`, and so require - manual resource management; -- are plain-old-data, that is, they don't move ownership, again unlike - `Box`, hence the Rust compiler cannot protect against bugs like - use-after-free; -- lack any form of lifetimes, unlike `&`, and so the compiler cannot - reason about dangling pointers; and -- have no guarantees about aliasing or mutability other than mutation - not being allowed directly through a `*const T`. - -# Basics - -Creating a raw pointer is perfectly safe: - -```rust -let x = 5; -let raw = &x as *const i32; - -let mut y = 10; -let raw_mut = &mut y as *mut i32; -``` - -However, dereferencing one is not. This won’t work: - -```rust,ignore -let x = 5; -let raw = &x as *const i32; - -println!("raw points at {}", *raw); -``` - -It gives this error: - -```text -error: dereference of raw pointer requires unsafe function or block [E0133] - println!("raw points at {}", *raw); - ^~~~ -``` - -When you dereference a raw pointer, you’re taking responsibility that it’s not -pointing somewhere that would be incorrect. As such, you need `unsafe`: - -```rust -let x = 5; -let raw = &x as *const i32; - -let points_at = unsafe { *raw }; - -println!("raw points at {}", points_at); -``` - -For more operations on raw pointers, see [their API documentation][rawapi]. - -[unsafe]: unsafe.html -[rawapi]: ../std/primitive.pointer.html - -# FFI - -Raw pointers are useful for FFI: Rust’s `*const T` and `*mut T` are similar to -C’s `const T*` and `T*`, respectively. For more about this use, consult the -[FFI chapter][ffi]. - -[ffi]: ffi.html - -# References and raw pointers - -At runtime, a raw pointer `*` and a reference pointing to the same piece of -data have an identical representation. In fact, an `&T` reference will -implicitly coerce to an `*const T` raw pointer in safe code and similarly for -the `mut` variants (both coercions can be performed explicitly with, -respectively, `value as *const T` and `value as *mut T`). - -Going the opposite direction, from `*const` to a reference `&`, is not safe. A -`&T` is always valid, and so, at a minimum, the raw pointer `*const T` has to -point to a valid instance of type `T`. Furthermore, the resulting pointer must -satisfy the aliasing and mutability laws of references. The compiler assumes -these properties are true for any references, no matter how they are created, -and so any conversion from raw pointers is asserting that they hold. The -programmer *must* guarantee this. - -The recommended method for the conversion is: - -```rust -// Explicit cast: -let i: u32 = 1; -let p_imm: *const u32 = &i as *const u32; - -// Implicit coercion: -let mut m: u32 = 2; -let p_mut: *mut u32 = &mut m; - -unsafe { - let ref_imm: &u32 = &*p_imm; - let ref_mut: &mut u32 = &mut *p_mut; -} -``` - -The `&*x` dereferencing style is preferred to using a `transmute`. The latter -is far more powerful than necessary, and the more restricted operation is -harder to use incorrectly; for example, it requires that `x` is a pointer -(unlike `transmute`). diff --git a/src/doc/book/src/references-and-borrowing.md b/src/doc/book/src/references-and-borrowing.md deleted file mode 100644 index f01aa45385acf..0000000000000 --- a/src/doc/book/src/references-and-borrowing.md +++ /dev/null @@ -1,411 +0,0 @@ -# References and Borrowing - -This is the second of three sections presenting Rust’s ownership system. This is one of -Rust’s most distinct and compelling features, with which Rust developers should -become quite acquainted. Ownership is how Rust achieves its largest goal, -memory safety. There are a few distinct concepts, each with its own -chapter: - -* [ownership][ownership], the key concept -* borrowing, which you’re reading now -* [lifetimes][lifetimes], an advanced concept of borrowing - -These three chapters are related, and in order. You’ll need all three to fully -understand the ownership system. - -[ownership]: ownership.html -[lifetimes]: lifetimes.html - -# Meta - -Before we get to the details, two important notes about the ownership system. - -Rust has a focus on safety and speed. It accomplishes these goals through many -‘zero-cost abstractions’, which means that in Rust, abstractions cost as little -as possible in order to make them work. The ownership system is a prime example -of a zero-cost abstraction. All of the analysis we’ll talk about in this guide -is _done at compile time_. You do not pay any run-time cost for any of these -features. - -However, this system does have a certain cost: learning curve. Many new users -to Rust experience something we like to call ‘fighting with the borrow -checker’, where the Rust compiler refuses to compile a program that the author -thinks is valid. This often happens because the programmer’s mental model of -how ownership should work doesn’t match the actual rules that Rust implements. -You probably will experience similar things at first. There is good news, -however: more experienced Rust developers report that once they work with the -rules of the ownership system for a period of time, they fight the borrow -checker less and less. - -With that in mind, let’s learn about borrowing. - -# Borrowing - -At the end of the [ownership][ownership] section, we had a nasty function that looked -like this: - -```rust -fn foo(v1: Vec<i32>, v2: Vec<i32>) -> (Vec<i32>, Vec<i32>, i32) { - // Do stuff with `v1` and `v2`. - - // Hand back ownership, and the result of our function. - (v1, v2, 42) -} - -let v1 = vec![1, 2, 3]; -let v2 = vec![1, 2, 3]; - -let (v1, v2, answer) = foo(v1, v2); -``` - -This is not idiomatic Rust, however, as it doesn’t take advantage of borrowing. Here’s -the first step: - -```rust -fn foo(v1: &Vec<i32>, v2: &Vec<i32>) -> i32 { - // Do stuff with `v1` and `v2`. - - // Return the answer. - 42 -} - -let v1 = vec![1, 2, 3]; -let v2 = vec![1, 2, 3]; - -let answer = foo(&v1, &v2); - -// We can use `v1` and `v2` here! -``` - -A more concrete example: - -```rust -fn main() { - // Don't worry if you don't understand how `fold` works, the point here is that an immutable reference is borrowed. - fn sum_vec(v: &Vec<i32>) -> i32 { - return v.iter().fold(0, |a, &b| a + b); - } - // Borrow two vectors and sum them. - // This kind of borrowing does not allow mutation through the borrowed reference. - fn foo(v1: &Vec<i32>, v2: &Vec<i32>) -> i32 { - // Do stuff with `v1` and `v2`. - let s1 = sum_vec(v1); - let s2 = sum_vec(v2); - // Return the answer. - s1 + s2 - } - - let v1 = vec![1, 2, 3]; - let v2 = vec![4, 5, 6]; - - let answer = foo(&v1, &v2); - println!("{}", answer); -} -``` - -Instead of taking `Vec<i32>`s as our arguments, we take a reference: -`&Vec<i32>`. And instead of passing `v1` and `v2` directly, we pass `&v1` and -`&v2`. We call the `&T` type a ‘reference’, and rather than owning the resource, -it borrows ownership. A binding that borrows something does not deallocate the -resource when it goes out of scope. This means that after the call to `foo()`, -we can use our original bindings again. - -References are immutable, like bindings. This means that inside of `foo()`, -the vectors can’t be changed at all: - -```rust,ignore -fn foo(v: &Vec<i32>) { - v.push(5); -} - -let v = vec![]; - -foo(&v); -``` - -will give us this error: - -```text -error: cannot borrow immutable borrowed content `*v` as mutable -v.push(5); -^ -``` - -Pushing a value mutates the vector, and so we aren’t allowed to do it. - -# &mut references - -There’s a second kind of reference: `&mut T`. A ‘mutable reference’ allows you -to mutate the resource you’re borrowing. For example: - -```rust -let mut x = 5; -{ - let y = &mut x; - *y += 1; -} -println!("{}", x); -``` - -This will print `6`. We make `y` a mutable reference to `x`, then add one to -the thing `y` points at. You’ll notice that `x` had to be marked `mut` as well. -If it wasn’t, we couldn’t take a mutable borrow to an immutable value. - -You'll also notice we added an asterisk (`*`) in front of `y`, making it `*y`, -this is because `y` is a `&mut` reference. You'll need to use asterisks to -access the contents of a reference as well. - -Otherwise, `&mut` references are like references. There _is_ a large -difference between the two, and how they interact, though. You can tell -something is fishy in the above example, because we need that extra scope, with -the `{` and `}`. If we remove them, we get an error: - -```text -error: cannot borrow `x` as immutable because it is also borrowed as mutable - println!("{}", x); - ^ -note: previous borrow of `x` occurs here; the mutable borrow prevents -subsequent moves, borrows, or modification of `x` until the borrow ends - let y = &mut x; - ^ -note: previous borrow ends here -fn main() { - -} -^ -``` - -As it turns out, there are rules. - -# The Rules - -Here are the rules for borrowing in Rust: - -First, any borrow must last for a scope no greater than that of the owner. -Second, you may have one or the other of these two kinds of borrows, but not -both at the same time: - -* one or more references (`&T`) to a resource, -* exactly one mutable reference (`&mut T`). - - -You may notice that this is very similar to, though not exactly the same as, -the definition of a data race: - -> There is a ‘data race’ when two or more pointers access the same memory -> location at the same time, where at least one of them is writing, and the -> operations are not synchronized. - -With references, you may have as many as you’d like, since none of them are -writing. However, as we can only have one `&mut` at a time, it is impossible to -have a data race. This is how Rust prevents data races at compile time: we’ll -get errors if we break the rules. - -With this in mind, let’s consider our example again. - -## Thinking in scopes - -Here’s the code: - -```rust,ignore -fn main() { - let mut x = 5; - let y = &mut x; - - *y += 1; - - println!("{}", x); -} -``` - -This code gives us this error: - -```text -error: cannot borrow `x` as immutable because it is also borrowed as mutable - println!("{}", x); - ^ -``` - -This is because we’ve violated the rules: we have a `&mut T` pointing to `x`, -and so we aren’t allowed to create any `&T`s. It's one or the other. The note -hints at how to think about this problem: - -```text -note: previous borrow ends here -fn main() { - -} -^ -``` - -In other words, the mutable borrow is held through the rest of our example. What -we want is for the mutable borrow by `y` to end so that the resource can be -returned to the owner, `x`. `x` can then provide an immutable borrow to `println!`. -In Rust, borrowing is tied to the scope that the borrow is valid for. And our -scopes look like this: - -```rust,ignore -fn main() { - let mut x = 5; - - let y = &mut x; // -+ &mut borrow of `x` starts here. - // | - *y += 1; // | - // | - println!("{}", x); // -+ - Try to borrow `x` here. -} // -+ &mut borrow of `x` ends here. - -``` - -The scopes conflict: we can’t make an `&x` while `y` is in scope. - -So when we add the curly braces: - -```rust -let mut x = 5; - -{ - let y = &mut x; // -+ &mut borrow starts here. - *y += 1; // | -} // -+ ... and ends here. - -println!("{}", x); // <- Try to borrow `x` here. -``` - -There’s no problem. Our mutable borrow goes out of scope before we create an -immutable one. So scope is the key to seeing how long a borrow lasts for. - -## Issues borrowing prevents - -Why have these restrictive rules? Well, as we noted, these rules prevent data -races. What kinds of issues do data races cause? Here are a few. - -### Iterator invalidation - -One example is ‘iterator invalidation’, which happens when you try to mutate a -collection that you’re iterating over. Rust’s borrow checker prevents this from -happening: - -```rust -let mut v = vec![1, 2, 3]; - -for i in &v { - println!("{}", i); -} -``` - -This prints out one through three. As we iterate through the vector, we’re -only given references to the elements. And `v` is itself borrowed as immutable, -which means we can’t change it while we’re iterating: - -```rust,ignore -let mut v = vec![1, 2, 3]; - -for i in &v { - println!("{}", i); - v.push(34); -} -``` - -Here’s the error: - -```text -error: cannot borrow `v` as mutable because it is also borrowed as immutable - v.push(34); - ^ -note: previous borrow of `v` occurs here; the immutable borrow prevents -subsequent moves or mutable borrows of `v` until the borrow ends -for i in &v { - ^ -note: previous borrow ends here -for i in &v { - println!(“{}”, i); - v.push(34); -} -^ -``` - -We can’t modify `v` because it’s borrowed by the loop. - -### Use after free - -References must not live longer than the resource they refer to. Rust will -check the scopes of your references to ensure that this is true. - -If Rust didn’t check this property, we could accidentally use a reference -which was invalid. For example: - -```rust,ignore -let y: &i32; -{ - let x = 5; - y = &x; -} - -println!("{}", y); -``` - -We get this error: - -```text -error: `x` does not live long enough - y = &x; - ^ -note: reference must be valid for the block suffix following statement 0 at -2:16... -let y: &i32; -{ - let x = 5; - y = &x; -} - -note: ...but borrowed value is only valid for the block suffix following -statement 0 at 4:18 - let x = 5; - y = &x; -} -``` - -In other words, `y` is only valid for the scope where `x` exists. As soon as -`x` goes away, it becomes invalid to refer to it. As such, the error says that -the borrow ‘doesn’t live long enough’ because it’s not valid for the right -amount of time. - -The same problem occurs when the reference is declared _before_ the variable it -refers to. This is because resources within the same scope are freed in the -opposite order they were declared: - -```rust,ignore -let y: &i32; -let x = 5; -y = &x; - -println!("{}", y); -``` - -We get this error: - -```text -error: `x` does not live long enough -y = &x; - ^ -note: reference must be valid for the block suffix following statement 0 at -2:16... - let y: &i32; - let x = 5; - y = &x; - - println!("{}", y); -} - -note: ...but borrowed value is only valid for the block suffix following -statement 1 at 3:14 - let x = 5; - y = &x; - - println!("{}", y); -} -``` - -In the above example, `y` is declared before `x`, meaning that `y` lives longer -than `x`, which is not allowed. diff --git a/src/doc/book/src/release-channels.md b/src/doc/book/src/release-channels.md deleted file mode 100644 index af89ca8348424..0000000000000 --- a/src/doc/book/src/release-channels.md +++ /dev/null @@ -1,68 +0,0 @@ -# Release Channels - -The Rust project uses a concept called ‘release channels’ to manage releases. -It’s important to understand this process to choose which version of Rust -your project should use. - -# Overview - -There are three channels for Rust releases: - -* Nightly -* Beta -* Stable - -New nightly releases are created once a day. Every six weeks, the latest -nightly release is promoted to ‘Beta’. At that point, it will only receive -patches to fix serious errors. Six weeks later, the beta is promoted to -‘Stable’, and becomes the next release of `1.x`. - -This process happens in parallel. So every six weeks, on the same day, -nightly goes to beta, beta goes to stable. When `1.x` is released, at -the same time, `1.(x + 1)-beta` is released, and the nightly becomes the -first version of `1.(x + 2)-nightly`. - -# Choosing a version - -Generally speaking, unless you have a specific reason, you should be using the -stable release channel. These releases are intended for a general audience. - -However, depending on your interest in Rust, you may choose to use nightly -instead. The basic tradeoff is this: in the nightly channel, you can use -unstable, new Rust features. However, unstable features are subject to change, -and so any new nightly release may break your code. If you use the stable -release, you cannot use experimental features, but the next release of Rust -will not cause significant issues through breaking changes. - -# Helping the ecosystem through CI - -What about beta? We encourage all Rust users who use the stable release channel -to also test against the beta channel in their continuous integration systems. -This will help alert the team in case there’s an accidental regression. - -Additionally, testing against nightly can catch regressions even sooner, and so -if you don’t mind a third build, we’d appreciate testing against all channels. - -As an example, many Rust programmers use [Travis](https://travis-ci.org/) to -test their crates, which is free for open source projects. Travis [supports -Rust directly][travis], and you can use a `.travis.yml` file like this to -test on all channels: - -```yaml -language: rust -rust: - - nightly - - beta - - stable - -matrix: - allow_failures: - - rust: nightly -``` - -[travis]: http://docs.travis-ci.com/user/languages/rust/ - -With this configuration, Travis will test all three channels, but if something -breaks on nightly, it won’t fail your build. A similar configuration is -recommended for any CI system, check the documentation of the one you’re -using for more details. diff --git a/src/doc/book/src/strings.md b/src/doc/book/src/strings.md deleted file mode 100644 index ffc9d2b697684..0000000000000 --- a/src/doc/book/src/strings.md +++ /dev/null @@ -1,195 +0,0 @@ -# Strings - -Strings are an important concept for any programmer to master. Rust’s string -handling system is a bit different from other languages, due to its systems -focus. Any time you have a data structure of variable size, things can get -tricky, and strings are a re-sizable data structure. That being said, Rust’s -strings also work differently than in some other systems languages, such as C. - -Let’s dig into the details. A ‘string’ is a sequence of Unicode scalar values -encoded as a stream of UTF-8 bytes. All strings are guaranteed to be a valid -encoding of UTF-8 sequences. Additionally, unlike some systems languages, -strings are not NUL-terminated and can contain NUL bytes. - -Rust has two main types of strings: `&str` and `String`. Let’s talk about -`&str` first. These are called ‘string slices’. A string slice has a fixed -size, and cannot be mutated. It is a reference to a sequence of UTF-8 bytes. - -```rust -let greeting = "Hello there."; // greeting: &'static str -``` - -`"Hello there."` is a string literal and its type is `&'static str`. A string -literal is a string slice that is statically allocated, meaning that it’s saved -inside our compiled program, and exists for the entire duration it runs. The -`greeting` binding is a reference to this statically allocated string. Any -function expecting a string slice will also accept a string literal. - -String literals can span multiple lines. There are two forms. The first will -include the newline and the leading spaces: - -```rust -let s = "foo - bar"; - -assert_eq!("foo\n bar", s); -``` - -The second, with a `\`, trims the spaces and the newline: - -```rust -let s = "foo\ - bar"; - -assert_eq!("foobar", s); -``` - -Note that you normally cannot access a `str` directly, but only through a `&str` -reference. This is because `str` is an unsized type which requires additional -runtime information to be usable. For more information see the chapter on -[unsized types][ut]. - -Rust has more than only `&str`s though. A `String` is a heap-allocated string. -This string is growable, and is also guaranteed to be UTF-8. `String`s are -commonly created by converting from a string slice using the `to_string` -method. - -```rust -let mut s = "Hello".to_string(); // mut s: String -println!("{}", s); - -s.push_str(", world."); -println!("{}", s); -``` - -`String`s will coerce into `&str` with an `&`: - -```rust -fn takes_slice(slice: &str) { - println!("Got: {}", slice); -} - -fn main() { - let s = "Hello".to_string(); - takes_slice(&s); -} -``` - -This coercion does not happen for functions that accept one of `&str`’s traits -instead of `&str`. For example, [`TcpStream::connect`][connect] has a parameter -of type `ToSocketAddrs`. A `&str` is okay but a `String` must be explicitly -converted using `&*`. - -```rust,no_run -use std::net::TcpStream; - -TcpStream::connect("192.168.0.1:3000"); // Parameter is of type &str. - -let addr_string = "192.168.0.1:3000".to_string(); -TcpStream::connect(&*addr_string); // Convert `addr_string` to &str. -``` - -Viewing a `String` as a `&str` is cheap, but converting the `&str` to a -`String` involves allocating memory. No reason to do that unless you have to! - -## Indexing - -Because strings are valid UTF-8, they do not support indexing: - -```rust,ignore -let s = "hello"; - -println!("The first letter of s is {}", s[0]); // ERROR!!! -``` - -Usually, access to a vector with `[]` is very fast. But, because each character -in a UTF-8 encoded string can be multiple bytes, you have to walk over the -string to find the nᵗʰ letter of a string. This is a significantly more -expensive operation, and we don’t want to be misleading. Furthermore, ‘letter’ -isn’t something defined in Unicode, exactly. We can choose to look at a string as -individual bytes, or as codepoints: - -```rust -let hachiko = "忠犬ハチ公"; - -for b in hachiko.as_bytes() { - print!("{}, ", b); -} - -println!(""); - -for c in hachiko.chars() { - print!("{}, ", c); -} - -println!(""); -``` - -This prints: - -```text -229, 191, 160, 231, 138, 172, 227, 131, 143, 227, 131, 129, 229, 133, 172, -忠, 犬, ハ, チ, 公, -``` - -As you can see, there are more bytes than `char`s. - -You can get something similar to an index like this: - -```rust -# let hachiko = "忠犬ハチ公"; -let dog = hachiko.chars().nth(1); // Kinda like `hachiko[1]`. -``` - -This emphasizes that we have to walk from the beginning of the list of `chars`. - -## Slicing - -You can get a slice of a string with the slicing syntax: - -```rust -let dog = "hachiko"; -let hachi = &dog[0..5]; -``` - -But note that these are _byte_ offsets, not _character_ offsets. So -this will fail at runtime: - -```rust,should_panic -let dog = "忠犬ハチ公"; -let hachi = &dog[0..2]; -``` - -with this error: - -```text -thread 'main' panicked at 'byte index 2 is not a char boundary; it is inside '忠' -(bytes 0..3) of `忠犬ハチ公`' -``` - -## Concatenation - -If you have a `String`, you can concatenate a `&str` to the end of it: - -```rust -let hello = "Hello ".to_string(); -let world = "world!"; - -let hello_world = hello + world; -``` - -But if you have two `String`s, you need an `&`: - -```rust -let hello = "Hello ".to_string(); -let world = "world!".to_string(); - -let hello_world = hello + &world; -``` - -This is because `&String` can automatically coerce to a `&str`. This is a -feature called ‘[`Deref` coercions][dc]’. - -[ut]: unsized-types.html -[dc]: deref-coercions.html -[connect]: ../std/net/struct.TcpStream.html#method.connect diff --git a/src/doc/book/src/structs.md b/src/doc/book/src/structs.md deleted file mode 100644 index 3efa4f0e0a8d8..0000000000000 --- a/src/doc/book/src/structs.md +++ /dev/null @@ -1,279 +0,0 @@ -# Structs - -`struct`s are a way of creating more complex data types. For example, if we were -doing calculations involving coordinates in 2D space, we would need both an `x` -and a `y` value: - -```rust -let origin_x = 0; -let origin_y = 0; -``` - -A `struct` lets us combine these two into a single, unified datatype with `x` -and `y` as field labels: - -```rust -struct Point { - x: i32, - y: i32, -} - -fn main() { - let origin = Point { x: 0, y: 0 }; // origin: Point - - println!("The origin is at ({}, {})", origin.x, origin.y); -} -``` - -There’s a lot going on here, so let’s break it down. We declare a `struct` with -the `struct` keyword, and then with a name. By convention, `struct`s begin with -a capital letter and are camel cased: `PointInSpace`, not `Point_In_Space`. - -We can create an instance of our `struct` via `let`, as usual, but we use a `key: -value` style syntax to set each field. The order doesn’t need to be the same as -in the original declaration. - -Finally, because fields have names, we can access them through dot -notation: `origin.x`. - -The values in `struct`s are immutable by default, like other bindings in Rust. -Use `mut` to make them mutable: - -```rust -struct Point { - x: i32, - y: i32, -} - -fn main() { - let mut point = Point { x: 0, y: 0 }; - - point.x = 5; - - println!("The point is at ({}, {})", point.x, point.y); -} -``` - -This will print `The point is at (5, 0)`. - -Rust does not support field mutability at the language level, so you cannot -write something like this: - -```rust,ignore -struct Point { - mut x: i32, // This causes an error. - y: i32, -} -``` - -Mutability is a property of the binding, not of the structure itself. If you’re -used to field-level mutability, this may seem strange at first, but it -significantly simplifies things. It even lets you make things mutable on a temporary -basis: - -```rust,ignore -struct Point { - x: i32, - y: i32, -} - -fn main() { - let mut point = Point { x: 0, y: 0 }; - - point.x = 5; - - let point = point; // `point` is now immutable. - - point.y = 6; // This causes an error. -} -``` - -Your structure can still contain `&mut` references, which will let -you do some kinds of mutation: - -```rust -struct Point { - x: i32, - y: i32, -} - -struct PointRef<'a> { - x: &'a mut i32, - y: &'a mut i32, -} - -fn main() { - let mut point = Point { x: 0, y: 0 }; - - { - let r = PointRef { x: &mut point.x, y: &mut point.y }; - - *r.x = 5; - *r.y = 6; - } - - assert_eq!(5, point.x); - assert_eq!(6, point.y); -} -``` - -Initialization of a data structure (struct, enum, union) can be simplified when -fields of the data structure are initialized with variables of the same -names as the fields. - -``` -#[derive(Debug)] -struct Person<'a> { - name: &'a str, - age: u8 -} - -fn main() { - // Create struct with field init shorthand - let name = "Peter"; - let age = 27; - let peter = Person { name, age }; - - // Debug-print struct - println!("{:?}", peter); -} -``` - -# Update syntax - -A `struct` can include `..` to indicate that you want to use a copy of some -other `struct` for some of the values. For example: - -```rust -struct Point3d { - x: i32, - y: i32, - z: i32, -} - -let mut point = Point3d { x: 0, y: 0, z: 0 }; -point = Point3d { y: 1, .. point }; -``` - -This gives `point` a new `y`, but keeps the old `x` and `z` values. It doesn’t -have to be the same `struct` either, you can use this syntax when making new -ones, and it will copy the values you don’t specify: - -```rust -# struct Point3d { -# x: i32, -# y: i32, -# z: i32, -# } -let origin = Point3d { x: 0, y: 0, z: 0 }; -let point = Point3d { z: 1, x: 2, .. origin }; -``` - -# Tuple structs - -Rust has another data type that’s like a hybrid between a [tuple][tuple] and a -`struct`, called a ‘tuple struct’. Tuple structs have a name, but their fields -don't. They are declared with the `struct` keyword, and then with a name -followed by a tuple: - -[tuple]: primitive-types.html#tuples - -```rust -struct Color(i32, i32, i32); -struct Point(i32, i32, i32); - -let black = Color(0, 0, 0); -let origin = Point(0, 0, 0); -``` - -Here, `black` and `origin` are not the same type, even though they contain the -same values. - -The members of a tuple struct may be accessed by dot notation or destructuring -`let`, just like regular tuples: - -```rust -# struct Color(i32, i32, i32); -# struct Point(i32, i32, i32); -# let black = Color(0, 0, 0); -# let origin = Point(0, 0, 0); -let black_r = black.0; -let Point(_, origin_y, origin_z) = origin; -``` - -Patterns like `Point(_, origin_y, origin_z)` are also used in -[match expressions][match]. - -One case when a tuple struct is very useful is when it has only one element. -We call this the ‘newtype’ pattern, because it allows you to create a new type -that is distinct from its contained value and also expresses its own semantic -meaning: - -```rust -struct Inches(i32); - -let length = Inches(10); - -let Inches(integer_length) = length; -println!("length is {} inches", integer_length); -``` - -As above, you can extract the inner integer type through a destructuring `let`. -In this case, the `let Inches(integer_length)` assigns `10` to `integer_length`. -We could have used dot notation to do the same thing: - -```rust -# struct Inches(i32); -# let length = Inches(10); -let integer_length = length.0; -``` - -It's always possible to use a `struct` instead of a tuple struct, and can be -clearer. We could write `Color` and `Point` like this instead: - -```rust -struct Color { - red: i32, - blue: i32, - green: i32, -} - -struct Point { - x: i32, - y: i32, - z: i32, -} -``` - -Good names are important, and while values in a tuple struct can be -referenced with dot notation as well, a `struct` gives us actual names, -rather than positions. - -[match]: match.html - -# Unit-like structs - -You can define a `struct` with no members at all: - -```rust,compile_fail,E0423 -struct Electron {} // Use empty braces... -struct Proton; // ...or just a semicolon. - -// Use the same notation when creating an instance. -let x = Electron {}; -let y = Proton; -let z = Electron; // Error -``` - -Such a `struct` is called ‘unit-like’ because it resembles the empty -tuple, `()`, sometimes called ‘unit’. Like a tuple struct, it defines a -new type. - -This is rarely useful on its own (although sometimes it can serve as a -marker type), but in combination with other features, it can become -useful. For instance, a library may ask you to create a structure that -implements a certain [trait][trait] to handle events. If you don’t have -any data you need to store in the structure, you can create a -unit-like `struct`. - -[trait]: traits.html diff --git a/src/doc/book/src/syntax-and-semantics.md b/src/doc/book/src/syntax-and-semantics.md deleted file mode 100644 index aa4c1251024de..0000000000000 --- a/src/doc/book/src/syntax-and-semantics.md +++ /dev/null @@ -1,10 +0,0 @@ -# Syntax and Semantics - -This chapter breaks Rust down into small chunks, one for each concept. - -If you’d like to learn Rust from the bottom up, reading this in order is a -great way to do that. - -These sections also form a reference for each concept, so if you’re reading -another tutorial and find something confusing, you can find it explained -somewhere in here. diff --git a/src/doc/book/src/syntax-index.md b/src/doc/book/src/syntax-index.md deleted file mode 100644 index a06520f4ac2f3..0000000000000 --- a/src/doc/book/src/syntax-index.md +++ /dev/null @@ -1,253 +0,0 @@ -# Syntax Index - -## Keywords - -* `as`: primitive casting, or disambiguating the specific trait containing an item. See [Casting Between Types (`as`)], [Universal Function Call Syntax (Angle-bracket Form)], [Associated Types]. -* `break`: break out of loop. See [Loops (Ending Iteration Early)]. -* `const`: constant items and constant raw pointers. See [`const` and `static`], [Raw Pointers]. -* `continue`: continue to next loop iteration. See [Loops (Ending Iteration Early)]. -* `crate`: external crate linkage. See [Crates and Modules (Importing External Crates)]. -* `else`: fallback for `if` and `if let` constructs. See [`if`], [`if let`]. -* `enum`: defining enumeration. See [Enums]. -* `extern`: external crate, function, and variable linkage. See [Crates and Modules (Importing External Crates)], [Foreign Function Interface]. -* `false`: boolean false literal. See [Primitive Types (Booleans)]. -* `fn`: function definition and function pointer types. See [Functions]. -* `for`: iterator loop, part of trait `impl` syntax, and higher-ranked lifetime syntax. See [Loops (`for`)], [Method Syntax]. -* `if`: conditional branching. See [`if`], [`if let`]. -* `impl`: inherent and trait implementation blocks. See [Method Syntax]. -* `in`: part of `for` loop syntax. See [Loops (`for`)]. -* `let`: variable binding. See [Variable Bindings]. -* `loop`: unconditional, infinite loop. See [Loops (`loop`)]. -* `match`: pattern matching. See [Match]. -* `mod`: module declaration. See [Crates and Modules (Defining Modules)]. -* `move`: part of closure syntax. See [Closures (`move` closures)]. -* `mut`: denotes mutability in pointer types and pattern bindings. See [Mutability]. -* `pub`: denotes public visibility in `struct` fields, `impl` blocks, and modules. See [Crates and Modules (Exporting a Public Interface)]. -* `ref`: by-reference binding. See [Patterns (`ref` and `ref mut`)]. -* `return`: return from function. See [Functions (Early Returns)]. -* `Self`: implementor type alias. See [Traits]. -* `self`: method subject. See [Method Syntax (Method Calls)]. -* `static`: global variable. See [`const` and `static` (`static`)]. -* `struct`: structure definition. See [Structs]. -* `trait`: trait definition. See [Traits]. -* `true`: boolean true literal. See [Primitive Types (Booleans)]. -* `type`: type alias, and associated type definition. See [`type` Aliases], [Associated Types]. -* `unsafe`: denotes unsafe code, functions, traits, and implementations. See [Unsafe]. -* `use`: import symbols into scope. See [Crates and Modules (Importing Modules with `use`)]. -* `where`: type constraint clauses. See [Traits (`where` clause)]. -* `while`: conditional loop. See [Loops (`while`)]. - -## Operators and Symbols - -* `!` (`ident!(…)`, `ident!{…}`, `ident![…]`): denotes macro expansion. See [Macros]. -* `!` (`!expr`): bitwise or logical complement. Overloadable (`Not`). -* `!=` (`var != expr`): nonequality comparison. Overloadable (`PartialEq`). -* `%` (`expr % expr`): arithmetic remainder. Overloadable (`Rem`). -* `%=` (`var %= expr`): arithmetic remainder & assignment. Overloadable (`RemAssign`). -* `&` (`expr & expr`): bitwise and. Overloadable (`BitAnd`). -* `&` (`&expr`, `&mut expr`): borrow. See [References and Borrowing]. -* `&` (`&type`, `&mut type`, `&'a type`, `&'a mut type`): borrowed pointer type. See [References and Borrowing]. -* `&=` (`var &= expr`): bitwise and & assignment. Overloadable (`BitAndAssign`). -* `&&` (`expr && expr`): logical and. -* `*` (`expr * expr`): arithmetic multiplication. Overloadable (`Mul`). -* `*` (`*expr`): dereference. -* `*` (`*const type`, `*mut type`): raw pointer. See [Raw Pointers]. -* `*=` (`var *= expr`): arithmetic multiplication & assignment. Overloadable (`MulAssign`). -* `+` (`expr + expr`): arithmetic addition. Overloadable (`Add`). -* `+` (`trait + trait`, `'a + trait`): compound type constraint. See [Traits (Multiple Trait Bounds)]. -* `+=` (`var += expr`): arithmetic addition & assignment. Overloadable (`AddAssign`). -* `,`: argument and element separator. See [Attributes], [Functions], [Structs], [Generics], [Match], [Closures], [Crates and Modules (Importing Modules with `use`)]. -* `-` (`expr - expr`): arithmetic subtraction. Overloadable (`Sub`). -* `-` (`- expr`): arithmetic negation. Overloadable (`Neg`). -* `-=` (`var -= expr`): arithmetic subtraction & assignment. Overloadable (`SubAssign`). -* `->` (`fn(…) -> type`, `|…| -> type`): function and closure return type. See [Functions], [Closures]. -* `.` (`expr.ident`): member access. See [Structs], [Method Syntax]. -* `..` (`..`, `expr..`, `..expr`, `expr..expr`): right-exclusive range literal. -* `..` (`..expr`): struct literal update syntax. See [Structs (Update syntax)]. -* `..` (`variant(x, ..)`, `struct_type { x, .. }`): "and the rest" pattern binding. See [Patterns (Ignoring bindings)]. -* `...` (`...expr`, `expr...expr`) *in an expression*: inclusive range expression. See [Iterators]. -* `...` (`expr...expr`) *in a pattern*: inclusive range pattern. See [Patterns (Ranges)]. -* `/` (`expr / expr`): arithmetic division. Overloadable (`Div`). -* `/=` (`var /= expr`): arithmetic division & assignment. Overloadable (`DivAssign`). -* `:` (`pat: type`, `ident: type`): constraints. See [Variable Bindings], [Functions], [Structs], [Traits]. -* `:` (`ident: expr`): struct field initializer. See [Structs]. -* `:` (`'a: loop {…}`): loop label. See [Loops (Loops Labels)]. -* `;`: statement and item terminator. -* `;` (`[…; len]`): part of fixed-size array syntax. See [Primitive Types (Arrays)]. -* `<<` (`expr << expr`): left-shift. Overloadable (`Shl`). -* `<<=` (`var <<= expr`): left-shift & assignment. Overloadable (`ShlAssign`). -* `<` (`expr < expr`): less-than comparison. Overloadable (`PartialOrd`). -* `<=` (`var <= expr`): less-than or equal-to comparison. Overloadable (`PartialOrd`). -* `=` (`var = expr`, `ident = type`): assignment/equivalence. See [Variable Bindings], [`type` Aliases], generic parameter defaults. -* `==` (`var == expr`): equality comparison. Overloadable (`PartialEq`). -* `=>` (`pat => expr`): part of match arm syntax. See [Match]. -* `>` (`expr > expr`): greater-than comparison. Overloadable (`PartialOrd`). -* `>=` (`var >= expr`): greater-than or equal-to comparison. Overloadable (`PartialOrd`). -* `>>` (`expr >> expr`): right-shift. Overloadable (`Shr`). -* `>>=` (`var >>= expr`): right-shift & assignment. Overloadable (`ShrAssign`). -* `@` (`ident @ pat`): pattern binding. See [Patterns (Bindings)]. -* `^` (`expr ^ expr`): bitwise exclusive or. Overloadable (`BitXor`). -* `^=` (`var ^= expr`): bitwise exclusive or & assignment. Overloadable (`BitXorAssign`). -* `|` (`expr | expr`): bitwise or. Overloadable (`BitOr`). -* `|` (`pat | pat`): pattern alternatives. See [Patterns (Multiple patterns)]. -* `|` (`|…| expr`): closures. See [Closures]. -* `|=` (`var |= expr`): bitwise or & assignment. Overloadable (`BitOrAssign`). -* `||` (`expr || expr`): logical or. -* `_`: "ignored" pattern binding (see [Patterns (Ignoring bindings)]). Also used to make integer-literals readable (see [Reference (Integer literals)]). -* `?` (`expr?`): Error propagation. Returns early when `Err(_)` is encountered, unwraps otherwise. Similar to the [`try!` macro]. - -## Other Syntax - -<!-- Various bits of standalone stuff. --> - -* `'ident`: named lifetime or loop label. See [Lifetimes], [Loops (Loops Labels)]. -* `…u8`, `…i32`, `…f64`, `…usize`, …: numeric literal of specific type. -* `"…"`: string literal. See [Strings]. -* `r"…"`, `r#"…"#`, `r##"…"##`, …: raw string literal, escape characters are not processed. See [Reference (Raw String Literals)]. -* `b"…"`: byte string literal, constructs a `[u8]` instead of a string. See [Reference (Byte String Literals)]. -* `br"…"`, `br#"…"#`, `br##"…"##`, …: raw byte string literal, combination of raw and byte string literal. See [Reference (Raw Byte String Literals)]. -* `'…'`: character literal. See [Primitive Types (`char`)]. -* `b'…'`: ASCII byte literal. -* `|…| expr`: closure. See [Closures]. - -<!-- Path-related syntax --> - -* `ident::ident`: path. See [Crates and Modules (Defining Modules)]. -* `::path`: path relative to the crate root (*i.e.* an explicitly absolute path). See [Crates and Modules (Re-exporting with `pub use`)]. -* `self::path`: path relative to the current module (*i.e.* an explicitly relative path). See [Crates and Modules (Re-exporting with `pub use`)]. -* `super::path`: path relative to the parent of the current module. See [Crates and Modules (Re-exporting with `pub use`)]. -* `type::ident`, `<type as trait>::ident`: associated constants, functions, and types. See [Associated Types]. -* `<type>::…`: associated item for a type which cannot be directly named (*e.g.* `<&T>::…`, `<[T]>::…`, *etc.*). See [Associated Types]. -* `trait::method(…)`: disambiguating a method call by naming the trait which defines it. See [Universal Function Call Syntax]. -* `type::method(…)`: disambiguating a method call by naming the type for which it's defined. See [Universal Function Call Syntax]. -* `<type as trait>::method(…)`: disambiguating a method call by naming the trait _and_ type. See [Universal Function Call Syntax (Angle-bracket Form)]. - -<!-- Generics --> - -* `path<…>` (*e.g.* `Vec<u8>`): specifies parameters to generic type *in a type*. See [Generics]. -* `path::<…>`, `method::<…>` (*e.g.* `"42".parse::<i32>()`): specifies parameters to generic type, function, or method *in an expression*. See [Generics § Resolving ambiguities](generics.html#resolving-ambiguities). -* `fn ident<…> …`: define generic function. See [Generics]. -* `struct ident<…> …`: define generic structure. See [Generics]. -* `enum ident<…> …`: define generic enumeration. See [Generics]. -* `impl<…> …`: define generic implementation. -* `for<…> type`: higher-ranked lifetime bounds. -* `type<ident=type>` (*e.g.* `Iterator<Item=T>`): a generic type where one or more associated types have specific assignments. See [Associated Types]. - -<!-- Constraints --> - -* `T: U`: generic parameter `T` constrained to types that implement `U`. See [Traits]. -* `T: 'a`: generic type `T` must outlive lifetime `'a`. When we say that a type 'outlives' the lifetime, we mean that it cannot transitively contain any references with lifetimes shorter than `'a`. -* `T : 'static`: The generic type `T` contains no borrowed references other than `'static` ones. -* `'b: 'a`: generic lifetime `'b` must outlive lifetime `'a`. -* `T: ?Sized`: allow generic type parameter to be a dynamically-sized type. See [Unsized Types (`?Sized`)]. -* `'a + trait`, `trait + trait`: compound type constraint. See [Traits (Multiple Trait Bounds)]. - -<!-- Macros and attributes --> - -* `#[meta]`: outer attribute. See [Attributes]. -* `#![meta]`: inner attribute. See [Attributes]. -* `$ident`: macro substitution. See [Macros]. -* `$ident:kind`: macro capture. See [Macros]. -* `$(…)…`: macro repetition. See [Macros]. - -<!-- Comments --> - -* `//`: line comment. See [Comments]. -* `//!`: inner line doc comment. See [Comments]. -* `///`: outer line doc comment. See [Comments]. -* `/*…*/`: block comment. See [Comments]. -* `/*!…*/`: inner block doc comment. See [Comments]. -* `/**…*/`: outer block doc comment. See [Comments]. - -<!-- Special types --> - -* `!`: always empty Never type. See [Diverging Functions]. - -<!-- Various things involving parens and tuples --> - -* `()`: empty tuple (*a.k.a.* unit), both literal and type. -* `(expr)`: parenthesized expression. -* `(expr,)`: single-element tuple expression. See [Primitive Types (Tuples)]. -* `(type,)`: single-element tuple type. See [Primitive Types (Tuples)]. -* `(expr, …)`: tuple expression. See [Primitive Types (Tuples)]. -* `(type, …)`: tuple type. See [Primitive Types (Tuples)]. -* `expr(expr, …)`: function call expression. Also used to initialize tuple `struct`s and tuple `enum` variants. See [Functions]. -* `ident!(…)`, `ident!{…}`, `ident![…]`: macro invocation. See [Macros]. -* `expr.0`, `expr.1`, …: tuple indexing. See [Primitive Types (Tuple Indexing)]. - -<!-- Bracey things --> - -* `{…}`: block expression. -* `Type {…}`: `struct` literal. See [Structs]. - -<!-- Brackety things --> - -* `[…]`: array literal. See [Primitive Types (Arrays)]. -* `[expr; len]`: array literal containing `len` copies of `expr`. See [Primitive Types (Arrays)]. -* `[type; len]`: array type containing `len` instances of `type`. See [Primitive Types (Arrays)]. -* `expr[expr]`: collection indexing. Overloadable (`Index`, `IndexMut`). -* `expr[..]`, `expr[a..]`, `expr[..b]`, `expr[a..b]`: collection indexing pretending to be collection slicing, using `Range`, `RangeFrom`, `RangeTo`, `RangeFull` as the "index". - -[`const` and `static` (`static`)]: const-and-static.html#static -[`const` and `static`]: const-and-static.html -[`if let`]: if-let.html -[`if`]: if.html -[`type` Aliases]: type-aliases.html -[Associated Types]: associated-types.html -[Attributes]: attributes.html -[Casting Between Types (`as`)]: casting-between-types.html#as -[Closures (`move` closures)]: closures.html#move-closures -[Closures]: closures.html -[Comments]: comments.html -[Crates and Modules (Defining Modules)]: crates-and-modules.html#defining-modules -[Crates and Modules (Exporting a Public Interface)]: crates-and-modules.html#exporting-a-public-interface -[Crates and Modules (Importing External Crates)]: crates-and-modules.html#importing-external-crates -[Crates and Modules (Importing Modules with `use`)]: crates-and-modules.html#importing-modules-with-use -[Crates and Modules (Re-exporting with `pub use`)]: crates-and-modules.html#re-exporting-with-pub-use -[Diverging Functions]: functions.html#diverging-functions -[Enums]: enums.html -[Foreign Function Interface]: ffi.html -[Functions (Early Returns)]: functions.html#early-returns -[Functions]: functions.html -[Generics]: generics.html -[Iterators]: iterators.html -[`try!` macro]: error-handling.html#the-try-macro -[Lifetimes]: lifetimes.html -[Loops (`for`)]: loops.html#for -[Loops (`loop`)]: loops.html#loop -[Loops (`while`)]: loops.html#while -[Loops (Ending Iteration Early)]: loops.html#ending-iteration-early -[Loops (Loops Labels)]: loops.html#loop-labels -[Macros]: macros.html -[Match]: match.html -[Method Syntax (Method Calls)]: method-syntax.html#method-calls -[Method Syntax]: method-syntax.html -[Mutability]: mutability.html -[Operators and Overloading]: operators-and-overloading.html -[Patterns (`ref` and `ref mut`)]: patterns.html#ref-and-ref-mut -[Patterns (Bindings)]: patterns.html#bindings -[Patterns (Ignoring bindings)]: patterns.html#ignoring-bindings -[Patterns (Multiple patterns)]: patterns.html#multiple-patterns -[Patterns (Ranges)]: patterns.html#ranges -[Primitive Types (`char`)]: primitive-types.html#char -[Primitive Types (Arrays)]: primitive-types.html#arrays -[Primitive Types (Booleans)]: primitive-types.html#booleans -[Primitive Types (Tuple Indexing)]: primitive-types.html#tuple-indexing -[Primitive Types (Tuples)]: primitive-types.html#tuples -[Raw Pointers]: raw-pointers.html -[Reference (Byte String Literals)]: ../reference/tokens.html/#byte-string-literals -[Reference (Integer literals)]: ../reference/tokens.html#integer-literals -[Reference (Raw Byte String Literals)]: ../reference/tokens.html#raw-byte-string-literals -[Reference (Raw String Literals)]: ../reference/tokens.html#raw-string-literals -[References and Borrowing]: references-and-borrowing.html -[Strings]: strings.html -[Structs (Update syntax)]: structs.html#update-syntax -[Structs]: structs.html -[Traits (`where` clause)]: traits.html#where-clause -[Traits (Multiple Trait Bounds)]: traits.html#multiple-trait-bounds -[Traits]: traits.html -[Universal Function Call Syntax]: ufcs.html -[Universal Function Call Syntax (Angle-bracket Form)]: ufcs.html#angle-bracket-form -[Unsafe]: unsafe.html -[Unsized Types (`?Sized`)]: unsized-types.html#sized -[Variable Bindings]: variable-bindings.html diff --git a/src/doc/book/src/testing.md b/src/doc/book/src/testing.md deleted file mode 100644 index 291c4481d5513..0000000000000 --- a/src/doc/book/src/testing.md +++ /dev/null @@ -1,633 +0,0 @@ -# Testing - -> Program testing can be a very effective way to show the presence of bugs, but -> it is hopelessly inadequate for showing their absence. -> -> Edsger W. Dijkstra, "The Humble Programmer" (1972) - -Let's talk about how to test Rust code. What we will not be talking about is -the right way to test Rust code. There are many schools of thought regarding -the right and wrong way to write tests. All of these approaches use the same -basic tools, and so we'll show you the syntax for using them. - -# The `test` attribute - -At its simplest, a test in Rust is a function that's annotated with the `test` -attribute. Let's make a new project with Cargo called `adder`: - -```bash -$ cargo new adder -$ cd adder -``` - -Cargo will automatically generate a simple test when you make a new project. -Here's the contents of `src/lib.rs`: - -```rust,ignore -# // The next line exists to trick play.rust-lang.org into running our code as a -# // test: -# // fn main -# -#[cfg(test)] -mod tests { - #[test] - fn it_works() { - } -} -``` - -For now, let's remove the `mod` bit, and focus on just the function: - -```rust,ignore -# // The next line exists to trick play.rust-lang.org into running our code as a -# // test: -# // fn main -# -#[test] -fn it_works() { -} -``` - -Note the `#[test]`. This attribute indicates that this is a test function. It -currently has no body. That's good enough to pass! We can run the tests with -`cargo test`: - -```bash -$ cargo test - Compiling adder v0.1.0 (file:///home/you/projects/adder) - Finished debug [unoptimized + debuginfo] target(s) in 0.15 secs - Running target/debug/deps/adder-941f01916ca4a642 - -running 1 test -test it_works ... ok - -test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured - - Doc-tests adder - -running 0 tests - -test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured -``` - -Cargo compiled and ran our tests. There are two sets of output here: one -for the test we wrote, and another for documentation tests. We'll talk about -those later. For now, see this line: - -```text -test it_works ... ok -``` - -Note the `it_works`. This comes from the name of our function: - -```rust -# fn main() { -fn it_works() { -} -# } -``` - -We also get a summary line: - -```text -test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured -``` - -So why does our do-nothing test pass? Any test which doesn't `panic!` passes, -and any test that does `panic!` fails. Let's make our test fail: - -```rust,ignore -# // The next line exists to trick play.rust-lang.org into running our code as a -# // test: -# // fn main -# -#[test] -fn it_works() { - assert!(false); -} -``` - -`assert!` is a macro provided by Rust which takes one argument: if the argument -is `true`, nothing happens. If the argument is `false`, it will `panic!`. Let's -run our tests again: - -```bash -$ cargo test - Compiling adder v0.1.0 (file:///home/you/projects/adder) - Finished debug [unoptimized + debuginfo] target(s) in 0.17 secs - Running target/debug/deps/adder-941f01916ca4a642 - -running 1 test -test it_works ... FAILED - -failures: - ----- it_works stdout ---- - thread 'it_works' panicked at 'assertion failed: false', src/lib.rs:5 -note: Run with `RUST_BACKTRACE=1` for a backtrace. - - -failures: - it_works - -test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured - -error: test failed -``` - -Rust indicates that our test failed: - -```text -test it_works ... FAILED -``` - -And that's reflected in the summary line: - -```text -test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured -``` - -We also get a non-zero status code. We can use `$?` on OS X and Linux: - -```bash -$ echo $? -101 -``` - -On Windows, if you’re using `cmd`: - -```bash -> echo %ERRORLEVEL% -``` - -And if you’re using PowerShell: - -```bash -> echo $LASTEXITCODE # the code itself -> echo $? # a boolean, fail or succeed -``` - -This is useful if you want to integrate `cargo test` into other tooling. - -We can invert our test's failure with another attribute: `should_panic`: - -```rust,ignore -# // The next line exists to trick play.rust-lang.org into running our code as a -# // test: -# // fn main -# -#[test] -#[should_panic] -fn it_works() { - assert!(false); -} -``` - -This test will now succeed if we `panic!` and fail if we complete. Let's try it: - -```bash -$ cargo test - Compiling adder v0.1.0 (file:///home/you/projects/adder) - Finished debug [unoptimized + debuginfo] target(s) in 0.17 secs - Running target/debug/deps/adder-941f01916ca4a642 - -running 1 test -test it_works ... ok - -test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured - - Doc-tests adder - -running 0 tests - -test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured -``` - -Rust provides another macro, `assert_eq!`, that compares two arguments for -equality: - -```rust,ignore -# // The next line exists to trick play.rust-lang.org into running our code as a -# // test: -# // fn main -# -#[test] -#[should_panic] -fn it_works() { - assert_eq!("Hello", "world"); -} -``` - -Does this test pass or fail? Because of the `should_panic` attribute, it -passes: - -```bash -$ cargo test - Compiling adder v0.1.0 (file:///home/you/projects/adder) - Finished debug [unoptimized + debuginfo] target(s) in 0.21 secs - Running target/debug/deps/adder-941f01916ca4a642 - -running 1 test -test it_works ... ok - -test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured - - Doc-tests adder - -running 0 tests - -test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured -``` - -`should_panic` tests can be fragile, as it's hard to guarantee that the test -didn't fail for an unexpected reason. To help with this, an optional `expected` -parameter can be added to the `should_panic` attribute. The test harness will -make sure that the failure message contains the provided text. A safer version -of the example above would be: - -```rust,ignore -# // The next line exists to trick play.rust-lang.org into running our code as a -# // test: -# // fn main -# -#[test] -#[should_panic(expected = "assertion failed")] -fn it_works() { - assert_eq!("Hello", "world"); -} -``` - -That's all there is to the basics! Let's write one 'real' test: - -```rust,ignore -# // The next line exists to trick play.rust-lang.org into running our code as a -# // test: -# // fn main -# -pub fn add_two(a: i32) -> i32 { - a + 2 -} - -#[test] -fn it_works() { - assert_eq!(4, add_two(2)); -} -``` - -This is a very common use of `assert_eq!`: call some function with -some known arguments and compare it to the expected output. - -# The `ignore` attribute - -Sometimes a few specific tests can be very time-consuming to execute. These -can be disabled by default by using the `ignore` attribute: - -```rust,ignore -# // The next line exists to trick play.rust-lang.org into running our code as a -# // test: -# // fn main -# -pub fn add_two(a: i32) -> i32 { - a + 2 -} - -#[test] -fn it_works() { - assert_eq!(4, add_two(2)); -} - -#[test] -#[ignore] -fn expensive_test() { - // Code that takes an hour to run... -} -``` - -Now we run our tests and see that `it_works` is run, but `expensive_test` is -not: - -```bash -$ cargo test - Compiling adder v0.1.0 (file:///home/you/projects/adder) - Finished debug [unoptimized + debuginfo] target(s) in 0.20 secs - Running target/debug/deps/adder-941f01916ca4a642 - -running 2 tests -test expensive_test ... ignored -test it_works ... ok - -test result: ok. 1 passed; 0 failed; 1 ignored; 0 measured - - Doc-tests adder - -running 0 tests - -test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured -``` - -The expensive tests can be run explicitly using `cargo test -- --ignored`: - -```bash -$ cargo test -- --ignored - Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs - Running target/debug/deps/adder-941f01916ca4a642 - -running 1 test -test expensive_test ... ok - -test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured - - Doc-tests adder - -running 0 tests - -test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured -``` - -The `--ignored` argument is an argument to the test binary, and not to Cargo, -which is why the command is `cargo test -- --ignored`. - -# The `tests` module - -There is one way in which our existing example is not idiomatic: it's -missing the `tests` module. You might have noticed this test module was -present in the code that was initially generated with `cargo new` but -was missing from our last example. Let's explain what this does. - -The idiomatic way of writing our example looks like this: - -```rust,ignore -# // The next line exists to trick play.rust-lang.org into running our code as a -# // test: -# // fn main -# -pub fn add_two(a: i32) -> i32 { - a + 2 -} - -#[cfg(test)] -mod tests { - use super::add_two; - - #[test] - fn it_works() { - assert_eq!(4, add_two(2)); - } -} -``` - -There's a few changes here. The first is the introduction of a `mod tests` with -a `cfg` attribute. The module allows us to group all of our tests together, and -to also define helper functions if needed, that don't become a part of the rest -of our crate. The `cfg` attribute only compiles our test code if we're -currently trying to run the tests. This can save compile time, and also ensures -that our tests are entirely left out of a normal build. - -The second change is the `use` declaration. Because we're in an inner module, -we need to bring the tested function into scope. This can be annoying if you have -a large module, and so this is a common use of globs. Let's change our -`src/lib.rs` to make use of it: - -```rust,ignore -# // The next line exists to trick play.rust-lang.org into running our code as a -# // test: -# // fn main -# -pub fn add_two(a: i32) -> i32 { - a + 2 -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_works() { - assert_eq!(4, add_two(2)); - } -} -``` - -Note the different `use` line. Now we run our tests: - -```bash -$ cargo test - Updating registry `https://github.com/rust-lang/crates.io-index` - Compiling adder v0.1.0 (file:///home/you/projects/adder) - Running target/debug/deps/adder-91b3e234d4ed382a - -running 1 test -test tests::it_works ... ok - -test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured - - Doc-tests adder - -running 0 tests - -test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured -``` - -It works! - -The current convention is to use the `tests` module to hold your "unit-style" -tests. Anything that tests one small bit of functionality makes sense to -go here. But what about "integration-style" tests instead? For that, we have -the `tests` directory. - -# The `tests` directory - -Each file in `tests/*.rs` directory is treated as an individual crate. -To write an integration test, let's make a `tests` directory and -put a `tests/integration_test.rs` file inside with this as its contents: - -```rust,ignore -# // The next line exists to trick play.rust-lang.org into running our code as a -# // test: -# // fn main -# -# // Sadly, this code will not work in play.rust-lang.org, because we have no -# // crate adder to import. You'll need to try this part on your own machine. -extern crate adder; - -#[test] -fn it_works() { - assert_eq!(4, adder::add_two(2)); -} -``` - -This looks similar to our previous tests, but slightly different. We now have -an `extern crate adder` at the top. This is because each test in the `tests` -directory is an entirely separate crate, and so we need to import our library. -This is also why `tests` is a suitable place to write integration-style tests: -they use the library like any other consumer of it would. - -Let's run them: - -```bash -$ cargo test - Compiling adder v0.1.0 (file:///home/you/projects/adder) - Running target/debug/deps/adder-91b3e234d4ed382a - -running 1 test -test tests::it_works ... ok - -test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured - - Running target/debug/integration_test-68064b69521c828a - -running 1 test -test it_works ... ok - -test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured - - Doc-tests adder - -running 0 tests - -test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured -``` - -Now we have three sections: our previous test is also run, as well as our new -one. - -Cargo will ignore files in subdirectories of the `tests/` directory. -Therefore shared modules in integrations tests are possible. -For example `tests/common/mod.rs` is not separately compiled by cargo but can -be imported in every test with `mod common;` - -That's all there is to the `tests` directory. The `tests` module isn't needed -here, since the whole thing is focused on tests. - -Note, when building integration tests, cargo will not pass the `test` attribute -to the compiler. It means that all parts in `cfg(test)` won't be included in -the build used in your integration tests. - -Let's finally check out that third section: documentation tests. - -# Documentation tests - -Nothing is better than documentation with examples. Nothing is worse than -examples that don't actually work, because the code has changed since the -documentation has been written. To this end, Rust supports automatically -running examples in your documentation (**note:** this only works in library -crates, not binary crates). Here's a fleshed-out `src/lib.rs` with examples: - -```rust,ignore -# // The next line exists to trick play.rust-lang.org into running our code as a -# // test: -# // fn main -# -//! The `adder` crate provides functions that add numbers to other numbers. -//! -//! # Examples -//! -//! ``` -//! assert_eq!(4, adder::add_two(2)); -//! ``` - -/// This function adds two to its argument. -/// -/// # Examples -/// -/// ``` -/// use adder::add_two; -/// -/// assert_eq!(4, add_two(2)); -/// ``` -pub fn add_two(a: i32) -> i32 { - a + 2 -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_works() { - assert_eq!(4, add_two(2)); - } -} -``` - -Note the module-level documentation with `//!` and the function-level -documentation with `///`. Rust's documentation supports Markdown in comments, -and so triple graves mark code blocks. It is conventional to include the -`# Examples` section, exactly like that, with examples following. - -Let's run the tests again: - -```bash -$ cargo test - Compiling adder v0.1.0. (file:///home/you/projects/adder) - Running target/debug/deps/adder-91b3e234d4ed382a - -running 1 test -test tests::it_works ... ok - -test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured - - Running target/debug/integration_test-68064b69521c828a - -running 1 test -test it_works ... ok - -test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured - - Doc-tests adder - -running 2 tests -test add_two_0 ... ok -test _0 ... ok - -test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured -``` - -Now we have all three kinds of tests running! Note the names of the -documentation tests: the `_0` is generated for the module test, and `add_two_0` -for the function test. These will auto increment with names like `add_two_1` as -you add more examples. - -We haven’t covered all of the details with writing documentation tests. For more, -please see the [Documentation chapter](documentation.html). - -# Testing and concurrency - -It is important to note that tests are run concurrently using threads. For this -reason, care should be taken to ensure your tests do not depend on each-other, -or on any shared state. "Shared state" can also include the environment, such -as the current working directory, or environment variables. - -If this is an issue it is possible to control this concurrency, either by -setting the environment variable `RUST_TEST_THREADS`, or by passing the argument -`--test-threads` to the tests: - -```bash -$ RUST_TEST_THREADS=1 cargo test # Run tests with no concurrency -... -$ cargo test -- --test-threads=1 # Same as above -... -``` - -# Test output - -By default Rust's test library captures and discards output to standard -out/error, e.g. output from `println!()`. This too can be controlled using the -environment or a switch: - - -```bash -$ RUST_TEST_NOCAPTURE=1 cargo test # Preserve stdout/stderr -... -$ cargo test -- --nocapture # Same as above -... -``` - -However a better method avoiding capture is to use logging rather than raw -output. Rust has a [standard logging API][log], which provides a frontend to -multiple logging implementations. This can be used in conjunction with the -default [env_logger] to output any debugging information in a manner that can be -controlled at runtime. - -[log]: https://crates.io/crates/log -[env_logger]: https://crates.io/crates/env_logger diff --git a/src/doc/book/src/the-stack-and-the-heap.md b/src/doc/book/src/the-stack-and-the-heap.md deleted file mode 100644 index 6866505df1310..0000000000000 --- a/src/doc/book/src/the-stack-and-the-heap.md +++ /dev/null @@ -1,583 +0,0 @@ -# The Stack and the Heap - -As a systems language, Rust operates at a low level. If you’re coming from a -high-level language, there are some aspects of systems programming that you may -not be familiar with. The most important one is how memory works, with a stack -and a heap. If you’re familiar with how C-like languages use stack allocation, -this chapter will be a refresher. If you’re not, you’ll learn about this more -general concept, but with a Rust-y focus. - -As with most things, when learning about them, we’ll use a simplified model to -start. This lets you get a handle on the basics, without getting bogged down -with details which are, for now, irrelevant. The examples we’ll use aren’t 100% -accurate, but are representative for the level we’re trying to learn at right -now. Once you have the basics down, learning more about how allocators are -implemented, virtual memory, and other advanced topics will reveal the leaks in -this particular abstraction. - -# Memory management - -These two terms are about memory management. The stack and the heap are -abstractions that help you determine when to allocate and deallocate memory. - -Here’s a high-level comparison: - -The stack is very fast, and is where memory is allocated in Rust by default. -But the allocation is local to a function call, and is limited in size. The -heap, on the other hand, is slower, and is explicitly allocated by your -program. But it’s effectively unlimited in size, and is globally accessible. -Note this meaning of heap, which allocates arbitrary-sized blocks of memory in arbitrary -order, is quite different from the heap data structure. - -# The Stack - -Let’s talk about this Rust program: - -```rust -fn main() { - let x = 42; -} -``` - -This program has one variable binding, `x`. This memory needs to be allocated -from somewhere. Rust ‘stack allocates’ by default, which means that basic -values ‘go on the stack’. What does that mean? - -Well, when a function gets called, some memory gets allocated for all of its -local variables and some other information. This is called a ‘stack frame’, and -for the purpose of this tutorial, we’re going to ignore the extra information -and only consider the local variables we’re allocating. So in this case, when -`main()` is run, we’ll allocate a single 32-bit integer for our stack frame. -This is automatically handled for you, as you can see; we didn’t have to write -any special Rust code or anything. - -When the function exits, its stack frame gets deallocated. This happens -automatically as well. - -That’s all there is for this simple program. The key thing to understand here -is that stack allocation is very, very fast. Since we know all the local -variables we have ahead of time, we can grab the memory all at once. And since -we’ll throw them all away at the same time as well, we can get rid of it very -fast too. - -The downside is that we can’t keep values around if we need them for longer -than a single function. We also haven’t talked about what the word, ‘stack’, -means. To do that, we need a slightly more complicated example: - -```rust -fn foo() { - let y = 5; - let z = 100; -} - -fn main() { - let x = 42; - - foo(); -} -``` - -This program has three variables total: two in `foo()`, one in `main()`. Just -as before, when `main()` is called, a single integer is allocated for its stack -frame. But before we can show what happens when `foo()` is called, we need to -visualize what’s going on with memory. Your operating system presents a view of -memory to your program that’s pretty simple: a huge list of addresses, from 0 -to a large number, representing how much RAM your computer has. For example, if -you have a gigabyte of RAM, your addresses go from `0` to `1,073,741,823`. That -number comes from 2<sup>30</sup>, the number of bytes in a gigabyte. [^gigabyte] - -[^gigabyte]: ‘Gigabyte’ can mean two things: 10<sup>9</sup>, or 2<sup>30</sup>. The IEC standard resolved this by stating that ‘gigabyte’ is 10<sup>9</sup>, and ‘gibibyte’ is 2<sup>30</sup>. However, very few people use this terminology, and rely on context to differentiate. We follow in that tradition here. - -This memory is kind of like a giant array: addresses start at zero and go -up to the final number. So here’s a diagram of our first stack frame: - -| Address | Name | Value | -|---------|------|-------| -| 0 | x | 42 | - -We’ve got `x` located at address `0`, with the value `42`. - -When `foo()` is called, a new stack frame is allocated: - -| Address | Name | Value | -|---------|------|-------| -| 2 | z | 100 | -| 1 | y | 5 | -| 0 | x | 42 | - -Because `0` was taken by the first frame, `1` and `2` are used for `foo()`’s -stack frame. It grows upward, the more functions we call. - - -There are some important things we have to take note of here. The numbers 0, 1, -and 2 are all solely for illustrative purposes, and bear no relationship to the -address values the computer will use in reality. In particular, the series of -addresses are in reality going to be separated by some number of bytes that -separate each address, and that separation may even exceed the size of the -value being stored. - -After `foo()` is over, its frame is deallocated: - -| Address | Name | Value | -|---------|------|-------| -| 0 | x | 42 | - -And then, after `main()`, even this last value goes away. Easy! - -It’s called a ‘stack’ because it works like a stack of dinner plates: the first -plate you put down is the last plate to pick back up. Stacks are sometimes -called ‘last in, first out queues’ for this reason, as the last value you put -on the stack is the first one you retrieve from it. - -Let’s try a three-deep example: - -```rust -fn italic() { - let i = 6; -} - -fn bold() { - let a = 5; - let b = 100; - let c = 1; - - italic(); -} - -fn main() { - let x = 42; - - bold(); -} -``` - -We have some kooky function names to make the diagrams clearer. - -Okay, first, we call `main()`: - -| Address | Name | Value | -|---------|------|-------| -| 0 | x | 42 | - -Next up, `main()` calls `bold()`: - -| Address | Name | Value | -|---------|------|-------| -| **3** | **c**|**1** | -| **2** | **b**|**100**| -| **1** | **a**| **5** | -| 0 | x | 42 | - -And then `bold()` calls `italic()`: - -| Address | Name | Value | -|---------|------|-------| -| *4* | *i* | *6* | -| **3** | **c**|**1** | -| **2** | **b**|**100**| -| **1** | **a**| **5** | -| 0 | x | 42 | - -Whew! Our stack is growing tall. - -After `italic()` is over, its frame is deallocated, leaving only `bold()` and -`main()`: - -| Address | Name | Value | -|---------|------|-------| -| **3** | **c**|**1** | -| **2** | **b**|**100**| -| **1** | **a**| **5** | -| 0 | x | 42 | - -And then `bold()` ends, leaving only `main()`: - -| Address | Name | Value | -|---------|------|-------| -| 0 | x | 42 | - -And then we’re done. Getting the hang of it? It’s like piling up dishes: you -add to the top, you take away from the top. - -# The Heap - -Now, this works pretty well, but not everything can work like this. Sometimes, -you need to pass some memory between different functions, or keep it alive for -longer than a single function’s execution. For this, we can use the heap. - -In Rust, you can allocate memory on the heap with the [`Box<T>` type][box]. -Here’s an example: - -```rust -fn main() { - let x = Box::new(5); - let y = 42; -} -``` - -[box]: ../std/boxed/index.html - -Here’s what happens in memory when `main()` is called: - -| Address | Name | Value | -|---------|------|--------| -| 1 | y | 42 | -| 0 | x | ?????? | - -We allocate space for two variables on the stack. `y` is `42`, as it always has -been, but what about `x`? Well, `x` is a `Box<i32>`, and boxes allocate memory -on the heap. The actual value of the box is a structure which has a pointer to -‘the heap’. When we start executing the function, and `Box::new()` is called, -it allocates some memory for the heap, and puts `5` there. The memory now looks -like this: - -| Address | Name | Value | -|----------------------|------|------------------------| -| (2<sup>30</sup>) - 1 | | 5 | -| ... | ... | ... | -| 1 | y | 42 | -| 0 | x | → (2<sup>30</sup>) - 1 | - -We have (2<sup>30</sup>) - 1 addresses in our hypothetical computer with 1GB of RAM. And since -our stack grows from zero, the easiest place to allocate memory is from the -other end. So our first value is at the highest place in memory. And the value -of the struct at `x` has a [raw pointer][rawpointer] to the place we’ve -allocated on the heap, so the value of `x` is (2<sup>30</sup>) - 1, the memory -location we’ve asked for. - -[rawpointer]: raw-pointers.html - -We haven’t really talked too much about what it actually means to allocate and -deallocate memory in these contexts. Getting into very deep detail is out of -the scope of this tutorial, but what’s important to point out here is that -the heap isn’t a stack that grows from the opposite end. We’ll have an -example of this later in the book, but because the heap can be allocated and -freed in any order, it can end up with ‘holes’. Here’s a diagram of the memory -layout of a program which has been running for a while now: - - -| Address | Name | Value | -|----------------------|------|------------------------| -| (2<sup>30</sup>) - 1 | | 5 | -| (2<sup>30</sup>) - 2 | | | -| (2<sup>30</sup>) - 3 | | | -| (2<sup>30</sup>) - 4 | | 42 | -| ... | ... | ... | -| 2 | z | → (2<sup>30</sup>) - 4 | -| 1 | y | 42 | -| 0 | x | → (2<sup>30</sup>) - 1 | - -In this case, we’ve allocated four things on the heap, but deallocated two of -them. There’s a gap between (2<sup>30</sup>) - 1 and (2<sup>30</sup>) - 4 which isn’t -currently being used. The specific details of how and why this happens depends -on what kind of strategy you use to manage the heap. Different programs can use -different ‘memory allocators’, which are libraries that manage this for you. -Rust programs use [jemalloc][jemalloc] for this purpose. - -[jemalloc]: http://www.canonware.com/jemalloc/ - -Anyway, back to our example. Since this memory is on the heap, it can stay -alive longer than the function which allocates the box. In this case, however, -it doesn’t.[^moving] When the function is over, we need to free the stack frame -for `main()`. `Box<T>`, though, has a trick up its sleeve: [Drop][drop]. The -implementation of `Drop` for `Box` deallocates the memory that was allocated -when it was created. Great! So when `x` goes away, it first frees the memory -allocated on the heap: - -| Address | Name | Value | -|---------|------|--------| -| 1 | y | 42 | -| 0 | x | ?????? | - -[drop]: drop.html -[^moving]: We can make the memory live longer by transferring ownership, - sometimes called ‘moving out of the box’. More complex examples will - be covered later. - - -And then the stack frame goes away, freeing all of our memory. - -# Arguments and borrowing - -We’ve got some basic examples with the stack and the heap going, but what about -function arguments and borrowing? Here’s a small Rust program: - -```rust -fn foo(i: &i32) { - let z = 42; -} - -fn main() { - let x = 5; - let y = &x; - - foo(y); -} -``` - -When we enter `main()`, memory looks like this: - -| Address | Name | Value | -|---------|------|--------| -| 1 | y | → 0 | -| 0 | x | 5 | - -`x` is a plain old `5`, and `y` is a reference to `x`. So its value is the -memory location that `x` lives at, which in this case is `0`. - -What about when we call `foo()`, passing `y` as an argument? - -| Address | Name | Value | -|---------|------|--------| -| 3 | z | 42 | -| 2 | i | → 0 | -| 1 | y | → 0 | -| 0 | x | 5 | - -Stack frames aren’t only for local bindings, they’re for arguments too. So in -this case, we need to have both `i`, our argument, and `z`, our local variable -binding. `i` is a copy of the argument, `y`. Since `y`’s value is `0`, so is -`i`’s. - -This is one reason why borrowing a variable doesn’t deallocate any memory: the -value of a reference is a pointer to a memory location. If we got rid of -the underlying memory, things wouldn’t work very well. - -# A complex example - -Okay, let’s go through this complex program step-by-step: - -```rust -fn foo(x: &i32) { - let y = 10; - let z = &y; - - baz(z); - bar(x, z); -} - -fn bar(a: &i32, b: &i32) { - let c = 5; - let d = Box::new(5); - let e = &d; - - baz(e); -} - -fn baz(f: &i32) { - let g = 100; -} - -fn main() { - let h = 3; - let i = Box::new(20); - let j = &h; - - foo(j); -} -``` - -First, we call `main()`: - -| Address | Name | Value | -|----------------------|------|------------------------| -| (2<sup>30</sup>) - 1 | | 20 | -| ... | ... | ... | -| 2 | j | → 0 | -| 1 | i | → (2<sup>30</sup>) - 1 | -| 0 | h | 3 | - -We allocate memory for `j`, `i`, and `h`. `i` is on the heap, and so has a -value pointing there. - -Next, at the end of `main()`, `foo()` gets called: - -| Address | Name | Value | -|----------------------|------|------------------------| -| (2<sup>30</sup>) - 1 | | 20 | -| ... | ... | ... | -| 5 | z | → 4 | -| 4 | y | 10 | -| 3 | x | → 0 | -| 2 | j | → 0 | -| 1 | i | → (2<sup>30</sup>) - 1 | -| 0 | h | 3 | - -Space gets allocated for `x`, `y`, and `z`. The argument `x` has the same value -as `j`, since that’s what we passed it in. It’s a pointer to the `0` address, -since `j` points at `h`. - -Next, `foo()` calls `baz()`, passing `z`: - -| Address | Name | Value | -|----------------------|------|------------------------| -| (2<sup>30</sup>) - 1 | | 20 | -| ... | ... | ... | -| 7 | g | 100 | -| 6 | f | → 4 | -| 5 | z | → 4 | -| 4 | y | 10 | -| 3 | x | → 0 | -| 2 | j | → 0 | -| 1 | i | → (2<sup>30</sup>) - 1 | -| 0 | h | 3 | - -We’ve allocated memory for `f` and `g`. `baz()` is very short, so when it’s -over, we get rid of its stack frame: - -| Address | Name | Value | -|----------------------|------|------------------------| -| (2<sup>30</sup>) - 1 | | 20 | -| ... | ... | ... | -| 5 | z | → 4 | -| 4 | y | 10 | -| 3 | x | → 0 | -| 2 | j | → 0 | -| 1 | i | → (2<sup>30</sup>) - 1 | -| 0 | h | 3 | - -Next, `foo()` calls `bar()` with `x` and `z`: - -| Address | Name | Value | -|----------------------|------|------------------------| -| (2<sup>30</sup>) - 1 | | 20 | -| (2<sup>30</sup>) - 2 | | 5 | -| ... | ... | ... | -| 10 | e | → 9 | -| 9 | d | → (2<sup>30</sup>) - 2 | -| 8 | c | 5 | -| 7 | b | → 4 | -| 6 | a | → 0 | -| 5 | z | → 4 | -| 4 | y | 10 | -| 3 | x | → 0 | -| 2 | j | → 0 | -| 1 | i | → (2<sup>30</sup>) - 1 | -| 0 | h | 3 | - -We end up allocating another value on the heap, and so we have to subtract one -from (2<sup>30</sup>) - 1. It’s easier to write that than `1,073,741,822`. In any -case, we set up the variables as usual. - -At the end of `bar()`, it calls `baz()`: - -| Address | Name | Value | -|----------------------|------|------------------------| -| (2<sup>30</sup>) - 1 | | 20 | -| (2<sup>30</sup>) - 2 | | 5 | -| ... | ... | ... | -| 12 | g | 100 | -| 11 | f | → (2<sup>30</sup>) - 2 | -| 10 | e | → 9 | -| 9 | d | → (2<sup>30</sup>) - 2 | -| 8 | c | 5 | -| 7 | b | → 4 | -| 6 | a | → 0 | -| 5 | z | → 4 | -| 4 | y | 10 | -| 3 | x | → 0 | -| 2 | j | → 0 | -| 1 | i | → (2<sup>30</sup>) - 1 | -| 0 | h | 3 | - -With this, we’re at our deepest point! Whew! Congrats for following along this -far. - -After `baz()` is over, we get rid of `f` and `g`: - -| Address | Name | Value | -|----------------------|------|------------------------| -| (2<sup>30</sup>) - 1 | | 20 | -| (2<sup>30</sup>) - 2 | | 5 | -| ... | ... | ... | -| 10 | e | → 9 | -| 9 | d | → (2<sup>30</sup>) - 2 | -| 8 | c | 5 | -| 7 | b | → 4 | -| 6 | a | → 0 | -| 5 | z | → 4 | -| 4 | y | 10 | -| 3 | x | → 0 | -| 2 | j | → 0 | -| 1 | i | → (2<sup>30</sup>) - 1 | -| 0 | h | 3 | - -Next, we return from `bar()`. `d` in this case is a `Box<T>`, so it also frees -what it points to: (2<sup>30</sup>) - 2. - -| Address | Name | Value | -|----------------------|------|------------------------| -| (2<sup>30</sup>) - 1 | | 20 | -| ... | ... | ... | -| 5 | z | → 4 | -| 4 | y | 10 | -| 3 | x | → 0 | -| 2 | j | → 0 | -| 1 | i | → (2<sup>30</sup>) - 1 | -| 0 | h | 3 | - -And after that, `foo()` returns: - -| Address | Name | Value | -|----------------------|------|------------------------| -| (2<sup>30</sup>) - 1 | | 20 | -| ... | ... | ... | -| 2 | j | → 0 | -| 1 | i | → (2<sup>30</sup>) - 1 | -| 0 | h | 3 | - -And then, finally, `main()`, which cleans the rest up. When `i` is `Drop`ped, -it will clean up the last of the heap too. - -# What do other languages do? - -Most languages with a garbage collector heap-allocate by default. This means -that every value is boxed. There are a number of reasons why this is done, but -they’re out of scope for this tutorial. There are some possible optimizations -that don’t make it true 100% of the time, too. Rather than relying on the stack -and `Drop` to clean up memory, the garbage collector deals with the heap -instead. - -# Which to use? - -So if the stack is faster and easier to manage, why do we need the heap? A big -reason is that Stack-allocation alone means you only have 'Last In First Out (LIFO)' semantics for -reclaiming storage. Heap-allocation is strictly more general, allowing storage -to be taken from and returned to the pool in arbitrary order, but at a -complexity cost. - -Generally, you should prefer stack allocation, and so, Rust stack-allocates by -default. The LIFO model of the stack is simpler, at a fundamental level. This -has two big impacts: runtime efficiency and semantic impact. - -## Runtime Efficiency - -Managing the memory for the stack is trivial: The machine -increments or decrements a single value, the so-called “stack pointer”. -Managing memory for the heap is non-trivial: heap-allocated memory is freed at -arbitrary points, and each block of heap-allocated memory can be of arbitrary -size, so the memory manager must generally work much harder to -identify memory for reuse. - -If you’d like to dive into this topic in greater detail, [this paper][wilson] -is a great introduction. - -[wilson]: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.143.4688 - -## Semantic impact - -Stack-allocation impacts the Rust language itself, and thus the developer’s -mental model. The LIFO semantics is what drives how the Rust language handles -automatic memory management. Even the deallocation of a uniquely-owned -heap-allocated box can be driven by the stack-based LIFO semantics, as -discussed throughout this chapter. The flexibility (i.e. expressiveness) of non -LIFO-semantics means that in general the compiler cannot automatically infer at -compile-time where memory should be freed; it has to rely on dynamic protocols, -potentially from outside the language itself, to drive deallocation (reference -counting, as used by `Rc<T>` and `Arc<T>`, is one example of this). - -When taken to the extreme, the increased expressive power of heap allocation -comes at the cost of either significant runtime support (e.g. in the form of a -garbage collector) or significant programmer effort (in the form of explicit -memory management calls that require verification not provided by the Rust -compiler). diff --git a/src/doc/book/src/trait-objects.md b/src/doc/book/src/trait-objects.md deleted file mode 100644 index a77d5fe93b524..0000000000000 --- a/src/doc/book/src/trait-objects.md +++ /dev/null @@ -1,335 +0,0 @@ -# Trait Objects - -When code involves polymorphism, there needs to be a mechanism to determine -which specific version is actually run. This is called ‘dispatch’. There are -two major forms of dispatch: static dispatch and dynamic dispatch. While Rust -favors static dispatch, it also supports dynamic dispatch through a mechanism -called ‘trait objects’. - -## Background - -For the rest of this chapter, we’ll need a trait and some implementations. -Let’s make a simple one, `Foo`. It has one method that is expected to return a -`String`. - -```rust -trait Foo { - fn method(&self) -> String; -} -``` - -We’ll also implement this trait for `u8` and `String`: - -```rust -# trait Foo { fn method(&self) -> String; } -impl Foo for u8 { - fn method(&self) -> String { format!("u8: {}", *self) } -} - -impl Foo for String { - fn method(&self) -> String { format!("string: {}", *self) } -} -``` - - -## Static dispatch - -We can use this trait to perform static dispatch with trait bounds: - -```rust -# trait Foo { fn method(&self) -> String; } -# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } } -# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } } -fn do_something<T: Foo>(x: T) { - x.method(); -} - -fn main() { - let x = 5u8; - let y = "Hello".to_string(); - - do_something(x); - do_something(y); -} -``` - -Rust uses ‘monomorphization’ to perform static dispatch here. This means that -Rust will create a special version of `do_something()` for both `u8` and -`String`, and then replace the call sites with calls to these specialized -functions. In other words, Rust generates something like this: - -```rust -# trait Foo { fn method(&self) -> String; } -# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } } -# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } } -fn do_something_u8(x: u8) { - x.method(); -} - -fn do_something_string(x: String) { - x.method(); -} - -fn main() { - let x = 5u8; - let y = "Hello".to_string(); - - do_something_u8(x); - do_something_string(y); -} -``` - -This has a great upside: static dispatch allows function calls to be -inlined because the callee is known at compile time, and inlining is -the key to good optimization. Static dispatch is fast, but it comes at -a tradeoff: ‘code bloat’, due to many copies of the same function -existing in the binary, one for each type. - -Furthermore, compilers aren’t perfect and may “optimize” code to become slower. -For example, functions inlined too eagerly will bloat the instruction cache -(cache rules everything around us). This is part of the reason that `#[inline]` -and `#[inline(always)]` should be used carefully, and one reason why using a -dynamic dispatch is sometimes more efficient. - -However, the common case is that it is more efficient to use static dispatch, -and one can always have a thin statically-dispatched wrapper function that does -a dynamic dispatch, but not vice versa, meaning static calls are more flexible. -The standard library tries to be statically dispatched where possible for this -reason. - -## Dynamic dispatch - -Rust provides dynamic dispatch through a feature called ‘trait objects’. Trait -objects, like `&Foo` or `Box<Foo>`, are normal values that store a value of -*any* type that implements the given trait, where the precise type can only be -known at runtime. - -A trait object can be obtained from a pointer to a concrete type that -implements the trait by *casting* it (e.g. `&x as &Foo`) or *coercing* it -(e.g. using `&x` as an argument to a function that takes `&Foo`). - -These trait object coercions and casts also work for pointers like `&mut T` to -`&mut Foo` and `Box<T>` to `Box<Foo>`, but that’s all at the moment. Coercions -and casts are identical. - -This operation can be seen as ‘erasing’ the compiler’s knowledge about the -specific type of the pointer, and hence trait objects are sometimes referred to -as ‘type erasure’. - -Coming back to the example above, we can use the same trait to perform dynamic -dispatch with trait objects by casting: - -```rust -# trait Foo { fn method(&self) -> String; } -# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } } -# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } } -fn do_something(x: &Foo) { - x.method(); -} - -fn main() { - let x = 5u8; - do_something(&x as &Foo); -} -``` - -or by coercing: - -```rust -# trait Foo { fn method(&self) -> String; } -# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } } -# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } } -fn do_something(x: &Foo) { - x.method(); -} - -fn main() { - let x = "Hello".to_string(); - do_something(&x); -} -``` - -A function that takes a trait object is not specialized to each of the types -that implements `Foo`: only one copy is generated, often (but not always) -resulting in less code bloat. However, this comes at the cost of requiring -slower virtual function calls, and effectively inhibiting any chance of -inlining and related optimizations from occurring. - -### Why pointers? - -Rust does not put things behind a pointer by default, unlike many managed -languages, so types can have different sizes. Knowing the size of the value at -compile time is important for things like passing it as an argument to a -function, moving it about on the stack and allocating (and deallocating) space -on the heap to store it. - -For `Foo`, we would need to have a value that could be at least either a -`String` (24 bytes) or a `u8` (1 byte), as well as any other type for which -dependent crates may implement `Foo` (any number of bytes at all). There’s no -way to guarantee that this last point can work if the values are stored without -a pointer, because those other types can be arbitrarily large. - -Putting the value behind a pointer means the size of the value is not relevant -when we are tossing a trait object around, only the size of the pointer itself. - -### Representation - -The methods of the trait can be called on a trait object via a special record -of function pointers traditionally called a ‘vtable’ (created and managed by -the compiler). - -Trait objects are both simple and complicated: their core representation and -layout is quite straight-forward, but there are some curly error messages and -surprising behaviors to discover. - -Let’s start simple, with the runtime representation of a trait object. The -`std::raw` module contains structs with layouts that are the same as the -complicated built-in types, [including trait objects][stdraw]: - -```rust -# mod foo { -pub struct TraitObject { - pub data: *mut (), - pub vtable: *mut (), -} -# } -``` - -[stdraw]: ../std/raw/struct.TraitObject.html - -That is, a trait object like `&Foo` consists of a ‘data’ pointer and a ‘vtable’ -pointer. - -The data pointer addresses the data (of some unknown type `T`) that the trait -object is storing, and the vtable pointer points to the vtable (‘virtual method -table’) corresponding to the implementation of `Foo` for `T`. - - -A vtable is essentially a struct of function pointers, pointing to the concrete -piece of machine code for each method in the implementation. A method call like -`trait_object.method()` will retrieve the correct pointer out of the vtable and -then do a dynamic call of it. For example: - -```rust,ignore -struct FooVtable { - destructor: fn(*mut ()), - size: usize, - align: usize, - method: fn(*const ()) -> String, -} - -// u8: - -fn call_method_on_u8(x: *const ()) -> String { - // The compiler guarantees that this function is only called - // with `x` pointing to a u8. - let byte: &u8 = unsafe { &*(x as *const u8) }; - - byte.method() -} - -static Foo_for_u8_vtable: FooVtable = FooVtable { - destructor: /* compiler magic */, - size: 1, - align: 1, - - // Cast to a function pointer: - method: call_method_on_u8 as fn(*const ()) -> String, -}; - - -// String: - -fn call_method_on_String(x: *const ()) -> String { - // The compiler guarantees that this function is only called - // with `x` pointing to a String. - let string: &String = unsafe { &*(x as *const String) }; - - string.method() -} - -static Foo_for_String_vtable: FooVtable = FooVtable { - destructor: /* compiler magic */, - // Values for a 64-bit computer, halve them for 32-bit ones. - size: 24, - align: 8, - - method: call_method_on_String as fn(*const ()) -> String, -}; -``` - -The `destructor` field in each vtable points to a function that will clean up -any resources of the vtable’s type: for `u8` it is trivial, but for `String` it -will free the memory. This is necessary for owning trait objects like -`Box<Foo>`, which need to clean-up both the `Box` allocation as well as the -internal type when they go out of scope. The `size` and `align` fields store -the size of the erased type, and its alignment requirements. - -Suppose we’ve got some values that implement `Foo`. The explicit form of -construction and use of `Foo` trait objects might look a bit like (ignoring the -type mismatches: they’re all pointers anyway): - -```rust,ignore -let a: String = "foo".to_string(); -let x: u8 = 1; - -// let b: &Foo = &a; -let b = TraitObject { - // Store the data: - data: &a, - // Store the methods: - vtable: &Foo_for_String_vtable -}; - -// let y: &Foo = x; -let y = TraitObject { - // Store the data: - data: &x, - // Store the methods: - vtable: &Foo_for_u8_vtable -}; - -// b.method(); -(b.vtable.method)(b.data); - -// y.method(); -(y.vtable.method)(y.data); -``` - -## Object Safety - -Not every trait can be used to make a trait object. For example, vectors implement -`Clone`, but if we try to make a trait object: - -```rust,ignore -let v = vec![1, 2, 3]; -let o = &v as &Clone; -``` - -We get an error: - -```text -error: cannot convert to a trait object because trait `core::clone::Clone` is not object-safe [E0038] -let o = &v as &Clone; - ^~ -note: the trait cannot require that `Self : Sized` -let o = &v as &Clone; - ^~ -``` - -The error says that `Clone` is not ‘object-safe’. Only traits that are -object-safe can be made into trait objects. A trait is object-safe if both of -these are true: - -* the trait does not require that `Self: Sized` -* all of its methods are object-safe - -So what makes a method object-safe? Each method must require that `Self: Sized` -or all of the following: - -* must not have any type parameters -* must not use `Self` - -Whew! As we can see, almost all of these rules talk about `Self`. A good intuition -is “except in special circumstances, if your trait’s method uses `Self`, it is not -object-safe.” diff --git a/src/doc/book/src/traits.md b/src/doc/book/src/traits.md deleted file mode 100644 index 19a133f84b0b6..0000000000000 --- a/src/doc/book/src/traits.md +++ /dev/null @@ -1,551 +0,0 @@ -# Traits - -A trait is a language feature that tells the Rust compiler about -functionality a type must provide. - -Recall the `impl` keyword, used to call a function with [method -syntax][methodsyntax]: - -```rust -struct Circle { - x: f64, - y: f64, - radius: f64, -} - -impl Circle { - fn area(&self) -> f64 { - std::f64::consts::PI * (self.radius * self.radius) - } -} -``` - -[methodsyntax]: method-syntax.html - -Traits are similar, except that we first define a trait with a method -signature, then implement the trait for a type. In this example, we implement the trait `HasArea` for `Circle`: - -```rust -struct Circle { - x: f64, - y: f64, - radius: f64, -} - -trait HasArea { - fn area(&self) -> f64; -} - -impl HasArea for Circle { - fn area(&self) -> f64 { - std::f64::consts::PI * (self.radius * self.radius) - } -} -``` - -As you can see, the `trait` block looks very similar to the `impl` block, -but we don’t define a body, only a type signature. When we `impl` a trait, -we use `impl Trait for Item`, rather than only `impl Item`. - -`Self` may be used in a type annotation to refer to an instance of the type -implementing this trait passed as a parameter. `Self`, `&Self` or `&mut Self` -may be used depending on the level of ownership required. - -```rust -struct Circle { - x: f64, - y: f64, - radius: f64, -} - -trait HasArea { - fn area(&self) -> f64; - - fn is_larger(&self, &Self) -> bool; -} - -impl HasArea for Circle { - fn area(&self) -> f64 { - std::f64::consts::PI * (self.radius * self.radius) - } - - fn is_larger(&self, other: &Self) -> bool { - self.area() > other.area() - } -} -``` - -## Trait bounds on generic functions - -Traits are useful because they allow a type to make certain promises about its -behavior. Generic functions can exploit this to constrain, or [bound][bounds], the types they -accept. Consider this function, which does not compile: - -[bounds]: glossary.html#bounds - -```rust,ignore -fn print_area<T>(shape: T) { - println!("This shape has an area of {}", shape.area()); -} -``` - -Rust complains: - -```text -error: no method named `area` found for type `T` in the current scope -``` - -Because `T` can be any type, we can’t be sure that it implements the `area` -method. But we can add a trait bound to our generic `T`, ensuring -that it does: - -```rust -# trait HasArea { -# fn area(&self) -> f64; -# } -fn print_area<T: HasArea>(shape: T) { - println!("This shape has an area of {}", shape.area()); -} -``` - -The syntax `<T: HasArea>` means “any type that implements the `HasArea` trait.” -Because traits define function type signatures, we can be sure that any type -which implements `HasArea` will have an `.area()` method. - -Here’s an extended example of how this works: - -```rust -trait HasArea { - fn area(&self) -> f64; -} - -struct Circle { - x: f64, - y: f64, - radius: f64, -} - -impl HasArea for Circle { - fn area(&self) -> f64 { - std::f64::consts::PI * (self.radius * self.radius) - } -} - -struct Square { - x: f64, - y: f64, - side: f64, -} - -impl HasArea for Square { - fn area(&self) -> f64 { - self.side * self.side - } -} - -fn print_area<T: HasArea>(shape: T) { - println!("This shape has an area of {}", shape.area()); -} - -fn main() { - let c = Circle { - x: 0.0f64, - y: 0.0f64, - radius: 1.0f64, - }; - - let s = Square { - x: 0.0f64, - y: 0.0f64, - side: 1.0f64, - }; - - print_area(c); - print_area(s); -} -``` - -This program outputs: - -```text -This shape has an area of 3.141593 -This shape has an area of 1 -``` - -As you can see, `print_area` is now generic, but also ensures that we have -passed in the correct types. If we pass in an incorrect type: - -```rust,ignore -print_area(5); -``` - -We get a compile-time error: - -```text -error: the trait bound `_ : HasArea` is not satisfied [E0277] -``` - -## Trait bounds on generic structs - -Your generic structs can also benefit from trait bounds. All you need to -do is append the bound when you declare type parameters. Here is a new -type `Rectangle<T>` and its operation `is_square()`: - -```rust -struct Rectangle<T> { - x: T, - y: T, - width: T, - height: T, -} - -impl<T: PartialEq> Rectangle<T> { - fn is_square(&self) -> bool { - self.width == self.height - } -} - -fn main() { - let mut r = Rectangle { - x: 0, - y: 0, - width: 47, - height: 47, - }; - - assert!(r.is_square()); - - r.height = 42; - assert!(!r.is_square()); -} -``` - -`is_square()` needs to check that the sides are equal, so the sides must be of -a type that implements the [`core::cmp::PartialEq`][PartialEq] trait: - -```rust,ignore -impl<T: PartialEq> Rectangle<T> { ... } -``` - -Now, a rectangle can be defined in terms of any type that can be compared for -equality. - -[PartialEq]: ../core/cmp/trait.PartialEq.html - -Here we defined a new struct `Rectangle` that accepts numbers of any -precision—really, objects of pretty much any type—as long as they can be -compared for equality. Could we do the same for our `HasArea` structs, `Square` -and `Circle`? Yes, but they need multiplication, and to work with that we need -to know more about [operator traits][operators-and-overloading]. - -[operators-and-overloading]: operators-and-overloading.html - -# Rules for implementing traits - -So far, we’ve only added trait implementations to structs, but you can -implement a trait for any type such as `f32`: - -```rust -trait ApproxEqual { - fn approx_equal(&self, other: &Self) -> bool; -} -impl ApproxEqual for f32 { - fn approx_equal(&self, other: &Self) -> bool { - // Appropriate for `self` and `other` being close to 1.0. - (self - other).abs() <= ::std::f32::EPSILON - } -} - -println!("{}", 1.0.approx_equal(&1.00000001)); -``` - -This may seem like the Wild West, but there are two restrictions around -implementing traits that prevent this from getting out of hand. The first is -that if the trait isn’t defined in your scope, it doesn’t apply. Here’s an -example: the standard library provides a [`Write`][write] trait which adds -extra functionality to `File`s, for doing file I/O. By default, a `File` -won’t have its methods: - -[write]: ../std/io/trait.Write.html - -```rust,ignore -let mut f = std::fs::File::create("foo.txt").expect("Couldn’t create foo.txt"); -let buf = b"whatever"; // buf: &[u8; 8], a byte string literal. -let result = f.write(buf); -# result.unwrap(); // Ignore the error. -``` - -Here’s the error: - -```text -error: type `std::fs::File` does not implement any method in scope named `write` -let result = f.write(buf); - ^~~~~~~~~~ -``` - -We need to `use` the `Write` trait first: - -```rust,no_run -use std::io::Write; - -let mut f = std::fs::File::create("foo.txt").expect("Couldn’t create foo.txt"); -let buf = b"whatever"; -let result = f.write(buf); -# result.unwrap(); // Ignore the error. -``` - -This will compile without error. - -This means that even if someone does something bad like add methods to `i32`, -it won’t affect you, unless you `use` that trait. - -There’s one more restriction on implementing traits: either the trait -or the type you’re implementing it for must be defined by you. Or more -precisely, one of them must be defined in the same crate as the `impl` -you're writing. For more on Rust's module and package system, see the -chapter on [crates and modules][cm]. - -So, we could implement the `HasArea` type for `i32`, because we defined -`HasArea` in our code. But if we tried to implement `ToString`, a trait -provided by Rust, for `i32`, we could not, because neither the trait nor -the type are defined in our crate. - -One last thing about traits: generic functions with a trait bound use -‘monomorphization’ (mono: one, morph: form), so they are statically dispatched. -What’s that mean? Check out the chapter on [trait objects][to] for more details. - -[cm]: crates-and-modules.html -[to]: trait-objects.html - -# Multiple trait bounds - -You’ve seen that you can bound a generic type parameter with a trait: - -```rust -fn foo<T: Clone>(x: T) { - x.clone(); -} -``` - -If you need more than one bound, you can use `+`: - -```rust -use std::fmt::Debug; - -fn foo<T: Clone + Debug>(x: T) { - x.clone(); - println!("{:?}", x); -} -``` - -`T` now needs to be both `Clone` as well as `Debug`. - -# Where clause - -Writing functions with only a few generic types and a small number of trait -bounds isn’t too bad, but as the number increases, the syntax gets increasingly -awkward: - -```rust -use std::fmt::Debug; - -fn foo<T: Clone, K: Clone + Debug>(x: T, y: K) { - x.clone(); - y.clone(); - println!("{:?}", y); -} -``` - -The name of the function is on the far left, and the parameter list is on the -far right. The bounds are getting in the way. - -Rust has a solution, and it’s called a ‘`where` clause’: - -```rust -use std::fmt::Debug; - -fn foo<T: Clone, K: Clone + Debug>(x: T, y: K) { - x.clone(); - y.clone(); - println!("{:?}", y); -} - -fn bar<T, K>(x: T, y: K) where T: Clone, K: Clone + Debug { - x.clone(); - y.clone(); - println!("{:?}", y); -} - -fn main() { - foo("Hello", "world"); - bar("Hello", "world"); -} -``` - -`foo()` uses the syntax we showed earlier, and `bar()` uses a `where` clause. -All you need to do is leave off the bounds when defining your type parameters, -and then add `where` after the parameter list. For longer lists, whitespace can -be added: - -```rust -use std::fmt::Debug; - -fn bar<T, K>(x: T, y: K) - where T: Clone, - K: Clone + Debug { - - x.clone(); - y.clone(); - println!("{:?}", y); -} -``` - -This flexibility can add clarity in complex situations. - -`where` is also more powerful than the simpler syntax. For example: - -```rust -trait ConvertTo<Output> { - fn convert(&self) -> Output; -} - -impl ConvertTo<i64> for i32 { - fn convert(&self) -> i64 { *self as i64 } -} - -// Can be called with T == i32. -fn normal<T: ConvertTo<i64>>(x: &T) -> i64 { - x.convert() -} - -// Can be called with T == i64. -fn inverse<T>(x: i32) -> T - // This is using ConvertTo as if it were "ConvertTo<i64>". - where i32: ConvertTo<T> { - x.convert() -} -``` - -This shows off the additional feature of `where` clauses: they allow bounds -on the left-hand side not only of type parameters `T`, but also of types (`i32` in this case). In this example, `i32` must implement -`ConvertTo<T>`. Rather than defining what `i32` is (since that's obvious), the -`where` clause here constrains `T`. - -# Default methods - -A default method can be added to a trait definition if it is already known how a typical implementor will define a method. For example, `is_invalid()` is defined as the opposite of `is_valid()`: - -```rust -trait Foo { - fn is_valid(&self) -> bool; - - fn is_invalid(&self) -> bool { !self.is_valid() } -} -``` - -Implementors of the `Foo` trait need to implement `is_valid()` but not `is_invalid()` due to the added default behavior. This default behavior can still be overridden as in: - -```rust -# trait Foo { -# fn is_valid(&self) -> bool; -# -# fn is_invalid(&self) -> bool { !self.is_valid() } -# } -struct UseDefault; - -impl Foo for UseDefault { - fn is_valid(&self) -> bool { - println!("Called UseDefault.is_valid."); - true - } -} - -struct OverrideDefault; - -impl Foo for OverrideDefault { - fn is_valid(&self) -> bool { - println!("Called OverrideDefault.is_valid."); - true - } - - fn is_invalid(&self) -> bool { - println!("Called OverrideDefault.is_invalid!"); - true // Overrides the expected value of `is_invalid()`. - } -} - -let default = UseDefault; -assert!(!default.is_invalid()); // Prints "Called UseDefault.is_valid." - -let over = OverrideDefault; -assert!(over.is_invalid()); // Prints "Called OverrideDefault.is_invalid!" -``` - -# Inheritance - -Sometimes, implementing a trait requires implementing another trait: - -```rust -trait Foo { - fn foo(&self); -} - -trait FooBar : Foo { - fn foobar(&self); -} -``` - -Implementors of `FooBar` must also implement `Foo`, like this: - -```rust -# trait Foo { -# fn foo(&self); -# } -# trait FooBar : Foo { -# fn foobar(&self); -# } -struct Baz; - -impl Foo for Baz { - fn foo(&self) { println!("foo"); } -} - -impl FooBar for Baz { - fn foobar(&self) { println!("foobar"); } -} -``` - -If we forget to implement `Foo`, Rust will tell us: - -```text -error: the trait bound `main::Baz : main::Foo` is not satisfied [E0277] -``` - -# Deriving - -Implementing traits like `Debug` and `Default` repeatedly can become -quite tedious. For that reason, Rust provides an [attribute][attributes] that -allows you to let Rust automatically implement traits for you: - -```rust -#[derive(Debug)] -struct Foo; - -fn main() { - println!("{:?}", Foo); -} -``` - -[attributes]: attributes.html - -However, deriving is limited to a certain set of traits: - -- [`Clone`](../core/clone/trait.Clone.html) -- [`Copy`](../core/marker/trait.Copy.html) -- [`Debug`](../core/fmt/trait.Debug.html) -- [`Default`](../core/default/trait.Default.html) -- [`Eq`](../core/cmp/trait.Eq.html) -- [`Hash`](../core/hash/trait.Hash.html) -- [`Ord`](../core/cmp/trait.Ord.html) -- [`PartialEq`](../core/cmp/trait.PartialEq.html) -- [`PartialOrd`](../core/cmp/trait.PartialOrd.html) diff --git a/src/doc/book/src/type-aliases.md b/src/doc/book/src/type-aliases.md deleted file mode 100644 index 1bd0f78e36853..0000000000000 --- a/src/doc/book/src/type-aliases.md +++ /dev/null @@ -1,78 +0,0 @@ -# Type Aliases - -The `type` keyword lets you declare an alias of another type: - -```rust -type Name = String; -``` - -You can then use this type as if it were a real type: - -```rust -type Name = String; - -let x: Name = "Hello".to_string(); -``` - -Note, however, that this is an _alias_, not a new type entirely. In other -words, because Rust is strongly typed, you’d expect a comparison between two -different types to fail: - -```rust,ignore -let x: i32 = 5; -let y: i64 = 5; - -if x == y { - // ... -} -``` - -this gives - -```text -error: mismatched types: - expected `i32`, - found `i64` -(expected i32, - found i64) [E0308] - if x == y { - ^ -``` - -But, if we had an alias: - -```rust -type Num = i32; - -let x: i32 = 5; -let y: Num = 5; - -if x == y { - // ... -} -``` - -This compiles without error. Values of a `Num` type are the same as a value of -type `i32`, in every way. You can use [tuple struct] to really get a new type. - -[tuple struct]: structs.html#tuple-structs - -You can also use type aliases with generics: - -```rust -use std::result; - -enum ConcreteError { - Foo, - Bar, -} - -type Result<T> = result::Result<T, ConcreteError>; -``` - -This creates a specialized version of the `Result` type, which always has a -`ConcreteError` for the `E` part of `Result<T, E>`. This is commonly used -in the standard library to create custom errors for each subsection. For -example, [io::Result][ioresult]. - -[ioresult]: ../std/io/type.Result.html diff --git a/src/doc/book/src/ufcs.md b/src/doc/book/src/ufcs.md deleted file mode 100644 index 016ecc7097657..0000000000000 --- a/src/doc/book/src/ufcs.md +++ /dev/null @@ -1,136 +0,0 @@ -# Universal Function Call Syntax - -Sometimes, functions can have the same names. Consider this code: - -```rust -trait Foo { - fn f(&self); -} - -trait Bar { - fn f(&self); -} - -struct Baz; - -impl Foo for Baz { - fn f(&self) { println!("Baz’s impl of Foo"); } -} - -impl Bar for Baz { - fn f(&self) { println!("Baz’s impl of Bar"); } -} - -let b = Baz; -``` - -If we were to try to call `b.f()`, we’d get an error: - -```text -error: multiple applicable methods in scope [E0034] -b.f(); - ^~~ -note: candidate #1 is defined in an impl of the trait `main::Foo` for the type -`main::Baz` - fn f(&self) { println!("Baz’s impl of Foo"); } - ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -note: candidate #2 is defined in an impl of the trait `main::Bar` for the type -`main::Baz` - fn f(&self) { println!("Baz’s impl of Bar"); } - ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -``` - -We need a way to disambiguate which method we need. This feature is called -‘universal function call syntax’, and it looks like this: - -```rust -# trait Foo { -# fn f(&self); -# } -# trait Bar { -# fn f(&self); -# } -# struct Baz; -# impl Foo for Baz { -# fn f(&self) { println!("Baz’s impl of Foo"); } -# } -# impl Bar for Baz { -# fn f(&self) { println!("Baz’s impl of Bar"); } -# } -# let b = Baz; -Foo::f(&b); -Bar::f(&b); -``` - -Let’s break it down. - -```rust,ignore -Foo:: -Bar:: -``` - -These halves of the invocation are the types of the two traits: `Foo` and -`Bar`. This is what ends up actually doing the disambiguation between the two: -Rust calls the one from the trait name you use. - -```rust,ignore -f(&b) -``` - -When we call a method like `b.f()` using [method syntax][methodsyntax], Rust -will automatically borrow `b` if `f()` takes `&self`. In this case, Rust will -not, and so we need to pass an explicit `&b`. - -[methodsyntax]: method-syntax.html - -# Angle-bracket Form - -The form of UFCS we just talked about: - -```rust,ignore -Trait::method(args); -``` - -Is a short-hand. There’s an expanded form of this that’s needed in some -situations: - -```rust,ignore -<Type as Trait>::method(args); -``` - -The `<>::` syntax is a means of providing a type hint. The type goes inside -the `<>`s. In this case, the type is `Type as Trait`, indicating that we want -`Trait`’s version of `method` to be called here. The `as Trait` part is -optional if it’s not ambiguous. Same with the angle brackets, hence the -shorter form. - -Here’s an example of using the longer form. - -```rust -trait Foo { - fn foo() -> i32; -} - -struct Bar; - -impl Bar { - fn foo() -> i32 { - 20 - } -} - -impl Foo for Bar { - fn foo() -> i32 { - 10 - } -} - -fn main() { - assert_eq!(10, <Bar as Foo>::foo()); - assert_eq!(20, Bar::foo()); -} -``` - -Using the angle bracket syntax lets you call the trait method instead of the -inherent one. diff --git a/src/doc/book/src/unsafe.md b/src/doc/book/src/unsafe.md deleted file mode 100644 index 9bf59fe2abdc3..0000000000000 --- a/src/doc/book/src/unsafe.md +++ /dev/null @@ -1,142 +0,0 @@ -# Unsafe - -Rust’s main draw is its powerful static guarantees about behavior. But safety -checks are conservative by nature: there are some programs that are actually -safe, but the compiler is not able to verify this is true. To write these kinds -of programs, we need to tell the compiler to relax its restrictions a bit. For -this, Rust has a keyword, `unsafe`. Code using `unsafe` has fewer restrictions -than normal code does. - -Let’s go over the syntax, and then we’ll talk semantics. `unsafe` is used in -four contexts. The first one is to mark a function as unsafe: - -```rust -unsafe fn danger_will_robinson() { - // Scary stuff... -} -``` - -All functions called from [FFI][ffi] must be marked as `unsafe`, for example. -The second use of `unsafe` is an unsafe block: - -[ffi]: ffi.html - -```rust -unsafe { - // Scary stuff... -} -``` - -The third is for unsafe traits: - -```rust -unsafe trait Scary { } -``` - -And the fourth is for `impl`ementing one of those traits: - -```rust -# unsafe trait Scary { } -unsafe impl Scary for i32 {} -``` - -It’s important to be able to explicitly delineate code that may have bugs that -cause big problems. If a Rust program segfaults, you can be sure the cause is -related to something marked `unsafe`. - -# What does ‘safe’ mean? - -Safe, in the context of Rust, means ‘doesn’t do anything unsafe’. It’s also -important to know that there are certain behaviors that are probably not -desirable in your code, but are expressly _not_ unsafe: - -* Deadlocks -* Leaks of memory or other resources -* Exiting without calling destructors -* Integer overflow - -Rust cannot prevent all kinds of software problems. Buggy code can and will be -written in Rust. These things aren’t great, but they don’t qualify as `unsafe` -specifically. - -In addition, the following are all undefined behaviors in Rust, and must be -avoided, even when writing `unsafe` code: - -* Data races -* Dereferencing a NULL/dangling raw pointer -* Reads of [undef][undef] (uninitialized) memory -* Breaking the [pointer aliasing rules][aliasing] with raw pointers. -* `&mut T` and `&T` follow LLVM’s scoped [noalias][noalias] model, except if - the `&T` contains an `UnsafeCell<U>`. Unsafe code must not violate these - aliasing guarantees. -* Mutating an immutable value/reference without `UnsafeCell<U>` -* Invoking undefined behavior via compiler intrinsics: - * Indexing outside of the bounds of an object with `std::ptr::offset` - (`offset` intrinsic), with - the exception of one byte past the end which is permitted. - * Using `std::ptr::copy_nonoverlapping_memory` (`memcpy32`/`memcpy64` - intrinsics) on overlapping buffers -* Invalid values in primitive types, even in private fields/locals: - * NULL/dangling references or boxes - * A value other than `false` (0) or `true` (1) in a `bool` - * A discriminant in an `enum` not included in its type definition - * A value in a `char` which is a surrogate or above `char::MAX` - * Non-UTF-8 byte sequences in a `str` -* Unwinding into Rust from foreign code or unwinding from Rust into foreign - code. - -[noalias]: http://llvm.org/docs/LangRef.html#noalias -[undef]: http://llvm.org/docs/LangRef.html#undefined-values -[aliasing]: http://llvm.org/docs/LangRef.html#pointer-aliasing-rules - -# Unsafe Superpowers - -In both unsafe functions and unsafe blocks, Rust will let you do three things -that you normally can not do. Just three. Here they are: - -1. Access or update a [static mutable variable][static]. -2. Dereference a raw pointer. -3. Call unsafe functions. This is the most powerful ability. - -That’s it. It’s important that `unsafe` does not, for example, ‘turn off the -borrow checker’. Adding `unsafe` to some random Rust code doesn’t change its -semantics, it won’t start accepting anything. But it will let you write -things that _do_ break some of the rules. - -You will also encounter the `unsafe` keyword when writing bindings to foreign -(non-Rust) interfaces. You're encouraged to write a safe, native Rust interface -around the methods provided by the library. - -Let’s go over the basic three abilities listed, in order. - -## Access or update a `static mut` - -Rust has a feature called ‘`static mut`’ which allows for mutable global state. -Doing so can cause a data race, and as such is inherently not safe. For more -details, see the [static][static] section of the book. - -[static]: const-and-static.html#static - -## Dereference a raw pointer - -Raw pointers let you do arbitrary pointer arithmetic, and can cause a number of -different memory safety and security issues. In some senses, the ability to -dereference an arbitrary pointer is one of the most dangerous things you can -do. For more on raw pointers, see [their section of the book][rawpointers]. - -[rawpointers]: raw-pointers.html - -## Call unsafe functions - -This last ability works with both aspects of `unsafe`: you can only call -functions marked `unsafe` from inside an unsafe block. - -This ability is powerful and varied. Rust exposes some [compiler -intrinsics][intrinsics] as unsafe functions, and some unsafe functions bypass -safety checks, trading safety for speed. - -I’ll repeat again: even though you _can_ do arbitrary things in unsafe blocks -and functions doesn’t mean you should. The compiler will act as though you’re -upholding its invariants, so be careful! - -[intrinsics]: ../unstable-book/intrinsics.html diff --git a/src/doc/book/src/unsized-types.md b/src/doc/book/src/unsized-types.md deleted file mode 100644 index 2d090925d51f6..0000000000000 --- a/src/doc/book/src/unsized-types.md +++ /dev/null @@ -1,61 +0,0 @@ -# Unsized Types - -Most types have a particular size, in bytes, that is knowable at compile time. -For example, an `i32` is thirty-two bits big, or four bytes. However, there are -some types which are useful to express, but do not have a defined size. These are -called ‘unsized’ or ‘dynamically sized’ types. One example is `[T]`. This type -represents a certain number of `T` in sequence. But we don’t know how many -there are, so the size is not known. - -Rust understands a few of these types, but they have some restrictions. There -are three: - -1. We can only manipulate an instance of an unsized type via a pointer. An - `&[T]` works fine, but a `[T]` does not. -2. Variables and arguments cannot have dynamically sized types. -3. Only the last field in a `struct` may have a dynamically sized type; the - other fields must not. Enum variants must not have dynamically sized types as - data. - -So why bother? Well, because `[T]` can only be used behind a pointer, if we -didn’t have language support for unsized types, it would be impossible to write -this: - -```rust,ignore -impl Foo for str { -``` - -or - -```rust,ignore -impl<T> Foo for [T] { -``` - -Instead, you would have to write: - -```rust,ignore -impl Foo for &str { -``` - -Meaning, this implementation would only work for [references][ref], and not -other types of pointers. With the `impl for str`, all pointers, including (at -some point, there are some bugs to fix first) user-defined custom smart -pointers, can use this `impl`. - -[ref]: references-and-borrowing.html - -# ?Sized - -If you want to write a function that accepts a dynamically sized type, you -can use the special bound syntax, `?Sized`: - -```rust -struct Foo<T: ?Sized> { - f: T, -} -``` - -This `?Sized`, read as “T may or may not be `Sized`”, which allows us to match -both sized and unsized types. All generic type parameters implicitly -have the `Sized` bound, so the `?Sized` can be used to opt-out of the implicit -bound. diff --git a/src/doc/book/src/using-rust-without-the-standard-library.md b/src/doc/book/src/using-rust-without-the-standard-library.md deleted file mode 100644 index 709d10f4e4791..0000000000000 --- a/src/doc/book/src/using-rust-without-the-standard-library.md +++ /dev/null @@ -1,42 +0,0 @@ -# Using Rust Without the Standard Library - -Rust’s standard library provides a lot of useful functionality, but assumes -support for various features of its host system: threads, networking, heap -allocation, and others. There are systems that do not have these features, -however, and Rust can work with those too! To do so, we tell Rust that we -don’t want to use the standard library via an attribute: `#![no_std]`. - -> Note: This feature is technically stable, but there are some caveats. For -> one, you can build a `#![no_std]` _library_ on stable, but not a _binary_. -> For details on binaries without the standard library, see [the nightly -> chapter on 'lang items'](../unstable-book/lang-items.html#using-libc) - -To use `#![no_std]`, add it to your crate root: - -```rust,ignore -#![no_std] - -fn plus_one(x: i32) -> i32 { - x + 1 -} -``` - -Much of the functionality that’s exposed in the standard library is also -available via the [`core` crate](../core/index.html). When we’re using the -standard library, Rust automatically brings `std` into scope, allowing you to -use its features without an explicit import. By the same token, when using -`#![no_std]`, Rust will bring `core` into scope for you, as well as [its -prelude](../core/prelude/v1/index.html). This means that a lot of code will Just -Work: - -```rust,ignore -#![no_std] - -fn may_fail(failure: bool) -> Result<(), &'static str> { - if failure { - Err("this didn’t work!") - } else { - Ok(()) - } -} -``` diff --git a/src/doc/book/src/variable-bindings.md b/src/doc/book/src/variable-bindings.md deleted file mode 100644 index d6aa8b1acb72f..0000000000000 --- a/src/doc/book/src/variable-bindings.md +++ /dev/null @@ -1,256 +0,0 @@ -# Variable Bindings - -Virtually every non-'Hello World’ Rust program uses *variable bindings*. They -bind some value to a name, so it can be used later. `let` is -used to introduce a binding, like this: - -```rust -fn main() { - let x = 5; -} -``` - -Putting `fn main() {` in each example is a bit tedious, so we’ll leave that out -in the future. If you’re following along, make sure to edit your `main()` -function, rather than leaving it off. Otherwise, you’ll get an error. - -# Patterns - -In many languages, a variable binding would be called a *variable*, but Rust’s -variable bindings have a few tricks up their sleeves. For example the -left-hand side of a `let` statement is a ‘[pattern][pattern]’, not a -variable name. This means we can do things like: - -```rust -let (x, y) = (1, 2); -``` - -After this statement is evaluated, `x` will be one, and `y` will be two. -Patterns are really powerful, and have [their own section][pattern] in the -book. We don’t need those features for now, so we’ll keep this in the back -of our minds as we go forward. - -[pattern]: patterns.html - -# Type annotations - -Rust is a statically typed language, which means that we specify our types up -front, and they’re checked at compile time. So why does our first example -compile? Well, Rust has this thing called ‘type inference’. If it can figure -out what the type of something is, Rust doesn’t require you to explicitly type -it out. - -We can add the type if we want to, though. Types come after a colon (`:`): - -```rust -let x: i32 = 5; -``` - -If I asked you to read this out loud to the rest of the class, you’d say “`x` -is a binding with the type `i32` and the value `5`.” - -In this case we chose to represent `x` as a 32-bit signed integer. Rust has -many different primitive integer types. They begin with `i` for signed integers -and `u` for unsigned integers. The possible integer sizes are 8, 16, 32, and 64 -bits. - -In future examples, we may annotate the type in a comment. The examples will -look like this: - -```rust -fn main() { - let x = 5; // x: i32 -} -``` - -Note the similarities between this annotation and the syntax you use with -`let`. Including these kinds of comments is not idiomatic Rust, but we'll -occasionally include them to help you understand what the types that Rust -infers are. - -# Mutability - -By default, bindings are *immutable*. This code will not compile: - -```rust,ignore -let x = 5; -x = 10; -``` - -It will give you this error: - -```text -error: re-assignment of immutable variable `x` - x = 10; - ^~~~~~~ -``` - -If you want a binding to be mutable, you can use `mut`: - -```rust -let mut x = 5; // mut x: i32 -x = 10; -``` - -There is no single reason that bindings are immutable by default, but we can -think about it through one of Rust’s primary focuses: safety. If you forget to -say `mut`, the compiler will catch it, and let you know that you have mutated -something you may not have intended to mutate. If bindings were mutable by -default, the compiler would not be able to tell you this. If you _did_ intend -mutation, then the solution is quite easy: add `mut`. - -There are other good reasons to avoid mutable state when possible, but they’re -out of the scope of this guide. In general, you can often avoid explicit -mutation, and so it is preferable in Rust. That said, sometimes, mutation is -what you need, so it’s not forbidden. - -# Initializing bindings - -Rust variable bindings have one more aspect that differs from other languages: -bindings are required to be initialized with a value before you're allowed to -use them. - -Let’s try it out. Change your `src/main.rs` file to look like this: - -```rust -fn main() { - let x: i32; - - println!("Hello world!"); -} -``` - -You can use `cargo build` on the command line to build it. You’ll get a -warning, but it will still print "Hello, world!": - -```text - Compiling hello_world v0.0.1 (file:///home/you/projects/hello_world) -src/main.rs:2:9: 2:10 warning: unused variable: `x`, #[warn(unused_variables)] - on by default -src/main.rs:2 let x: i32; - ^ -``` - -Rust warns us that we never use the variable binding, but since we never use -it, no harm, no foul. Things change if we try to actually use this `x`, -however. Let’s do that. Change your program to look like this: - -```rust,ignore -fn main() { - let x: i32; - - println!("The value of x is: {}", x); -} -``` - -And try to build it. You’ll get an error: - -```bash -$ cargo build - Compiling hello_world v0.0.1 (file:///home/you/projects/hello_world) -src/main.rs:4:39: 4:40 error: use of possibly uninitialized variable: `x` -src/main.rs:4 println!("The value of x is: {}", x); - ^ -note: in expansion of format_args! -<std macros>:2:23: 2:77 note: expansion site -<std macros>:1:1: 3:2 note: in expansion of println! -src/main.rs:4:5: 4:42 note: expansion site -error: aborting due to previous error -Could not compile `hello_world`. -``` - -Rust will not let us use a value that has not been initialized. - -Let us take a minute to talk about this stuff we've added to `println!`. - -If you include two curly braces (`{}`, some call them moustaches...) in your -string to print, Rust will interpret this as a request to interpolate some sort -of value. *String interpolation* is a computer science term that means "stick -in the middle of a string." We add a comma, and then `x`, to indicate that we -want `x` to be the value we’re interpolating. The comma is used to separate -arguments we pass to functions and macros, if you’re passing more than one. - -When you use the curly braces, Rust will attempt to display the value in a -meaningful way by checking out its type. If you want to specify the format in a -more detailed manner, there are a [wide number of options available][format]. -For now, we'll stick to the default: integers aren't very complicated to -print. - -[format]: ../std/fmt/index.html - -# Scope and shadowing - -Let’s get back to bindings. Variable bindings have a scope - they are -constrained to live in the block they were defined in. A block is a collection -of statements enclosed by `{` and `}`. Function definitions are also blocks! -In the following example we define two variable bindings, `x` and `y`, which -live in different blocks. `x` can be accessed from inside the `fn main() {}` -block, while `y` can be accessed only from inside the inner block: - -```rust,ignore -fn main() { - let x: i32 = 17; - { - let y: i32 = 3; - println!("The value of x is {} and value of y is {}", x, y); - } - println!("The value of x is {} and value of y is {}", x, y); // This won't work. -} -``` - -The first `println!` would print "The value of x is 17 and the value of y is -3", but this example cannot be compiled successfully, because the second -`println!` cannot access the value of `y`, since it is not in scope anymore. -Instead we get this error: - -```bash -$ cargo build - Compiling hello v0.1.0 (file:///home/you/projects/hello_world) -main.rs:7:62: 7:63 error: unresolved name `y`. Did you mean `x`? [E0425] -main.rs:7 println!("The value of x is {} and value of y is {}", x, y); // This won't work. - ^ -note: in expansion of format_args! -<std macros>:2:25: 2:56 note: expansion site -<std macros>:1:1: 2:62 note: in expansion of print! -<std macros>:3:1: 3:54 note: expansion site -<std macros>:1:1: 3:58 note: in expansion of println! -main.rs:7:5: 7:65 note: expansion site -main.rs:7:62: 7:63 help: run `rustc --explain E0425` to see a detailed explanation -error: aborting due to previous error -Could not compile `hello`. - -To learn more, run the command again with --verbose. -``` - -Additionally, variable bindings can be shadowed. This means that a later -variable binding with the same name as another binding that is currently in -scope will override the previous binding. - -```rust -let x: i32 = 8; -{ - println!("{}", x); // Prints "8". - let x = 12; - println!("{}", x); // Prints "12". -} -println!("{}", x); // Prints "8". -let x = 42; -println!("{}", x); // Prints "42". -``` - -Shadowing and mutable bindings may appear as two sides of the same coin, but -they are two distinct concepts that can't always be used interchangeably. For -one, shadowing enables us to rebind a name to a value of a different type. It -is also possible to change the mutability of a binding. Note that shadowing a -name does not alter or destroy the value it was bound to, and the value will -continue to exist until it goes out of scope, even if it is no longer accessible -by any means. - -```rust -let mut x: i32 = 1; -x = 7; -let x = x; // `x` is now immutable and is bound to `7`. - -let y = 4; -let y = "I can also be bound to text!"; // `y` is now of a different type. -``` diff --git a/src/doc/book/src/vectors.md b/src/doc/book/src/vectors.md deleted file mode 100644 index aff078718dfb1..0000000000000 --- a/src/doc/book/src/vectors.md +++ /dev/null @@ -1,156 +0,0 @@ -# Vectors - -A ‘vector’ is a dynamic or ‘growable’ array, implemented as the standard -library type [`Vec<T>`][vec]. The `T` means that we can have vectors -of any type (see the chapter on [generics][generic] for more). -Vectors always allocate their data on the heap. -You can create them with the `vec!` macro: - -```rust -let v = vec![1, 2, 3, 4, 5]; // v: Vec<i32> -``` - -(Notice that unlike the `println!` macro we’ve used in the past, we use square -brackets `[]` with `vec!` macro. Rust allows you to use either in either -situation, this is just convention.) - -There’s an alternate form of `vec!` for repeating an initial value: - -```rust -let v = vec![0; 10]; // A vector of ten zeroes. -``` - -Vectors store their contents as contiguous arrays of `T` on the heap. This means -that they must be able to know the size of `T` at compile time (that is, how -many bytes are needed to store a `T`?). The size of some things can't be known -at compile time. For these you'll have to store a pointer to that thing: -thankfully, the [`Box`][box] type works perfectly for this. - -## Accessing elements - -To get the value at a particular index in the vector, we use `[]`s: - -```rust -let v = vec![1, 2, 3, 4, 5]; - -println!("The third element of v is {}", v[2]); -``` - -The indices count from `0`, so the third element is `v[2]`. - -It’s also important to note that you must index with the `usize` type: - -```rust,ignore -let v = vec![1, 2, 3, 4, 5]; - -let i: usize = 0; -let j: i32 = 0; - -// Works: -v[i]; - -// Doesn’t: -v[j]; -``` - -Indexing with a non-`usize` type gives an error that looks like this: - -```text -error: the trait bound `collections::vec::Vec<_> : core::ops::Index<i32>` -is not satisfied [E0277] -v[j]; -^~~~ -note: the type `collections::vec::Vec<_>` cannot be indexed by `i32` -error: aborting due to previous error -``` - -There’s a lot of punctuation in that message, but the core of it makes sense: -you cannot index with an `i32`. - -## Out-of-bounds Access - -If you try to access an index that doesn’t exist: - -```rust,ignore -let v = vec![1, 2, 3]; -println!("Item 7 is {}", v[7]); -``` - -then the current thread will [panic] with a message like this: - -```text -thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 7' -``` - -If you want to handle out-of-bounds errors without panicking, you can use -methods like [`get`][get] or [`get_mut`][get_mut] that return `None` when -given an invalid index: - -```rust -let v = vec![1, 2, 3]; -match v.get(7) { - Some(x) => println!("Item 7 is {}", x), - None => println!("Sorry, this vector is too short.") -} -``` - -## Iterating - -Once you have a vector, you can iterate through its elements with `for`. There -are three versions: - -```rust -let mut v = vec![1, 2, 3, 4, 5]; - -for i in &v { - println!("A reference to {}", i); -} - -for i in &mut v { - println!("A mutable reference to {}", i); -} - -for i in v { - println!("Take ownership of the vector and its element {}", i); -} -``` - -Note: You cannot use the vector again once you have iterated by taking ownership of the vector. -You can iterate the vector multiple times by taking a reference to the vector whilst iterating. -For example, the following code does not compile. - -```rust,ignore -let v = vec![1, 2, 3, 4, 5]; - -for i in v { - println!("Take ownership of the vector and its element {}", i); -} - -for i in v { - println!("Take ownership of the vector and its element {}", i); -} -``` - -Whereas the following works perfectly, - -```rust -let v = vec![1, 2, 3, 4, 5]; - -for i in &v { - println!("This is a reference to {}", i); -} - -for i in &v { - println!("This is a reference to {}", i); -} -``` - -Vectors have many more useful methods, which you can read about in [their -API documentation][vec]. - -[vec]: ../std/vec/index.html -[box]: ../std/boxed/index.html -[generic]: generics.html -[panic]: concurrency.html#panics -[get]: ../std/vec/struct.Vec.html#method.get -[get_mut]: ../std/vec/struct.Vec.html#method.get_mut diff --git a/src/doc/index.md b/src/doc/index.md index 1f262b360e3ed..1294c1a8c59e7 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -11,18 +11,18 @@ Other unofficial documentation may exist elsewhere; for example, the [Rust Learning] project collects documentation from the community, and [Docs.rs] builds documentation for individual Rust packages. -## API Documentation +# API Documentation Rust provides a standard library with a number of features; [we host its documentation here][api]. -## Extended Error Documentation +# Extended Error Documentation Many of Rust's errors come with error codes, and you can request extended diagnostics from the compiler on those errors. We also [have the text of those extended errors on the web][err], if you prefer to read them that way. -## The Rust Bookshelf +# The Rust Bookshelf Rust provides a number of book-length sets of documentation, collectively nicknamed 'The Rust Bookshelf.' diff --git a/src/doc/reference b/src/doc/reference index 2d23ea601f017..516549972d61c 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 2d23ea601f017c106a2303094ee1c57ba856d246 +Subproject commit 516549972d61c8946542d1a34afeae97167ff77b diff --git a/src/doc/unstable-book/src/SUMMARY.md b/src/doc/unstable-book/src/SUMMARY.md index 5fb323d6ce909..44eda204a3d29 100644 --- a/src/doc/unstable-book/src/SUMMARY.md +++ b/src/doc/unstable-book/src/SUMMARY.md @@ -75,6 +75,7 @@ - [simd](simd.md) - [simd_ffi](simd-ffi.md) - [slice_patterns](slice-patterns.md) +- [sort_unstable](sort-unstable.md) - [specialization](specialization.md) - [staged_api](staged-api.md) - [start](start.md) diff --git a/src/doc/unstable-book/src/concat-idents.md b/src/doc/unstable-book/src/concat-idents.md index c9a48293dba68..ecfd34a22e5cc 100644 --- a/src/doc/unstable-book/src/concat-idents.md +++ b/src/doc/unstable-book/src/concat-idents.md @@ -6,5 +6,17 @@ The tracking issue for this feature is: [#29599] ------------------------ +The `concat_idents` feature adds a macro for concatenating multiple identifiers +into one identifier. +## Examples +```rust +#![feature(concat_idents)] + +fn main() { + fn foobar() -> u32 { 23 } + let f = concat_idents!(foo, bar); + assert_eq!(f(), 23); +} +``` \ No newline at end of file diff --git a/src/doc/unstable-book/src/conservative-impl-trait.md b/src/doc/unstable-book/src/conservative-impl-trait.md index 7d8bda439bd34..62a7f8c16a0a7 100644 --- a/src/doc/unstable-book/src/conservative-impl-trait.md +++ b/src/doc/unstable-book/src/conservative-impl-trait.md @@ -6,5 +6,61 @@ The tracking issue for this feature is: [#34511] ------------------------ +The `conservative_impl_trait` feature allows a conservative form of abstract +return types. +Abstract return types allow a function to hide a concrete return type behind a +trait interface similar to trait objects, while still generating the same +statically dispatched code as with concrete types. +## Examples + +```rust +#![feature(conservative_impl_trait)] + +fn even_iter() -> impl Iterator<Item=u32> { + (0..).map(|n| n * 2) +} + +fn main() { + let first_four_even_numbers = even_iter().take(4).collect::<Vec<_>>(); + assert_eq!(first_four_even_numbers, vec![0, 2, 4, 6]); +} +``` + +## Background + +In today's Rust, you can write function signatures like: + +````rust,ignore +fn consume_iter_static<I: Iterator<u8>>(iter: I) { } + +fn consume_iter_dynamic(iter: Box<Iterator<u8>>) { } +```` + +In both cases, the function does not depend on the exact type of the argument. +The type held is "abstract", and is assumed only to satisfy a trait bound. + +* In the `_static` version using generics, each use of the function is + specialized to a concrete, statically-known type, giving static dispatch, + inline layout, and other performance wins. +* In the `_dynamic` version using trait objects, the concrete argument type is + only known at runtime using a vtable. + +On the other hand, while you can write: + +````rust,ignore +fn produce_iter_dynamic() -> Box<Iterator<u8>> { } +```` + +...but you _cannot_ write something like: + +````rust,ignore +fn produce_iter_static() -> Iterator<u8> { } +```` + +That is, in today's Rust, abstract return types can only be written using trait +objects, which can be a significant performance penalty. This RFC proposes +"unboxed abstract types" as a way of achieving signatures like +`produce_iter_static`. Like generics, unboxed abstract types guarantee static +dispatch and inline data layout. diff --git a/src/doc/unstable-book/src/const-fn.md b/src/doc/unstable-book/src/const-fn.md index 9b7942c408a24..d5a2243683862 100644 --- a/src/doc/unstable-book/src/const-fn.md +++ b/src/doc/unstable-book/src/const-fn.md @@ -6,5 +6,24 @@ The tracking issue for this feature is: [#24111] ------------------------ +The `const_fn` feature allows marking free functions and inherent methods as +`const`, enabling them to be called in constants contexts, with constant +arguments. +## Examples +```rust +#![feature(const_fn)] + +const fn double(x: i32) -> i32 { + x * 2 +} + +const FIVE: i32 = 5; +const TEN: i32 = double(FIVE); + +fn main() { + assert_eq!(5, FIVE); + assert_eq!(10, TEN); +} +``` diff --git a/src/doc/unstable-book/src/const-indexing.md b/src/doc/unstable-book/src/const-indexing.md index bd92b0b1b478f..42d46ce15f676 100644 --- a/src/doc/unstable-book/src/const-indexing.md +++ b/src/doc/unstable-book/src/const-indexing.md @@ -6,5 +6,14 @@ The tracking issue for this feature is: [#29947] ------------------------ +The `const_indexing` feature allows the constant evaluation of index operations +on constant arrays and repeat expressions. +## Examples +```rust +#![feature(const_indexing)] + +const ARR: [usize; 5] = [1, 2, 3, 4, 5]; +const ARR2: [usize; ARR[1]] = [42, 99]; +``` \ No newline at end of file diff --git a/src/doc/unstable-book/src/i128-type.md b/src/doc/unstable-book/src/i128-type.md index ffcf45feb2ad7..a850b7644c3a7 100644 --- a/src/doc/unstable-book/src/i128-type.md +++ b/src/doc/unstable-book/src/i128-type.md @@ -6,5 +6,20 @@ The tracking issue for this feature is: [#35118] ------------------------ +The `i128_type` feature adds support for 128 bit signed and unsigned integer +types. +```rust +#![feature(i128_type)] + +fn main() { + assert_eq!(1u128 + 1u128, 2u128); + assert_eq!(u128::min_value(), 0); + assert_eq!(u128::max_value(), 340282366920938463463374607431768211455); + + assert_eq!(1i128 - 2i128, -1i128); + assert_eq!(i128::min_value(), -170141183460469231731687303715884105728); + assert_eq!(i128::max_value(), 170141183460469231731687303715884105727); +} +``` diff --git a/src/doc/unstable-book/src/non-ascii-idents.md b/src/doc/unstable-book/src/non-ascii-idents.md index f426022ab3a51..d5600c58fd9a6 100644 --- a/src/doc/unstable-book/src/non-ascii-idents.md +++ b/src/doc/unstable-book/src/non-ascii-idents.md @@ -6,5 +6,13 @@ The tracking issue for this feature is: [#28979] ------------------------ +The `non_ascii_idents` feature adds support for non-ASCII identifiers. +## Examples +```rust +#![feature(non_ascii_idents)] + +const ε: f64 = 0.00001f64; +const Π: f64 = 3.14f64; +``` \ No newline at end of file diff --git a/src/doc/unstable-book/src/plugin.md b/src/doc/unstable-book/src/plugin.md index ca69b7084d3e6..3a1872e18ddb8 100644 --- a/src/doc/unstable-book/src/plugin.md +++ b/src/doc/unstable-book/src/plugin.md @@ -137,7 +137,7 @@ of extensions. See `Registry::register_syntax_extension` and the ## Tips and tricks -Some of the [macro debugging tips](../book/macros.html#debugging-macro-code) are applicable. +Some of the [macro debugging tips](../book/first-edition/macros.html#debugging-macro-code) are applicable. You can use `syntax::parse` to turn token trees into higher-level syntax elements like expressions: diff --git a/src/doc/unstable-book/src/sort-unstable.md b/src/doc/unstable-book/src/sort-unstable.md new file mode 100644 index 0000000000000..aec39de2c9a73 --- /dev/null +++ b/src/doc/unstable-book/src/sort-unstable.md @@ -0,0 +1,9 @@ +# `sort_unstable` + +The tracking issue for this feature is: [#40585] + +[#40585]: https://github.com/rust-lang/rust/issues/40585 + +------------------------ + + diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 38d843263ffda..28f6d97756f2c 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -102,7 +102,7 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// [downgrade]: struct.Arc.html#method.downgrade /// [upgrade]: struct.Weak.html#method.upgrade /// [`None`]: ../../std/option/enum.Option.html#variant.None -/// [assoc]: ../../book/method-syntax.html#associated-functions +/// [assoc]: ../../book/first-edition/method-syntax.html#associated-functions /// /// # Examples /// @@ -287,17 +287,15 @@ impl<T> Arc<T> { /// # Examples /// /// ``` - /// #![feature(rc_raw)] - /// /// use std::sync::Arc; /// /// let x = Arc::new(10); /// let x_ptr = Arc::into_raw(x); /// assert_eq!(unsafe { *x_ptr }, 10); /// ``` - #[unstable(feature = "rc_raw", issue = "37197")] - pub fn into_raw(this: Self) -> *mut T { - let ptr = unsafe { &mut (**this.ptr).data as *mut _ }; + #[stable(feature = "rc_raw", since = "1.17.0")] + pub fn into_raw(this: Self) -> *const T { + let ptr = unsafe { &(**this.ptr).data as *const _ }; mem::forget(this); ptr } @@ -315,8 +313,6 @@ impl<T> Arc<T> { /// # Examples /// /// ``` - /// #![feature(rc_raw)] - /// /// use std::sync::Arc; /// /// let x = Arc::new(10); @@ -332,11 +328,14 @@ impl<T> Arc<T> { /// /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling! /// ``` - #[unstable(feature = "rc_raw", issue = "37197")] - pub unsafe fn from_raw(ptr: *mut T) -> Self { + #[stable(feature = "rc_raw", since = "1.17.0")] + pub unsafe fn from_raw(ptr: *const T) -> Self { // To find the corresponding pointer to the `ArcInner` we need to subtract the offset of the // `data` field from the pointer. - Arc { ptr: Shared::new((ptr as *mut u8).offset(-offset_of!(ArcInner<T>, data)) as *mut _) } + let ptr = (ptr as *const u8).offset(-offset_of!(ArcInner<T>, data)); + Arc { + ptr: Shared::new(ptr as *const _), + } } } @@ -448,7 +447,7 @@ impl<T: ?Sized> Arc<T> { // Non-inlined part of `drop`. #[inline(never)] unsafe fn drop_slow(&mut self) { - let ptr = *self.ptr; + let ptr = self.ptr.as_mut_ptr(); // Destroy the data at this time, even though we may not free the box // allocation itself (there may still be weak pointers lying around). @@ -461,17 +460,13 @@ impl<T: ?Sized> Arc<T> { } #[inline] - #[unstable(feature = "ptr_eq", - reason = "newly added", - issue = "36497")] + #[stable(feature = "ptr_eq", since = "1.17.0")] /// Returns true if the two `Arc`s point to the same value (not /// just values that compare as equal). /// /// # Examples /// /// ``` - /// #![feature(ptr_eq)] - /// /// use std::sync::Arc; /// /// let five = Arc::new(5); @@ -628,7 +623,7 @@ impl<T: Clone> Arc<T> { // As with `get_mut()`, the unsafety is ok because our reference was // either unique to begin with, or became one upon cloning the contents. unsafe { - let inner = &mut **this.ptr; + let inner = &mut *this.ptr.as_mut_ptr(); &mut inner.data } } @@ -671,7 +666,7 @@ impl<T: ?Sized> Arc<T> { // the Arc itself to be `mut`, so we're returning the only possible // reference to the inner data. unsafe { - let inner = &mut **this.ptr; + let inner = &mut *this.ptr.as_mut_ptr(); Some(&mut inner.data) } } else { diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 6108a06634bb8..aff1fc0d42956 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -215,7 +215,7 @@ //! [downgrade]: struct.Rc.html#method.downgrade //! [upgrade]: struct.Weak.html#method.upgrade //! [`None`]: ../../std/option/enum.Option.html#variant.None -//! [assoc]: ../../book/method-syntax.html#associated-functions +//! [assoc]: ../../book/first-edition/method-syntax.html#associated-functions //! [mutability]: ../../std/cell/index.html#introducing-mutability-inside-of-something-immutable #![stable(feature = "rust1", since = "1.0.0")] @@ -364,17 +364,15 @@ impl<T> Rc<T> { /// # Examples /// /// ``` - /// #![feature(rc_raw)] - /// /// use std::rc::Rc; /// /// let x = Rc::new(10); /// let x_ptr = Rc::into_raw(x); /// assert_eq!(unsafe { *x_ptr }, 10); /// ``` - #[unstable(feature = "rc_raw", issue = "37197")] - pub fn into_raw(this: Self) -> *mut T { - let ptr = unsafe { &mut (**this.ptr).value as *mut _ }; + #[stable(feature = "rc_raw", since = "1.17.0")] + pub fn into_raw(this: Self) -> *const T { + let ptr = unsafe { &mut (*this.ptr.as_mut_ptr()).value as *const _ }; mem::forget(this); ptr } @@ -392,8 +390,6 @@ impl<T> Rc<T> { /// # Examples /// /// ``` - /// #![feature(rc_raw)] - /// /// use std::rc::Rc; /// /// let x = Rc::new(10); @@ -409,11 +405,11 @@ impl<T> Rc<T> { /// /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling! /// ``` - #[unstable(feature = "rc_raw", issue = "37197")] - pub unsafe fn from_raw(ptr: *mut T) -> Self { + #[stable(feature = "rc_raw", since = "1.17.0")] + pub unsafe fn from_raw(ptr: *const T) -> Self { // To find the corresponding pointer to the `RcBox` we need to subtract the offset of the // `value` field from the pointer. - Rc { ptr: Shared::new((ptr as *mut u8).offset(-offset_of!(RcBox<T>, value)) as *mut _) } + Rc { ptr: Shared::new((ptr as *const u8).offset(-offset_of!(RcBox<T>, value)) as *const _) } } } @@ -543,7 +539,7 @@ impl<T: ?Sized> Rc<T> { #[stable(feature = "rc_unique", since = "1.4.0")] pub fn get_mut(this: &mut Self) -> Option<&mut T> { if Rc::is_unique(this) { - let inner = unsafe { &mut **this.ptr }; + let inner = unsafe { &mut *this.ptr.as_mut_ptr() }; Some(&mut inner.value) } else { None @@ -551,17 +547,13 @@ impl<T: ?Sized> Rc<T> { } #[inline] - #[unstable(feature = "ptr_eq", - reason = "newly added", - issue = "36497")] + #[stable(feature = "ptr_eq", since = "1.17.0")] /// Returns true if the two `Rc`s point to the same value (not /// just values that compare as equal). /// /// # Examples /// /// ``` - /// #![feature(ptr_eq)] - /// /// use std::rc::Rc; /// /// let five = Rc::new(5); @@ -631,7 +623,7 @@ impl<T: Clone> Rc<T> { // reference count is guaranteed to be 1 at this point, and we required // the `Rc<T>` itself to be `mut`, so we're returning the only possible // reference to the inner value. - let inner = unsafe { &mut **this.ptr }; + let inner = unsafe { &mut *this.ptr.as_mut_ptr() }; &mut inner.value } } @@ -677,7 +669,7 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Rc<T> { /// ``` fn drop(&mut self) { unsafe { - let ptr = *self.ptr; + let ptr = self.ptr.as_mut_ptr(); self.dec_strong(); if self.strong() == 0 { diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 7218d15ded5f8..53fe6b4bc9f4f 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -338,6 +338,7 @@ pub struct ValuesMut<'a, K: 'a, V: 'a> { } /// An iterator over a sub-range of BTreeMap's entries. +#[stable(feature = "btree_range", since = "1.17.0")] pub struct Range<'a, K: 'a, V: 'a> { front: Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge>, back: Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge>, @@ -351,6 +352,7 @@ impl<'a, K: 'a + fmt::Debug, V: 'a + fmt::Debug> fmt::Debug for Range<'a, K, V> } /// A mutable iterator over a sub-range of BTreeMap's entries. +#[stable(feature = "btree_range", since = "1.17.0")] pub struct RangeMut<'a, K: 'a, V: 'a> { front: Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>, back: Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>, @@ -724,8 +726,6 @@ impl<K: Ord, V> BTreeMap<K, V> { /// Basic usage: /// /// ``` - /// #![feature(btree_range, collections_bound)] - /// /// use std::collections::BTreeMap; /// use std::collections::Bound::Included; /// @@ -738,9 +738,7 @@ impl<K: Ord, V> BTreeMap<K, V> { /// } /// assert_eq!(Some((&5, &"b")), map.range(4..).next()); /// ``` - #[unstable(feature = "btree_range", - reason = "matches collection reform specification, waiting for dust to settle", - issue = "27787")] + #[stable(feature = "btree_range", since = "1.17.0")] pub fn range<T: ?Sized, R>(&self, range: R) -> Range<K, V> where T: Ord, K: Borrow<T>, R: RangeArgument<T> { @@ -768,8 +766,6 @@ impl<K: Ord, V> BTreeMap<K, V> { /// Basic usage: /// /// ``` - /// #![feature(btree_range)] - /// /// use std::collections::BTreeMap; /// /// let mut map: BTreeMap<&str, i32> = ["Alice", "Bob", "Carol", "Cheryl"].iter() @@ -782,9 +778,7 @@ impl<K: Ord, V> BTreeMap<K, V> { /// println!("{} => {}", name, balance); /// } /// ``` - #[unstable(feature = "btree_range", - reason = "matches collection reform specification, waiting for dust to settle", - issue = "27787")] + #[stable(feature = "btree_range", since = "1.17.0")] pub fn range_mut<T: ?Sized, R>(&mut self, range: R) -> RangeMut<K, V> where T: Ord, K: Borrow<T>, R: RangeArgument<T> { diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index e3c990c80decf..72d25f87bca95 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -113,6 +113,7 @@ pub struct IntoIter<T> { /// [`BTreeSet`]: struct.BTreeSet.html /// [`range`]: struct.BTreeSet.html#method.range #[derive(Debug)] +#[stable(feature = "btree_range", since = "1.17.0")] pub struct Range<'a, T: 'a> { iter: ::btree_map::Range<'a, T, ()>, } @@ -264,8 +265,6 @@ impl<T: Ord> BTreeSet<T> { /// # Examples /// /// ``` - /// #![feature(btree_range, collections_bound)] - /// /// use std::collections::BTreeSet; /// use std::collections::Bound::Included; /// @@ -278,9 +277,7 @@ impl<T: Ord> BTreeSet<T> { /// } /// assert_eq!(Some(&5), set.range(4..).next()); /// ``` - #[unstable(feature = "btree_range", - reason = "matches collection reform specification, waiting for dust to settle", - issue = "27787")] + #[stable(feature = "btree_range", since = "1.17.0")] pub fn range<K: ?Sized, R>(&self, range: R) -> Range<T> where K: Ord, T: Borrow<K>, R: RangeArgument<K> { diff --git a/src/libcollections/fmt.rs b/src/libcollections/fmt.rs index dfd292176d2f9..1ec1749c3aa64 100644 --- a/src/libcollections/fmt.rs +++ b/src/libcollections/fmt.rs @@ -306,7 +306,8 @@ //! `%`. The actual grammar for the formatting syntax is: //! //! ```text -//! format_string := <text> [ format <text> ] * +//! format_string := <text> [ maybe-format <text> ] * +//! maybe-format := '{' '{' | '}' '}' | <format> //! format := '{' [ argument ] [ ':' format_spec ] '}' //! argument := integer | identifier //! diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index f88bdd0ecf382..10650dab583c3 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -129,14 +129,17 @@ mod std { } /// An endpoint of a range of keys. -#[unstable(feature = "collections_bound", issue = "27787")] +#[stable(feature = "collections_bound", since = "1.17.0")] #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] pub enum Bound<T> { /// An inclusive bound. + #[stable(feature = "collections_bound", since = "1.17.0")] Included(T), /// An exclusive bound. + #[stable(feature = "collections_bound", since = "1.17.0")] Excluded(T), /// An infinite endpoint. Indicates that there is no bound in this direction. + #[stable(feature = "collections_bound", since = "1.17.0")] Unbounded, } diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs index d4f77d625b361..f58c87b801f55 100644 --- a/src/libcollections/linked_list.rs +++ b/src/libcollections/linked_list.rs @@ -142,7 +142,7 @@ impl<T> LinkedList<T> { match self.head { None => self.tail = node, - Some(head) => (**head).prev = node, + Some(head) => (*head.as_mut_ptr()).prev = node, } self.head = node; @@ -154,12 +154,12 @@ impl<T> LinkedList<T> { #[inline] fn pop_front_node(&mut self) -> Option<Box<Node<T>>> { self.head.map(|node| unsafe { - let node = Box::from_raw(*node); + let node = Box::from_raw(node.as_mut_ptr()); self.head = node.next; match self.head { None => self.tail = None, - Some(head) => (**head).prev = None, + Some(head) => (*head.as_mut_ptr()).prev = None, } self.len -= 1; @@ -177,7 +177,7 @@ impl<T> LinkedList<T> { match self.tail { None => self.head = node, - Some(tail) => (**tail).next = node, + Some(tail) => (*tail.as_mut_ptr()).next = node, } self.tail = node; @@ -189,12 +189,12 @@ impl<T> LinkedList<T> { #[inline] fn pop_back_node(&mut self) -> Option<Box<Node<T>>> { self.tail.map(|node| unsafe { - let node = Box::from_raw(*node); + let node = Box::from_raw(node.as_mut_ptr()); self.tail = node.prev; match self.tail { None => self.head = None, - Some(tail) => (**tail).next = None, + Some(tail) => (*tail.as_mut_ptr()).next = None, } self.len -= 1; @@ -269,8 +269,8 @@ impl<T> LinkedList<T> { Some(tail) => { if let Some(other_head) = other.head.take() { unsafe { - (**tail).next = Some(other_head); - (**other_head).prev = Some(tail); + (*tail.as_mut_ptr()).next = Some(other_head); + (*other_head.as_mut_ptr()).prev = Some(tail); } self.tail = other.tail.take(); @@ -484,7 +484,7 @@ impl<T> LinkedList<T> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn front_mut(&mut self) -> Option<&mut T> { - self.head.map(|node| unsafe { &mut (**node).element }) + self.head.map(|node| unsafe { &mut (*node.as_mut_ptr()).element }) } /// Provides a reference to the back element, or `None` if the list is @@ -530,7 +530,7 @@ impl<T> LinkedList<T> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn back_mut(&mut self) -> Option<&mut T> { - self.tail.map(|node| unsafe { &mut (**node).element }) + self.tail.map(|node| unsafe { &mut (*node.as_mut_ptr()).element }) } /// Adds an element first in the list. @@ -675,9 +675,9 @@ impl<T> LinkedList<T> { let second_part_head; unsafe { - second_part_head = (**split_node.unwrap()).next.take(); + second_part_head = (*split_node.unwrap().as_mut_ptr()).next.take(); if let Some(head) = second_part_head { - (**head).prev = None; + (*head.as_mut_ptr()).prev = None; } } @@ -816,7 +816,7 @@ impl<'a, T> Iterator for IterMut<'a, T> { None } else { self.head.map(|node| unsafe { - let node = &mut **node; + let node = &mut *node.as_mut_ptr(); self.len -= 1; self.head = node.next; &mut node.element @@ -838,7 +838,7 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { None } else { self.tail.map(|node| unsafe { - let node = &mut **node; + let node = &mut *node.as_mut_ptr(); self.len -= 1; self.tail = node.prev; &mut node.element @@ -896,8 +896,8 @@ impl<'a, T> IterMut<'a, T> { element: element, }))); - (**prev).next = node; - (**head).prev = node; + (*prev.as_mut_ptr()).next = node; + (*head.as_mut_ptr()).prev = node; self.list.len += 1; }, @@ -929,7 +929,7 @@ impl<'a, T> IterMut<'a, T> { if self.len == 0 { None } else { - self.head.map(|node| unsafe { &mut (**node).element }) + self.head.map(|node| unsafe { &mut (*node.as_mut_ptr()).element }) } } } diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index e4a6af33409e1..0d9ceec633119 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -838,7 +838,11 @@ impl<T> Vec<T> { self.dedup_by(|a, b| key(a) == key(b)) } - /// Removes consecutive elements in the vector that resolve to the same key. + /// Removes consecutive elements in the vector according to a predicate. + /// + /// The `same_bucket` function is passed references to two elements from the vector, and + /// returns `true` if the elements compare equal, or `false` if they do not. Only the first + /// of adjacent equal items is kept. /// /// If the vector is sorted, this removes all duplicates. /// @@ -2116,7 +2120,7 @@ unsafe impl<#[may_dangle] T> Drop for IntoIter<T> { for _x in self.by_ref() {} // RawVec handles deallocation - let _ = unsafe { RawVec::from_raw_parts(*self.buf, self.cap) }; + let _ = unsafe { RawVec::from_raw_parts(self.buf.as_mut_ptr(), self.cap) }; } } @@ -2181,7 +2185,7 @@ impl<'a, T> Drop for Drain<'a, T> { if self.tail_len > 0 { unsafe { - let source_vec = &mut **self.vec; + let source_vec = &mut *self.vec.as_mut_ptr(); // memmove back untouched tail, update to new length let start = source_vec.len(); let tail = self.tail_start; diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 1985be7f901c6..6a04d47a345e8 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -2125,7 +2125,7 @@ impl<'a, T: 'a> Drop for Drain<'a, T> { fn drop(&mut self) { for _ in self.by_ref() {} - let source_deque = unsafe { &mut **self.deque }; + let source_deque = unsafe { &mut *self.deque.as_mut_ptr() }; // T = source_deque_tail; H = source_deque_head; t = drain_tail; h = drain_head // diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs index 98d0b1c8e1565..618eb386c0f4c 100644 --- a/src/libcollectionstest/lib.rs +++ b/src/libcollectionstest/lib.rs @@ -13,11 +13,9 @@ #![feature(binary_heap_extras)] #![feature(binary_heap_peek_mut_pop)] #![feature(box_syntax)] -#![feature(btree_range)] #![feature(inclusive_range_syntax)] #![feature(collection_placement)] #![feature(collections)] -#![feature(collections_bound)] #![feature(const_fn)] #![feature(exact_size_is_empty)] #![feature(pattern)] diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 736797d162b1d..0186d9727828d 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -394,7 +394,6 @@ impl<T> Cell<T> { /// # Examples /// /// ``` - /// #![feature(move_cell)] /// use std::cell::Cell; /// /// let c1 = Cell::new(5i32); @@ -404,7 +403,7 @@ impl<T> Cell<T> { /// assert_eq!(5, c2.get()); /// ``` #[inline] - #[unstable(feature = "move_cell", issue = "39264")] + #[stable(feature = "move_cell", since = "1.17.0")] pub fn swap(&self, other: &Self) { if ptr::eq(self, other) { return; @@ -419,7 +418,6 @@ impl<T> Cell<T> { /// # Examples /// /// ``` - /// #![feature(move_cell)] /// use std::cell::Cell; /// /// let c = Cell::new(5); @@ -427,7 +425,7 @@ impl<T> Cell<T> { /// /// assert_eq!(5, old); /// ``` - #[unstable(feature = "move_cell", issue = "39264")] + #[stable(feature = "move_cell", since = "1.17.0")] pub fn replace(&self, val: T) -> T { mem::replace(unsafe { &mut *self.value.get() }, val) } @@ -437,7 +435,6 @@ impl<T> Cell<T> { /// # Examples /// /// ``` - /// #![feature(move_cell)] /// use std::cell::Cell; /// /// let c = Cell::new(5); @@ -445,7 +442,7 @@ impl<T> Cell<T> { /// /// assert_eq!(five, 5); /// ``` - #[unstable(feature = "move_cell", issue = "39264")] + #[stable(feature = "move_cell", since = "1.17.0")] pub fn into_inner(self) -> T { unsafe { self.value.into_inner() } } @@ -457,7 +454,6 @@ impl<T: Default> Cell<T> { /// # Examples /// /// ``` - /// #![feature(move_cell)] /// use std::cell::Cell; /// /// let c = Cell::new(5); @@ -466,7 +462,7 @@ impl<T: Default> Cell<T> { /// assert_eq!(five, 5); /// assert_eq!(c.into_inner(), 0); /// ``` - #[unstable(feature = "move_cell", issue = "39264")] + #[stable(feature = "move_cell", since = "1.17.0")] pub fn take(&self) -> T { self.replace(Default::default()) } diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 78764091cf032..febc825876567 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -94,7 +94,7 @@ pub const MAX: char = '\u{10ffff}'; /// /// [`char`]: ../../std/primitive.char.html /// [`u32`]: ../../std/primitive.u32.html -/// [`as`]: ../../book/casting-between-types.html#as +/// [`as`]: ../../book/first-edition/casting-between-types.html#as /// /// For an unsafe version of this function which ignores these checks, see /// [`from_u32_unchecked()`]. @@ -146,7 +146,7 @@ pub fn from_u32(i: u32) -> Option<char> { /// /// [`char`]: ../../std/primitive.char.html /// [`u32`]: ../../std/primitive.u32.html -/// [`as`]: ../../book/casting-between-types.html#as +/// [`as`]: ../../book/first-edition/casting-between-types.html#as /// /// # Safety /// diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index cc066099cf8b0..23213f56084d3 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -255,8 +255,6 @@ impl Ordering { /// # Examples /// /// ``` - /// #![feature(ordering_chaining)] - /// /// use std::cmp::Ordering; /// /// let result = Ordering::Equal.then(Ordering::Less); @@ -277,7 +275,7 @@ impl Ordering { /// /// assert_eq!(result, Ordering::Less); /// ``` - #[unstable(feature = "ordering_chaining", issue = "37053")] + #[stable(feature = "ordering_chaining", since = "1.17.0")] pub fn then(self, other: Ordering) -> Ordering { match self { Equal => other, @@ -293,8 +291,6 @@ impl Ordering { /// # Examples /// /// ``` - /// #![feature(ordering_chaining)] - /// /// use std::cmp::Ordering; /// /// let result = Ordering::Equal.then_with(|| Ordering::Less); @@ -315,7 +311,7 @@ impl Ordering { /// /// assert_eq!(result, Ordering::Less); /// ``` - #[unstable(feature = "ordering_chaining", issue = "37053")] + #[stable(feature = "ordering_chaining", since = "1.17.0")] pub fn then_with<F: FnOnce() -> Ordering>(self, f: F) -> Ordering { match self { Equal => f(), diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index f0d8d1a321917..8c7d83232de4f 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -16,7 +16,8 @@ //! # Examples //! //! ```rust -//! use std::hash::{Hash, SipHasher, Hasher}; +//! use std::collections::hash_map::DefaultHasher; +//! use std::hash::{Hash, Hasher}; //! //! #[derive(Hash)] //! struct Person { @@ -25,13 +26,21 @@ //! phone: u64, //! } //! -//! let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 }; -//! let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 }; +//! let person1 = Person { +//! id: 5, +//! name: "Janet".to_string(), +//! phone: 555_666_7777, +//! }; +//! let person2 = Person { +//! id: 5, +//! name: "Bob".to_string(), +//! phone: 555_666_7777, +//! }; //! -//! assert!(hash(&person1) != hash(&person2)); +//! assert!(calculate_hash(&person1) != calculate_hash(&person2)); //! -//! fn hash<T: Hash>(t: &T) -> u64 { -//! let mut s = SipHasher::new(); +//! fn calculate_hash<T: Hash>(t: &T) -> u64 { +//! let mut s = DefaultHasher::new(); //! t.hash(&mut s); //! s.finish() //! } @@ -43,11 +52,12 @@ //! [`Hash`]: trait.Hash.html //! //! ```rust -//! use std::hash::{Hash, Hasher, SipHasher}; +//! use std::collections::hash_map::DefaultHasher; +//! use std::hash::{Hash, Hasher}; //! //! struct Person { //! id: u32, -//! # #[allow(dead_code)] +//! # #[allow(dead_code)] //! name: String, //! phone: u64, //! } @@ -59,13 +69,21 @@ //! } //! } //! -//! let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 }; -//! let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 }; +//! let person1 = Person { +//! id: 5, +//! name: "Janet".to_string(), +//! phone: 555_666_7777, +//! }; +//! let person2 = Person { +//! id: 5, +//! name: "Bob".to_string(), +//! phone: 555_666_7777, +//! }; //! -//! assert_eq!(hash(&person1), hash(&person2)); +//! assert_eq!(calculate_hash(&person1), calculate_hash(&person2)); //! -//! fn hash<T: Hash>(t: &T) -> u64 { -//! let mut s = SipHasher::new(); +//! fn calculate_hash<T: Hash>(t: &T) -> u64 { +//! let mut s = DefaultHasher::new(); //! t.hash(&mut s); //! s.finish() //! } diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 0f47378aebb7c..edbcc73d78be3 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -409,7 +409,7 @@ pub trait Iterator { /// If you're doing some sort of looping for a side effect, it's considered /// more idiomatic to use [`for`] than `map()`. /// - /// [`for`]: ../../book/loops.html#for + /// [`for`]: ../../book/first-edition/loops.html#for /// /// # Examples /// @@ -1306,7 +1306,7 @@ pub trait Iterator { /// use a `for` loop with a list of things to build up a result. Those /// can be turned into `fold()`s: /// - /// [`for`]: ../../book/loops.html#for + /// [`for`]: ../../book/first-edition/loops.html#for /// /// ``` /// let numbers = [1, 2, 3, 4, 5]; diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index f4ce4697d7cf4..3ba0c41170921 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -164,7 +164,7 @@ pub use intrinsics::transmute; /// [uninit]: fn.uninitialized.html /// [clone]: ../clone/trait.Clone.html /// [swap]: fn.swap.html -/// [FFI]: ../../book/ffi.html +/// [FFI]: ../../book/first-edition/ffi.html /// [box]: ../../std/boxed/struct.Box.html /// [into_raw]: ../../std/boxed/struct.Box.html#method.into_raw /// [ub]: ../../reference/behavior-considered-undefined.html @@ -199,7 +199,7 @@ pub fn size_of<T>() -> usize { /// then `size_of_val` can be used to get the dynamically-known size. /// /// [slice]: ../../std/primitive.slice.html -/// [trait object]: ../../book/trait-objects.html +/// [trait object]: ../../book/first-edition/trait-objects.html /// /// # Examples /// @@ -317,7 +317,7 @@ pub fn align_of_val<T: ?Sized>(val: &T) -> usize { /// many of the same caveats. /// /// [uninit]: fn.uninitialized.html -/// [FFI]: ../../book/ffi.html +/// [FFI]: ../../book/first-edition/ffi.html /// [ub]: ../../reference/behavior-considered-undefined.html /// /// # Examples @@ -343,7 +343,7 @@ pub unsafe fn zeroed<T>() -> T { /// This is useful for [FFI] functions and initializing arrays sometimes, /// but should generally be avoided. /// -/// [FFI]: ../../book/ffi.html +/// [FFI]: ../../book/first-edition/ffi.html /// /// # Undefined behavior /// @@ -525,7 +525,7 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T { /// it will not release any borrows, as borrows are based on lexical scope. /// /// This effectively does nothing for -/// [types which implement `Copy`](../../book/ownership.html#copy-types), +/// [types which implement `Copy`](../../book/first-edition/ownership.html#copy-types), /// e.g. integers. Such values are copied and _then_ moved into the function, /// so the value persists after this function call. /// diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 260fdab9d58fb..f7b06a194a9e1 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -161,8 +161,6 @@ pub unsafe fn read<T>(src: *const T) -> T { /// Basic usage: /// /// ``` -/// #![feature(ptr_unaligned)] -/// /// let x = 12; /// let y = &x as *const i32; /// @@ -171,7 +169,7 @@ pub unsafe fn read<T>(src: *const T) -> T { /// } /// ``` #[inline(always)] -#[unstable(feature = "ptr_unaligned", issue = "37955")] +#[stable(feature = "ptr_unaligned", since = "1.17.0")] pub unsafe fn read_unaligned<T>(src: *const T) -> T { let mut tmp: T = mem::uninitialized(); copy_nonoverlapping(src as *const u8, @@ -191,9 +189,8 @@ pub unsafe fn read_unaligned<T>(src: *const T) -> T { /// allocations or resources, so care must be taken not to overwrite an object /// that should be dropped. /// -/// It does not immediately drop the contents of `src` either; it is rather -/// *moved* into the memory location `dst` and will be dropped whenever that -/// location goes out of scope. +/// Additionally, it does not drop `src`. Semantically, `src` is moved into the +/// location pointed to by `dst`. /// /// This is appropriate for initializing uninitialized memory, or overwriting /// memory that has previously been `read` from. @@ -233,6 +230,9 @@ pub unsafe fn write<T>(dst: *mut T, src: T) { /// allocations or resources, so care must be taken not to overwrite an object /// that should be dropped. /// +/// Additionally, it does not drop `src`. Semantically, `src` is moved into the +/// location pointed to by `dst`. +/// /// This is appropriate for initializing uninitialized memory, or overwriting /// memory that has previously been `read` from. /// @@ -241,8 +241,6 @@ pub unsafe fn write<T>(dst: *mut T, src: T) { /// Basic usage: /// /// ``` -/// #![feature(ptr_unaligned)] -/// /// let mut x = 0; /// let y = &mut x as *mut i32; /// let z = 12; @@ -253,7 +251,7 @@ pub unsafe fn write<T>(dst: *mut T, src: T) { /// } /// ``` #[inline] -#[unstable(feature = "ptr_unaligned", issue = "37955")] +#[stable(feature = "ptr_unaligned", since = "1.17.0")] pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) { copy_nonoverlapping(&src as *const T as *const u8, dst as *mut u8, @@ -675,7 +673,7 @@ impl<T: ?Sized> Eq for *mut T {} /// assert!(ptr::eq(five_ref, same_five_ref)); /// assert!(!ptr::eq(five_ref, other_five_ref)); /// ``` -#[unstable(feature = "ptr_eq", reason = "newly added", issue = "36497")] +#[stable(feature = "ptr_eq", since = "1.17.0")] #[inline] pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool { a == b @@ -970,11 +968,19 @@ impl<T: ?Sized> Shared<T> { /// # Safety /// /// `ptr` must be non-null. - pub unsafe fn new(ptr: *mut T) -> Self { + pub unsafe fn new(ptr: *const T) -> Self { Shared { pointer: NonZero::new(ptr), _marker: PhantomData } } } +#[unstable(feature = "shared", issue = "27730")] +impl<T: ?Sized> Shared<T> { + /// Acquires the underlying pointer as a `*mut` pointer. + pub unsafe fn as_mut_ptr(&self) -> *mut T { + **self as _ + } +} + #[unstable(feature = "shared", issue = "27730")] impl<T: ?Sized> Clone for Shared<T> { fn clone(&self) -> Self { @@ -990,10 +996,10 @@ impl<T: ?Sized, U: ?Sized> CoerceUnsized<Shared<U>> for Shared<T> where T: Unsiz #[unstable(feature = "shared", issue = "27730")] impl<T: ?Sized> Deref for Shared<T> { - type Target = *mut T; + type Target = *const T; #[inline] - fn deref(&self) -> &*mut T { + fn deref(&self) -> &*const T { unsafe { mem::transmute(&*self.pointer) } } } diff --git a/src/libcore/raw.rs b/src/libcore/raw.rs index a7d0d3899b181..a95f05227fb8b 100644 --- a/src/libcore/raw.rs +++ b/src/libcore/raw.rs @@ -25,7 +25,7 @@ /// Book][moreinfo] contains more details about the precise nature of /// these internals. /// -/// [moreinfo]: ../../book/trait-objects.html#representation +/// [moreinfo]: ../../book/first-edition/trait-objects.html#representation /// /// `TraitObject` is guaranteed to match layouts, but it is not the /// type of trait objects (e.g. the fields are not directly accessible diff --git a/src/libcore/result.rs b/src/libcore/result.rs index a05db9b489ca1..00ff2fd2ce5ef 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -803,12 +803,11 @@ impl<T: fmt::Debug, E> Result<T, E> { /// Basic usage: /// /// ```{.should_panic} - /// # #![feature(result_expect_err)] /// let x: Result<u32, &str> = Ok(10); /// x.expect_err("Testing expect_err"); // panics with `Testing expect_err: 10` /// ``` #[inline] - #[unstable(feature = "result_expect_err", issue = "39041")] + #[stable(feature = "result_expect_err", since = "1.17.0")] pub fn expect_err(self, msg: &str) -> E { match self { Ok(t) => unwrap_failed(msg, t), diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 0331c5d4ba401..22658f9a81b0d 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -10,7 +10,9 @@ //! Slice management and manipulation //! -//! For more details `std::slice`. +//! For more details see [`std::slice`]. +//! +//! [`std::slice`]: ../../std/slice/index.html #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs index e06b757691e5a..d84a1e227560e 100644 --- a/src/libcoretest/lib.rs +++ b/src/libcoretest/lib.rs @@ -23,7 +23,6 @@ #![feature(nonzero)] #![feature(rand)] #![feature(raw)] -#![feature(result_expect_err)] #![feature(sip_hash_13)] #![feature(slice_patterns)] #![feature(step_by)] @@ -31,9 +30,6 @@ #![feature(try_from)] #![feature(unicode)] #![feature(unique)] -#![feature(ordering_chaining)] -#![feature(ptr_unaligned)] -#![feature(move_cell)] #![feature(fmt_internals)] extern crate core; diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index 4567795184e4d..7a70eda955b69 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -52,14 +52,16 @@ pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tables: tables, graph: graph, fn_exit: fn_exit, - loop_scopes: Vec::new() + loop_scopes: Vec::new(), }; body_exit = cfg_builder.expr(&body.value, entry); cfg_builder.add_contained_edge(body_exit, fn_exit); - let CFGBuilder {graph, ..} = cfg_builder; - CFG {graph: graph, - entry: entry, - exit: fn_exit} + let CFGBuilder { graph, .. } = cfg_builder; + CFG { + graph: graph, + entry: entry, + exit: fn_exit, + } } impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { @@ -81,7 +83,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { self.add_ast_node(id, &[exit]) } - hir::StmtExpr(ref expr, id) | hir::StmtSemi(ref expr, id) => { + hir::StmtExpr(ref expr, id) | + hir::StmtSemi(ref expr, id) => { let exit = self.expr(&expr, pred); self.add_ast_node(id, &[exit]) } @@ -95,9 +98,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { self.pat(&local.pat, init_exit) } - hir::DeclItem(_) => { - pred - } + hir::DeclItem(_) => pred, } } @@ -107,9 +108,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { PatKind::Path(_) | PatKind::Lit(..) | PatKind::Range(..) | - PatKind::Wild => { - self.add_ast_node(pat.id, &[pred]) - } + PatKind::Wild => self.add_ast_node(pat.id, &[pred]), PatKind::Box(ref subpat) | PatKind::Ref(ref subpat, _) | @@ -125,8 +124,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } PatKind::Struct(_, ref subpats, _) => { - let pats_exit = - self.pats_all(subpats.iter().map(|f| &f.node.pat), pred); + let pats_exit = self.pats_all(subpats.iter().map(|f| &f.node.pat), pred); self.add_ast_node(pat.id, &[pats_exit]) } @@ -385,7 +383,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { let method_call = ty::MethodCall::expr(call_expr.id); let fn_ty = match self.tables.method_map.get(&method_call) { Some(method) => method.ty, - None => self.tables.expr_ty_adjusted(func_or_rcvr) + None => self.tables.expr_ty_adjusted(func_or_rcvr), }; let func_or_rcvr_exit = self.expr(func_or_rcvr, pred); @@ -556,7 +554,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { from_index: CFGIndex, to_loop: LoopScope, to_index: CFGIndex) { - let mut data = CFGEdgeData {exiting_scopes: vec![] }; + let mut data = CFGEdgeData { exiting_scopes: vec![] }; let mut scope = self.tcx.region_maps.node_extent(from_expr.id); let target_scope = self.tcx.region_maps.node_extent(to_loop.loop_id); while scope != target_scope { @@ -591,7 +589,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } span_bug!(expr.span, "no loop scope for id {}", loop_id); } - Err(err) => span_bug!(expr.span, "loop scope error: {}", err) + Err(err) => span_bug!(expr.span, "loop scope error: {}", err), } } } diff --git a/src/librustc/dep_graph/dep_tracking_map.rs b/src/librustc/dep_graph/dep_tracking_map.rs index 9f45e66f0d937..0f3108df9a822 100644 --- a/src/librustc/dep_graph/dep_tracking_map.rs +++ b/src/librustc/dep_graph/dep_tracking_map.rs @@ -39,7 +39,7 @@ impl<M: DepTrackingMapConfig> DepTrackingMap<M> { DepTrackingMap { phantom: PhantomData, graph: graph, - map: FxHashMap() + map: FxHashMap(), } } diff --git a/src/librustc/dep_graph/visit.rs b/src/librustc/dep_graph/visit.rs index a34a3591c151d..93f6e3a83a0c2 100644 --- a/src/librustc/dep_graph/visit.rs +++ b/src/librustc/dep_graph/visit.rs @@ -29,7 +29,7 @@ pub fn visit_all_item_likes_in_krate<'a, 'tcx, V, F>(tcx: TyCtxt<'a, 'tcx, 'tcx> struct TrackingVisitor<'visit, 'tcx: 'visit, F: 'visit, V: 'visit> { tcx: TyCtxt<'visit, 'tcx, 'tcx>, dep_node_fn: &'visit mut F, - visitor: &'visit mut V + visitor: &'visit mut V, } impl<'visit, 'tcx, F, V> ItemLikeVisitor<'tcx> for TrackingVisitor<'visit, 'tcx, F, V> @@ -70,13 +70,16 @@ pub fn visit_all_item_likes_in_krate<'a, 'tcx, V, F>(tcx: TyCtxt<'a, 'tcx, 'tcx> let mut tracking_visitor = TrackingVisitor { tcx: tcx, dep_node_fn: &mut dep_node_fn, - visitor: visitor + visitor: visitor, }; krate.visit_all_item_likes(&mut tracking_visitor) } pub fn visit_all_bodies_in_krate<'a, 'tcx, C>(tcx: TyCtxt<'a, 'tcx, 'tcx>, callback: C) - where C: Fn(/* body_owner */ DefId, /* body id */ hir::BodyId), + where C: Fn(/* body_owner */ + DefId, + /* body id */ + hir::BodyId) { let krate = tcx.hir.krate(); for &body_id in &krate.body_ids { diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 9279f24a57ab3..708a74c791af7 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -113,13 +113,19 @@ impl<'a, S: Into<MultiSpan>> IntoEarlyLint for (S, &'a str) { let (span, msg) = self; let mut diagnostic = Diagnostic::new(errors::Level::Warning, msg); diagnostic.set_span(span); - EarlyLint { id: id, diagnostic: diagnostic } + EarlyLint { + id: id, + diagnostic: diagnostic, + } } } impl IntoEarlyLint for Diagnostic { fn into_early_lint(self, id: LintId) -> EarlyLint { - EarlyLint { id: id, diagnostic: self } + EarlyLint { + id: id, + diagnostic: self, + } } } @@ -146,7 +152,7 @@ enum TargetLint { enum FindLintError { NotFound, - Removed + Removed, } impl LintStore { @@ -1127,7 +1133,7 @@ enum CheckLintNameResult { NoLint, // The lint is either renamed or removed. This is the warning // message. - Warning(String) + Warning(String), } /// Checks the name of a lint for its existence, and whether it was diff --git a/src/librustc/session/code_stats.rs b/src/librustc/session/code_stats.rs index a042b2abf3a29..215539de6766e 100644 --- a/src/librustc/session/code_stats.rs +++ b/src/librustc/session/code_stats.rs @@ -25,7 +25,10 @@ pub struct VariantInfo { } #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] -pub enum SizeKind { Exact, Min } +pub enum SizeKind { + Exact, + Min, +} #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub struct FieldInfo { diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 79df7de04f540..2c99ee21b0f73 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -37,7 +37,7 @@ pub mod specialization_graph; pub struct OverlapError { pub with_impl: DefId, pub trait_desc: String, - pub self_desc: Option<String> + pub self_desc: Option<String>, } /// Given a subst for the requested impl, translate it to a subst @@ -274,7 +274,7 @@ fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, } pub struct SpecializesCache { - map: FxHashMap<(DefId, DefId), bool> + map: FxHashMap<(DefId, DefId), bool>, } impl SpecializesCache { diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 44a3aabc0560a..5a696446b4bb6 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -23,7 +23,7 @@ use hir; #[derive(Clone, Copy, Debug)] pub struct ExpectedFound<T> { pub expected: T, - pub found: T + pub found: T, } // Data structures used in type unification diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 448be7fe9a149..874e032bc4644 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -374,14 +374,13 @@ impl LocalPathBuffer { fn new(root_mode: RootMode) -> LocalPathBuffer { LocalPathBuffer { root_mode: root_mode, - str: String::new() + str: String::new(), } } fn into_string(self) -> String { self.str } - } impl ItemPathBuffer for LocalPathBuffer { diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index fcfdda8721f52..af05c0c43113b 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -85,7 +85,7 @@ impl<'tcx> Value<'tcx> for Ty<'tcx> { pub struct CycleError<'a> { span: Span, - cycle: RefMut<'a, [(Span, Query)]> + cycle: RefMut<'a, [(Span, Query)]>, } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index e686d62019145..0e3005847bc2c 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -45,7 +45,7 @@ pub struct TypeAndMut<'tcx> { /// at least as big as the scope `fr.scope`". pub struct FreeRegion { pub scope: region::CodeExtent, - pub bound_region: BoundRegion + pub bound_region: BoundRegion, } #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, @@ -65,7 +65,7 @@ pub enum BoundRegion { // Anonymous region for the implicit env pointer parameter // to a closure - BrEnv + BrEnv, } /// When a region changed from late-bound to early-bound when #32330 @@ -320,7 +320,7 @@ impl<'tcx> Slice<ExistentialPredicate<'tcx>> { pub fn principal(&self) -> Option<ExistentialTraitRef<'tcx>> { match self.get(0) { Some(&ExistentialPredicate::Trait(tr)) => Some(tr), - _ => None + _ => None, } } @@ -520,13 +520,13 @@ impl<T> Binder<T> { ty::Binder(&self.0) } - pub fn map_bound_ref<F,U>(&self, f: F) -> Binder<U> + pub fn map_bound_ref<F, U>(&self, f: F) -> Binder<U> where F: FnOnce(&T) -> U { self.as_ref().map_bound(f) } - pub fn map_bound<F,U>(self, f: F) -> Binder<U> + pub fn map_bound<F, U>(self, f: F) -> Binder<U> where F: FnOnce(T) -> U { ty::Binder(f(self.0)) @@ -790,22 +790,22 @@ pub struct TyVid { #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct IntVid { - pub index: u32 + pub index: u32, } #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct FloatVid { - pub index: u32 + pub index: u32, } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)] pub struct RegionVid { - pub index: u32 + pub index: u32, } #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct SkolemizedRegionVid { - pub index: u32 + pub index: u32, } #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] @@ -819,7 +819,7 @@ pub enum InferTy { /// `infer::freshen` for more details. FreshTy(u32), FreshIntTy(u32), - FreshFloatTy(u32) + FreshFloatTy(u32), } /// A `ProjectionPredicate` for an `ExistentialTraitRef`. @@ -827,7 +827,7 @@ pub enum InferTy { pub struct ExistentialProjection<'tcx> { pub trait_ref: ExistentialTraitRef<'tcx>, pub item_name: Name, - pub ty: Ty<'tcx> + pub ty: Ty<'tcx>, } pub type PolyExistentialProjection<'tcx> = Binder<ExistentialProjection<'tcx>>; @@ -860,9 +860,9 @@ impl<'a, 'tcx, 'gcx> ExistentialProjection<'tcx> { ty::ProjectionPredicate { projection_ty: ty::ProjectionTy { trait_ref: self.trait_ref.with_self_ty(tcx, self_ty), - item_name: self.item_name + item_name: self.item_name, }, - ty: self.ty + ty: self.ty, } } } @@ -899,7 +899,7 @@ impl Region { match *self { ty::ReEarlyBound(..) => true, ty::ReLateBound(..) => true, - _ => false + _ => false, } } @@ -969,7 +969,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn is_nil(&self) -> bool { match self.sty { TyTuple(ref tys, _) => tys.is_empty(), - _ => false + _ => false, } } @@ -1047,7 +1047,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn is_ty_var(&self) -> bool { match self.sty { TyInfer(TyVar(_)) => true, - _ => false + _ => false, } } @@ -1071,7 +1071,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn is_self(&self) -> bool { match self.sty { TyParam(ref p) => p.is_self(), - _ => false + _ => false, } } @@ -1088,7 +1088,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn is_structural(&self) -> bool { match self.sty { TyAdt(..) | TyTuple(..) | TyArray(..) | TyClosure(..) => true, - _ => self.is_slice() | self.is_trait() + _ => self.is_slice() | self.is_trait(), } } @@ -1096,7 +1096,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn is_simd(&self) -> bool { match self.sty { TyAdt(def, _) => def.repr.simd, - _ => false + _ => false, } } @@ -1127,7 +1127,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn is_region_ptr(&self) -> bool { match self.sty { TyRef(..) => true, - _ => false + _ => false, } } @@ -1145,7 +1145,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn is_unsafe_ptr(&self) -> bool { match self.sty { TyRawPtr(_) => return true, - _ => return false + _ => return false, } } @@ -1189,7 +1189,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn is_trait(&self) -> bool { match self.sty { TyDynamic(..) => true, - _ => false + _ => false, } } @@ -1205,7 +1205,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { TyInfer(FreshTy(_)) => true, TyInfer(FreshIntTy(_)) => true, TyInfer(FreshFloatTy(_)) => true, - _ => false + _ => false, } } @@ -1219,7 +1219,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn is_char(&self) -> bool { match self.sty { TyChar => true, - _ => false + _ => false, } } @@ -1237,7 +1237,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn is_signed(&self) -> bool { match self.sty { TyInt(_) => true, - _ => false + _ => false, } } @@ -1245,7 +1245,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { match self.sty { TyInt(ast::IntTy::Is) | TyUint(ast::UintTy::Us) => false, TyInt(..) | TyUint(..) | TyFloat(..) => true, - _ => false + _ => false, } } @@ -1276,7 +1276,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { }, TyRef(_, mt) => Some(mt), TyRawPtr(mt) if explicit => Some(mt), - _ => None + _ => None, } } @@ -1284,7 +1284,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn builtin_index(&self) -> Option<Ty<'tcx>> { match self.sty { TyArray(ty, _) | TySlice(ty) => Some(ty), - _ => None + _ => None, } } @@ -1307,7 +1307,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn is_fn(&self) -> bool { match self.sty { TyFnDef(..) | TyFnPtr(_) => true, - _ => false + _ => false, } } @@ -1316,14 +1316,14 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { TyDynamic(ref tt, ..) => tt.principal().map(|p| p.def_id()), TyAdt(def, _) => Some(def.did), TyClosure(id, _) => Some(id), - _ => None + _ => None, } } pub fn ty_adt_def(&self) -> Option<&'tcx AdtDef> { match self.sty { TyAdt(adt, _) => Some(adt), - _ => None + _ => None, } } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index a81c3a177f885..fd95724990941 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -16,7 +16,7 @@ use infer::InferCtxt; use hir::map as hir_map; use traits::{self, Reveal}; use ty::{self, Ty, TyCtxt, TypeAndMut, TypeFlags, TypeFoldable}; -use ty::{ParameterEnvironment}; +use ty::ParameterEnvironment; use ty::fold::TypeVisitor; use ty::layout::{Layout, LayoutError}; use ty::TypeVariants::*; @@ -39,13 +39,13 @@ use hir; type Disr = ConstInt; - pub trait IntTypeExt { +pub trait IntTypeExt { fn to_ty<'a, 'gcx, 'tcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx>; fn disr_incr<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, val: Option<Disr>) -> Option<Disr>; fn assert_ty_matches(&self, val: Disr); fn initial_discriminant<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Disr; - } +} macro_rules! typed_literal { @@ -133,7 +133,7 @@ impl IntTypeExt for attr::IntType { pub enum CopyImplementationError<'tcx> { InfrigingField(&'tcx ty::FieldDef), NotAnAdt, - HasDestructor + HasDestructor, } /// Describes whether a type is representable. For types that are not @@ -159,14 +159,14 @@ impl<'tcx> ParameterEnvironment<'tcx> { tcx.infer_ctxt(self.clone(), Reveal::UserFacing).enter(|infcx| { let (adt, substs) = match self_type.sty { ty::TyAdt(adt, substs) => (adt, substs), - _ => return Err(CopyImplementationError::NotAnAdt) + _ => return Err(CopyImplementationError::NotAnAdt), }; let field_implements_copy = |field: &ty::FieldDef| { let cause = traits::ObligationCause::dummy(); match traits::fully_normalize(&infcx, cause, &field.ty(tcx, substs)) { Ok(ty) => !infcx.type_moves_by_default(ty, span), - Err(..) => false + Err(..) => false, } }; @@ -198,7 +198,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } } - _ => () + _ => (), } false } @@ -218,7 +218,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { adt.variants[0].fields.get(i).map(|f| f.ty(self, substs)) } (&TyTuple(ref v, _), None) => v.get(i).cloned(), - _ => None + _ => None, } } @@ -245,11 +245,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn struct_tail(self, mut ty: Ty<'tcx>) -> Ty<'tcx> { while let TyAdt(def, substs) = ty.sty { if !def.is_struct() { - break + break; } match def.struct_variant().fields.last() { Some(f) => ty = f.ty(self, substs), - None => break + None => break, } } ty @@ -267,14 +267,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let (mut a, mut b) = (source, target); while let (&TyAdt(a_def, a_substs), &TyAdt(b_def, b_substs)) = (&a.sty, &b.sty) { if a_def != b_def || !a_def.is_struct() { - break + break; } match a_def.struct_variant().fields.last() { Some(f) => { a = f.ty(self, a_substs); b = f.ty(self, b_substs); } - _ => break + _ => break, } } (a, b) @@ -373,7 +373,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let dtor_did = match dtor_did { Some(dtor) => dtor, - None => return None + None => return None, }; // RFC 1238: if the destructor method is tagged with the @@ -725,9 +725,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { substs_a.types().zip(substs_b.types()).all(|(a, b)| same_type(a, b)) } - _ => { - a == b - } + _ => a == b, } } diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 4ddccbfd4c597..7b5e2253109aa 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -94,7 +94,7 @@ pub fn to_readable_str(mut val: usize) -> String { if val == 0 { groups.push(format!("{}", group)); - break + break; } else { groups.push(format!("{:03}", group)); } @@ -142,7 +142,8 @@ fn get_resident() -> Option<usize> { type HANDLE = *mut u8; use libc::size_t; use std::mem; - #[repr(C)] #[allow(non_snake_case)] + #[repr(C)] + #[allow(non_snake_case)] struct PROCESS_MEMORY_COUNTERS { cb: DWORD, PageFaultCount: DWORD, @@ -184,7 +185,7 @@ pub fn indent<R, F>(op: F) -> R where } pub struct Indenter { - _cannot_construct_outside_of_this_module: () + _cannot_construct_outside_of_this_module: (), } impl Drop for Indenter { diff --git a/src/librustc/util/fs.rs b/src/librustc/util/fs.rs index 3b4b3998c5745..da6a202e5afb2 100644 --- a/src/librustc/util/fs.rs +++ b/src/librustc/util/fs.rs @@ -116,7 +116,7 @@ pub fn create_dir_racy(path: &Path) -> io::Result<()> { match fs::create_dir(path) { Ok(()) => return Ok(()), Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => return Ok(()), - Err(ref e) if e.kind() == io::ErrorKind::NotFound => {} + Err(ref e) if e.kind() == io::ErrorKind::NotFound => (), Err(e) => return Err(e), } match path.parent() { diff --git a/src/librustc_data_structures/array_vec.rs b/src/librustc_data_structures/array_vec.rs index 51e6e09ab5003..29fbcb70756ba 100644 --- a/src/librustc_data_structures/array_vec.rs +++ b/src/librustc_data_structures/array_vec.rs @@ -248,7 +248,7 @@ impl<'a, A: Array> Drop for Drain<'a, A> { if self.tail_len > 0 { unsafe { - let source_array_vec = &mut **self.array_vec; + let source_array_vec = &mut *self.array_vec.as_mut_ptr(); // memmove back untouched tail, update to new length let start = source_array_vec.len(); let tail = self.tail_start; @@ -317,4 +317,3 @@ impl<T> Default for ManuallyDrop<T> { ManuallyDrop::new() } } - diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index f278325ebec74..8ecfd75dc95a9 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -27,7 +27,6 @@ #![feature(shared)] #![feature(collections_range)] -#![feature(collections_bound)] #![cfg_attr(stage0,feature(field_init_shorthand))] #![feature(nonzero)] #![feature(rustc_private)] diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 4047f6045bcc5..3df120eece9c5 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -167,7 +167,7 @@ nav.sub { position: absolute; left: 0; top: 0; - min-height: 100vh; + min-height: 100%; } .sidebar .current { diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index 2c8bb433e8aef..211605bef1ee0 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -1154,7 +1154,7 @@ impl<'a, K, V> Iterator for Drain<'a, K, V> { fn next(&mut self) -> Option<(SafeHash, K, V)> { self.iter.next().map(|bucket| { unsafe { - (**self.table).size -= 1; + (*self.table.as_mut_ptr()).size -= 1; let (k, v) = ptr::read(bucket.pair); (SafeHash { hash: ptr::replace(bucket.hash, EMPTY_BUCKET) }, k, v) } diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 2765fd83ed554..bf3f41b13c184 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -188,6 +188,16 @@ impl OsString { /// in the given `OsString`. /// /// The collection may reserve more space to avoid frequent reallocations. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::OsString; + /// + /// let mut s = OsString::new(); + /// s.reserve(10); + /// assert!(s.capacity() >= 10); + /// ``` #[stable(feature = "osstring_simple_functions", since = "1.9.0")] pub fn reserve(&mut self, additional: usize) { self.inner.reserve(additional) @@ -200,18 +210,56 @@ impl OsString { /// Note that the allocator may give the collection more space than it /// requests. Therefore capacity can not be relied upon to be precisely /// minimal. Prefer reserve if future insertions are expected. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::OsString; + /// + /// let mut s = OsString::new(); + /// s.reserve_exact(10); + /// assert!(s.capacity() >= 10); + /// ``` #[stable(feature = "osstring_simple_functions", since = "1.9.0")] pub fn reserve_exact(&mut self, additional: usize) { self.inner.reserve_exact(additional) } /// Shrinks the capacity of the `OsString` to match its length. + /// + /// # Examples + /// + /// ``` + /// #![feature(osstring_shrink_to_fit)] + /// + /// use std::ffi::OsString; + /// + /// let mut s = OsString::from("foo"); + /// + /// s.reserve(100); + /// assert!(s.capacity() >= 100); + /// + /// s.shrink_to_fit(); + /// assert_eq!(3, s.capacity()); + /// ``` #[unstable(feature = "osstring_shrink_to_fit", issue = "40421")] pub fn shrink_to_fit(&mut self) { self.inner.shrink_to_fit() } /// Converts this `OsString` into a boxed `OsStr`. + /// + /// # Examples + /// + /// ``` + /// #![feature(into_boxed_os_str)] + /// + /// use std::ffi::{OsString, OsStr}; + /// + /// let s = OsString::from("hello"); + /// + /// let b: Box<OsStr> = s.into_boxed_os_str(); + /// ``` #[unstable(feature = "into_boxed_os_str", issue = "40380")] pub fn into_boxed_os_str(self) -> Box<OsStr> { unsafe { mem::transmute(self.inner.into_box()) } @@ -398,6 +446,16 @@ impl OsStr { /// Copies the slice into an owned [`OsString`]. /// /// [`OsString`]: struct.OsString.html + /// + /// # Examples + /// + /// ``` + /// use std::ffi::{OsStr, OsString}; + /// + /// let os_str = OsStr::new("foo"); + /// let os_string = os_str.to_os_string(); + /// assert_eq!(os_string, OsString::from("foo")); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn to_os_string(&self) -> OsString { OsString { inner: self.inner.to_owned() } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 7fa5ad255609c..0c595b69b3d2a 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -174,7 +174,7 @@ //! [slice]: primitive.slice.html //! [`atomic`]: sync/atomic/index.html //! [`collections`]: collections/index.html -//! [`for`]: ../book/loops.html#for +//! [`for`]: ../book/first-edition/loops.html#for //! [`format!`]: macro.format.html //! [`fs`]: fs/index.html //! [`io`]: io/index.html @@ -189,14 +189,14 @@ //! [`sync`]: sync/index.html //! [`thread`]: thread/index.html //! [`use std::env`]: env/index.html -//! [`use`]: ../book/crates-and-modules.html#importing-modules-with-use -//! [crate root]: ../book/crates-and-modules.html#basic-terminology-crates-and-modules +//! [`use`]: ../book/first-edition/crates-and-modules.html#importing-modules-with-use +//! [crate root]: ../book/first-edition/crates-and-modules.html#basic-terminology-crates-and-modules //! [crates.io]: https://crates.io -//! [deref coercions]: ../book/deref-coercions.html +//! [deref coercions]: ../book/first-edition/deref-coercions.html //! [files]: fs/struct.File.html //! [multithreading]: thread/index.html //! [other]: #what-is-in-the-standard-library-documentation -//! [primitive types]: ../book/primitive-types.html +//! [primitive types]: ../book/first-edition/primitive-types.html #![crate_name = "std"] #![stable(feature = "rust1", since = "1.0.0")] @@ -245,7 +245,6 @@ #![feature(char_escape_debug)] #![feature(char_internals)] #![feature(collections)] -#![feature(collections_bound)] #![feature(collections_range)] #![feature(compiler_builtins_lib)] #![feature(const_fn)] diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 49b01bc085373..b524af800c1c6 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1224,14 +1224,6 @@ impl Into<Box<Path>> for PathBuf { } } -#[stable(feature = "box_default_extra", since = "1.17.0")] -impl Default for Box<Path> { - fn default() -> Box<Path> { - let boxed: Box<OsStr> = Default::default(); - unsafe { mem::transmute(boxed) } - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for PathBuf { fn from(s: &'a T) -> PathBuf { @@ -3730,10 +3722,4 @@ mod tests { assert_eq!(&*boxed, &*path_buf); assert_eq!(&*path_buf, path); } - - #[test] - fn boxed_default() { - let boxed = <Box<Path>>::default(); - assert!(boxed.as_os_str().is_empty()); - } } diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index 11197db98a396..47beae7c80fe4 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -29,7 +29,7 @@ /// ``` /// /// [`assert!`]: macro.assert.html -/// [`if`]: ../book/if.html +/// [`if`]: ../book/first-edition/if.html /// [`BitAnd`]: ops/trait.BitAnd.html /// [`BitOr`]: ops/trait.BitOr.html /// [`Not`]: ops/trait.Not.html @@ -490,7 +490,7 @@ mod prim_str { } /// assert_eq!(tuple.2, 'c'); /// ``` /// -/// For more about tuples, see [the book](../book/primitive-types.html#tuples). +/// For more about tuples, see [the book](../book/first-edition/primitive-types.html#tuples). /// /// # Trait implementations /// diff --git a/src/libstd/process.rs b/src/libstd/process.rs index f846ef3e69e09..97c48ee590341 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -1032,7 +1032,7 @@ pub fn exit(code: i32) -> ! { /// will be run. If a clean shutdown is needed it is recommended to only call /// this function at a known point where there are no more destructors left /// to run. -#[unstable(feature = "process_abort", issue = "37838")] +#[stable(feature = "process_abort", since = "1.17.0")] pub fn abort() -> ! { unsafe { ::sys::abort_internal() }; } diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs index 78d5aa597ba0d..6c791cd336ded 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -34,7 +34,7 @@ fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize { use panic; use sys; use sys_common; - use sys_common::thread_info::{self, NewThread}; + use sys_common::thread_info; use thread::Thread; sys::init(); @@ -47,7 +47,7 @@ fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize { // created. Note that this isn't necessary in general for new threads, // but we just do this to name the main thread and to give it correct // info about the stack bounds. - let thread: Thread = NewThread::new(Some("main".to_owned())); + let thread = Thread::new(Some("main".to_owned())); thread_info::set(main_guard, thread); // Store our args if necessary in a squirreled away location diff --git a/src/libstd/sys_common/thread_info.rs b/src/libstd/sys_common/thread_info.rs index 95d8b6cc9516d..5ed48ee455871 100644 --- a/src/libstd/sys_common/thread_info.rs +++ b/src/libstd/sys_common/thread_info.rs @@ -31,7 +31,7 @@ impl ThreadInfo { if c.borrow().is_none() { *c.borrow_mut() = Some(ThreadInfo { stack_guard: None, - thread: NewThread::new(None), + thread: Thread::new(None), }) } Some(f(c.borrow_mut().as_mut().unwrap())) @@ -54,8 +54,3 @@ pub fn set(stack_guard: Option<usize>, thread: Thread) { thread: thread, })); } - -// a hack to get around privacy restrictions; implemented by `std::thread` -pub trait NewThread { - fn new(name: Option<String>) -> Self; -} diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 2bc066d3fea55..fa4cc276ee5df 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -745,7 +745,7 @@ pub struct Thread { impl Thread { // Used only internally to construct a thread object without spawning - fn new(name: Option<String>) -> Thread { + pub(crate) fn new(name: Option<String>) -> Thread { let cname = name.map(|n| { CString::new(n).expect("thread name may not contain interior null bytes") }); @@ -858,11 +858,6 @@ impl fmt::Debug for Thread { } } -// a hack to get around privacy restrictions -impl thread_info::NewThread for Thread { - fn new(name: Option<String>) -> Thread { Thread::new(name) } -} - //////////////////////////////////////////////////////////////////////////////// // JoinHandle //////////////////////////////////////////////////////////////////////////////// diff --git a/src/libstd_unicode/char.rs b/src/libstd_unicode/char.rs index 4269ce8534bd0..def2b7cc36d3d 100644 --- a/src/libstd_unicode/char.rs +++ b/src/libstd_unicode/char.rs @@ -829,7 +829,8 @@ impl char { /// // Sometimes the result is more than one character: /// assert_eq!('İ'.to_lowercase().to_string(), "i\u{307}"); /// - /// // Japanese scripts do not have case, and so: + /// // Characters that do not have both uppercase and lowercase + /// // convert into themselves. /// assert_eq!('山'.to_lowercase().to_string(), "山"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -889,7 +890,8 @@ impl char { /// // Sometimes the result is more than one character: /// assert_eq!('ß'.to_uppercase().to_string(), "SS"); /// - /// // Japanese does not have case, and so: + /// // Characters that do not have both uppercase and lowercase + /// // convert into themselves. /// assert_eq!('山'.to_uppercase().to_string(), "山"); /// ``` /// diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 8f66c1a2b8cf6..208db8391441c 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2919,7 +2919,10 @@ impl<'a> Parser<'a> { let op_span = mk_sp(op.span.lo, self.span.hi); let mut err = self.diagnostic().struct_span_err(op_span, "chained comparison operators require parentheses"); - if op.node == BinOpKind::Lt && *outer_op == AssocOp::Greater { + if op.node == BinOpKind::Lt && + *outer_op == AssocOp::Less || // Include `<` to provide this recommendation + *outer_op == AssocOp::Greater // even in a case like the following: + { // Foo<Bar<Baz<Qux, ()>>> err.help( "use `::<...>` instead of `<...>` if you meant to specify type arguments"); } diff --git a/src/test/ui/did_you_mean/issue-40396.rs b/src/test/ui/did_you_mean/issue-40396.rs new file mode 100644 index 0000000000000..1eae180976ad3 --- /dev/null +++ b/src/test/ui/did_you_mean/issue-40396.rs @@ -0,0 +1,23 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn foo() { + println!("{:?}", (0..13).collect<Vec<i32>>()); +} + +fn bar() { + println!("{:?}", Vec<i32>::new()); +} + +fn qux() { + println!("{:?}", (0..13).collect<Vec<i32>()); +} + +fn main() {} diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr new file mode 100644 index 0000000000000..1a0c74dc01a09 --- /dev/null +++ b/src/test/ui/did_you_mean/issue-40396.stderr @@ -0,0 +1,34 @@ +error: chained comparison operators require parentheses + --> $DIR/issue-40396.rs:12:37 + | +12 | println!("{:?}", (0..13).collect<Vec<i32>>()); + | ^^^^^^^^ + | + = help: use `::<...>` instead of `<...>` if you meant to specify type arguments + +error: chained comparison operators require parentheses + --> $DIR/issue-40396.rs:16:25 + | +16 | println!("{:?}", Vec<i32>::new()); + | ^^^^^^^ + | + = help: use `::<...>` instead of `<...>` if you meant to specify type arguments + +error: chained comparison operators require parentheses + --> $DIR/issue-40396.rs:20:37 + | +20 | println!("{:?}", (0..13).collect<Vec<i32>()); + | ^^^^^^^^ + | + = help: use `::<...>` instead of `<...>` if you meant to specify type arguments + +error: chained comparison operators require parentheses + --> $DIR/issue-40396.rs:20:41 + | +20 | println!("{:?}", (0..13).collect<Vec<i32>()); + | ^^^^^^ + | + = help: use `::<...>` instead of `<...>` if you meant to specify type arguments + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/span/issue-29595.rs b/src/test/ui/span/issue-29595.rs new file mode 100644 index 0000000000000..79704619ccd37 --- /dev/null +++ b/src/test/ui/span/issue-29595.rs @@ -0,0 +1,19 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(associated_consts)] + +trait Tr { + const C: Self; +} + +fn main() { + let a: u8 = Tr::C; //~ ERROR the trait bound `u8: Tr` is not satisfied +} diff --git a/src/test/ui/span/issue-29595.stderr b/src/test/ui/span/issue-29595.stderr new file mode 100644 index 0000000000000..abbac245f89f6 --- /dev/null +++ b/src/test/ui/span/issue-29595.stderr @@ -0,0 +1,10 @@ +error[E0277]: the trait bound `u8: Tr` is not satisfied + --> $DIR/issue-29595.rs:18:17 + | +18 | let a: u8 = Tr::C; //~ ERROR the trait bound `u8: Tr` is not satisfied + | ^^^^^ the trait `Tr` is not implemented for `u8` + | + = note: required by `Tr::C` + +error: aborting due to previous error + diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index c2ec42195fcb7..adddd7b7e89b0 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -250,12 +250,13 @@ impl Builder { let mut components = Vec::new(); let mut extensions = Vec::new(); - // rustc/rust-std/cargo are all required, and so is rust-mingw if it's - // available for the target. + // rustc/rust-std/cargo/docs are all required, and so is rust-mingw + // if it's available for the target. components.extend(vec![ Component { pkg: "rustc".to_string(), target: host.to_string() }, Component { pkg: "rust-std".to_string(), target: host.to_string() }, Component { pkg: "cargo".to_string(), target: host.to_string() }, + Component { pkg: "rust-docs".to_string(), target: host.to_string() }, ]); if host.contains("pc-windows-gnu") { components.push(Component { @@ -264,12 +265,6 @@ impl Builder { }); } - // Docs, other standard libraries, and the source package are all - // optional. - extensions.push(Component { - pkg: "rust-docs".to_string(), - target: host.to_string(), - }); for target in TARGETS { if target != host { extensions.push(Component { diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index ba5ca44526b86..e83a1f8aea73f 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -121,6 +121,12 @@ fn check(cache: &mut Cache, if file.extension().and_then(|s| s.to_str()) == Some("js") { return None; } + + // ignore handlebars files as they use {{}} to build links, we only + // want to test the generated files + if file.extension().and_then(|s| s.to_str()) == Some("hbs") { + return None; + } // Unfortunately we're not 100% full of valid links today to we need a few // whitelists to get this past `make check` today.