diff --git a/mk/docs.mk b/mk/docs.mk index a84977b382b..1104c3eb6db 100644 --- a/mk/docs.mk +++ b/mk/docs.mk @@ -275,9 +275,8 @@ endif docs: $(DOC_TARGETS) compiler-docs: $(COMPILER_DOC_TARGETS) -trpl: tmp/trpl.ok +trpl: doc/book/index.html -tmp/trpl.ok: $(RUSTBOOK_EXE) $(wildcard $(S)/src/doc/trpl/*.md) +doc/book/index.html: $(RUSTBOOK_EXE) $(wildcard $(S)/src/doc/trpl/*.md) $(Q)rm -rf doc/book $(Q)$(RUSTBOOK) build $(S)src/doc/trpl doc/book - $(Q)touch $@ diff --git a/mk/tests.mk b/mk/tests.mk index 97455e744d4..c8c4beb1153 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -156,8 +156,8 @@ endef $(foreach doc,$(DOCS), \ $(eval $(call DOCTEST,md-$(doc),$(S)src/doc/$(doc).md))) -$(foreach file,$(wildcard $(S)src/doc/trpl/src/*), \ - $(eval $(call DOCTEST,$(file:$(S)src/doc/trpl/src/%.md=trpl-%),$(file)))) +$(foreach file,$(wildcard $(S)src/doc/trpl/*.md), \ + $(eval $(call DOCTEST,$(file:$(S)src/doc/trpl/%.md=trpl-%),$(file)))) ###################################################################### # Main test targets diff --git a/src/doc/trpl/SUMMARY.md b/src/doc/trpl/SUMMARY.md index 0f1bce389df..1a61c6d216b 100644 --- a/src/doc/trpl/SUMMARY.md +++ b/src/doc/trpl/SUMMARY.md @@ -1,35 +1,36 @@ # Summary -* [I: The Basics](src/basic.md) - * [Installing Rust](src/installing-rust.md) - * [Hello, world!](src/hello-world.md) - * [Hello, Cargo!](src/hello-cargo.md) - * [Variable Bindings](src/variable-bindings.md) - * [If](src/if.md) - * [Functions](src/functions.md) - * [Comments](src/comments.md) - * [Compound Data Types](src/compound-data-types.md) - * [Match](src/match.md) - * [Looping](src/looping.md) - * [Strings](src/strings.md) - * [Arrays, Vectors, and Slices](src/arrays-vectors-and-slices.md) - * [Standard Input](src/standard-input.md) - * [Guessing Game](src/guessing-game.md) -* [II: Intermedite Rust](src/intermediate.md) - * [Crates and Modules](src/crates-and-modules.md) - * [Testing](src/testing.md) - * [Pointers](src/pointers.md) - * [Patterns](src/patterns.md) - * [Method Syntax](src/method-syntax.md) - * [Closures](src/closures.md) - * [Iterators](src/iterators.md) - * [Generics](src/generics.md) - * [Traits](src/traits.md) - * [Tasks](src/tasks.md) - * [Error Handling](src/error-handling.md) -* [III: Advanced Topics](src/advanced.md) - * [FFI](src/ffi.md) - * [Unsafe Code](src/unsafe.md) - * [Macros](src/macros.md) - * [Compiler Plugins](src/plugins.md) -* [Conclusion](src/conclusion.md) +* [I: The Basics](basic.md) + * [Installing Rust](installing-rust.md) + * [Hello, world!](hello-world.md) + * [Hello, Cargo!](hello-cargo.md) + * [Variable Bindings](variable-bindings.md) + * [If](if.md) + * [Functions](functions.md) + * [Comments](comments.md) + * [Compound Data Types](compound-data-types.md) + * [Match](match.md) + * [Looping](looping.md) + * [Strings](strings.md) + * [Arrays, Vectors, and Slices](arrays-vectors-and-slices.md) + * [Standard Input](standard-input.md) + * [Guessing Game](guessing-game.md) +* [II: Intermediate Rust](intermediate.md) + * [Crates and Modules](crates-and-modules.md) + * [Testing](testing.md) + * [Pointers](pointers.md) + * [Ownership](ownership.md) + * [Patterns](patterns.md) + * [Method Syntax](method-syntax.md) + * [Closures](closures.md) + * [Iterators](iterators.md) + * [Generics](generics.md) + * [Traits](traits.md) + * [Tasks](tasks.md) + * [Error Handling](error-handling.md) +* [III: Advanced Topics](advanced.md) + * [FFI](ffi.md) + * [Unsafe Code](unsafe.md) + * [Macros](macros.md) + * [Compiler Plugins](plugins.md) +* [Conclusion](conclusion.md) diff --git a/src/doc/trpl/src/advanced.md b/src/doc/trpl/advanced.md similarity index 100% rename from src/doc/trpl/src/advanced.md rename to src/doc/trpl/advanced.md diff --git a/src/doc/trpl/src/arrays-vectors-and-slices.md b/src/doc/trpl/arrays-vectors-and-slices.md similarity index 96% rename from src/doc/trpl/src/arrays-vectors-and-slices.md rename to src/doc/trpl/arrays-vectors-and-slices.md index 68fc73222fd..24d60dd2e4e 100644 --- a/src/doc/trpl/src/arrays-vectors-and-slices.md +++ b/src/doc/trpl/arrays-vectors-and-slices.md @@ -1,4 +1,4 @@ -# Arrays, Vectors, and Slices +% Arrays, Vectors, and Slices 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 @@ -48,7 +48,7 @@ errant access is the source of many bugs in other systems programming languages. A **vector** is a dynamic or "growable" array, implemented as the standard -library type [`Vec<T>`](std/vec/) (we'll talk about what the `<T>` means +library type [`Vec<T>`](../std/vec/) (we'll talk about what the `<T>` means later). Vectors are to arrays what `String` is to `&str`. You can create them with the `vec!` macro: diff --git a/src/doc/trpl/src/basic.md b/src/doc/trpl/basic.md similarity index 100% rename from src/doc/trpl/src/basic.md rename to src/doc/trpl/basic.md diff --git a/src/doc/trpl/src/closures.md b/src/doc/trpl/closures.md similarity index 99% rename from src/doc/trpl/src/closures.md rename to src/doc/trpl/closures.md index 79ae28e1b91..6413b90ee71 100644 --- a/src/doc/trpl/src/closures.md +++ b/src/doc/trpl/closures.md @@ -1,4 +1,4 @@ -# Closures +% Closures So far, we've made lots of functions in Rust, but we've given them all names. Rust also allows us to create anonymous functions. Rust's anonymous diff --git a/src/doc/trpl/src/comments.md b/src/doc/trpl/comments.md similarity index 93% rename from src/doc/trpl/src/comments.md rename to src/doc/trpl/comments.md index cce6eacea04..f02c1ad9a18 100644 --- a/src/doc/trpl/src/comments.md +++ b/src/doc/trpl/comments.md @@ -1,4 +1,4 @@ -# Comments +% 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 @@ -42,5 +42,5 @@ fn hello(name: &str) { When writing doc comments, adding sections for any arguments, return values, and providing some examples of usage is very, very helpful. -You can use the [`rustdoc`](rustdoc.html) tool to generate HTML documentation +You can use the [`rustdoc`](../rustdoc.html) tool to generate HTML documentation from these doc comments. diff --git a/src/doc/trpl/src/compound-data-types.md b/src/doc/trpl/compound-data-types.md similarity index 99% rename from src/doc/trpl/src/compound-data-types.md rename to src/doc/trpl/compound-data-types.md index b9bb5097361..b80d248bc41 100644 --- a/src/doc/trpl/src/compound-data-types.md +++ b/src/doc/trpl/compound-data-types.md @@ -1,4 +1,4 @@ -# Compound Data Types +% Compound Data Types Rust, like many programming languages, has a number of different data types that are built-in. You've already done some simple work with integers and diff --git a/src/doc/trpl/src/conclusion.md b/src/doc/trpl/conclusion.md similarity index 100% rename from src/doc/trpl/src/conclusion.md rename to src/doc/trpl/conclusion.md diff --git a/src/doc/trpl/src/crates-and-modules.md b/src/doc/trpl/crates-and-modules.md similarity index 100% rename from src/doc/trpl/src/crates-and-modules.md rename to src/doc/trpl/crates-and-modules.md diff --git a/src/doc/trpl/src/error-handling.md b/src/doc/trpl/error-handling.md similarity index 100% rename from src/doc/trpl/src/error-handling.md rename to src/doc/trpl/error-handling.md diff --git a/src/doc/trpl/src/ffi.md b/src/doc/trpl/ffi.md similarity index 100% rename from src/doc/trpl/src/ffi.md rename to src/doc/trpl/ffi.md diff --git a/src/doc/trpl/src/functions.md b/src/doc/trpl/functions.md similarity index 99% rename from src/doc/trpl/src/functions.md rename to src/doc/trpl/functions.md index 0fa3c66af64..e3827d962c3 100644 --- a/src/doc/trpl/src/functions.md +++ b/src/doc/trpl/functions.md @@ -1,4 +1,4 @@ -# Functions +% Functions You've already seen one function so far, the `main` function: diff --git a/src/doc/trpl/src/generics.md b/src/doc/trpl/generics.md similarity index 100% rename from src/doc/trpl/src/generics.md rename to src/doc/trpl/generics.md diff --git a/src/doc/trpl/src/guessing-game.md b/src/doc/trpl/guessing-game.md similarity index 98% rename from src/doc/trpl/src/guessing-game.md rename to src/doc/trpl/guessing-game.md index 1efcd489760..2847964f15f 100644 --- a/src/doc/trpl/src/guessing-game.md +++ b/src/doc/trpl/guessing-game.md @@ -1,4 +1,4 @@ -# Guessing Game +% Guessing Game Okay! We've got the basics of Rust down. Let's write a bigger program. @@ -108,12 +108,12 @@ we do know that Rust has random number generation, but we don't know how to use it. Enter the docs. Rust has a page specifically to document the standard library. -You can find that page [here](std/index.html). There's a lot of information on +You can find that page [here](../std/index.html). There's a lot of information on that page, but the best part is the search bar. Right up at the top, there's a box that you can enter in a search term. The search is pretty primitive right now, but is getting better all the time. If you type 'random' in that -box, the page will update to [this one](std/index.html?search=random). The very -first result is a link to [`std::rand::random`](std/rand/fn.random.html). If we +box, the page will update to [this one](../std/index.html?search=random). The very +first result is a link to [`std::rand::random`](../std/rand/fn.random.html). If we click on that result, we'll be taken to its documentation page. This page shows us a few things: the type signature of the function, some diff --git a/src/doc/trpl/src/hello-cargo.md b/src/doc/trpl/hello-cargo.md similarity index 99% rename from src/doc/trpl/src/hello-cargo.md rename to src/doc/trpl/hello-cargo.md index c81cdc465c8..d8acd95b59d 100644 --- a/src/doc/trpl/src/hello-cargo.md +++ b/src/doc/trpl/hello-cargo.md @@ -1,4 +1,4 @@ -# Hello, Cargo! +% Hello, Cargo! [Cargo](http://crates.io) is a tool that Rustaceans use to help manage their Rust projects. Cargo is currently in an alpha state, just like Rust, and so it diff --git a/src/doc/trpl/src/hello-world.md b/src/doc/trpl/hello-world.md similarity index 99% rename from src/doc/trpl/src/hello-world.md rename to src/doc/trpl/hello-world.md index 33cb752c364..f9cc1ebf0bf 100644 --- a/src/doc/trpl/src/hello-world.md +++ b/src/doc/trpl/hello-world.md @@ -1,4 +1,4 @@ -# Hello, world! +% Hello, world! Now that you have Rust installed, let's write your first Rust program. It's traditional to make your first program in any new language one that prints the diff --git a/src/doc/trpl/src/if.md b/src/doc/trpl/if.md similarity index 99% rename from src/doc/trpl/src/if.md rename to src/doc/trpl/if.md index bc3d548ce9f..6f81a27b2b7 100644 --- a/src/doc/trpl/src/if.md +++ b/src/doc/trpl/if.md @@ -1,4 +1,4 @@ -# `if` +% `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 diff --git a/src/doc/trpl/src/installing-rust.md b/src/doc/trpl/installing-rust.md similarity index 99% rename from src/doc/trpl/src/installing-rust.md rename to src/doc/trpl/installing-rust.md index 1705893c397..5893b51a420 100644 --- a/src/doc/trpl/src/installing-rust.md +++ b/src/doc/trpl/installing-rust.md @@ -1,4 +1,4 @@ -# Installing Rust +% Installing Rust The first step to using Rust is to install it! There are a number of ways to install Rust, but the easiest is to use the `rustup` script. If you're on diff --git a/src/doc/trpl/src/intermediate.md b/src/doc/trpl/intermediate.md similarity index 100% rename from src/doc/trpl/src/intermediate.md rename to src/doc/trpl/intermediate.md diff --git a/src/doc/trpl/src/iterators.md b/src/doc/trpl/iterators.md similarity index 99% rename from src/doc/trpl/src/iterators.md rename to src/doc/trpl/iterators.md index 056e9a9720e..a773b7329db 100644 --- a/src/doc/trpl/src/iterators.md +++ b/src/doc/trpl/iterators.md @@ -336,4 +336,4 @@ 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). +consumers, check out the [iterator module documentation](../std/iter/index.html). diff --git a/src/doc/trpl/src/looping.md b/src/doc/trpl/looping.md similarity index 99% rename from src/doc/trpl/src/looping.md rename to src/doc/trpl/looping.md index 03384b28703..80926c99e87 100644 --- a/src/doc/trpl/src/looping.md +++ b/src/doc/trpl/looping.md @@ -1,4 +1,4 @@ -# Looping +% Looping Looping is the last basic construct that we haven't learned yet in Rust. Rust has two main looping constructs: `for` and `while`. diff --git a/src/doc/trpl/src/macros.md b/src/doc/trpl/macros.md similarity index 99% rename from src/doc/trpl/src/macros.md rename to src/doc/trpl/macros.md index 95f5305775e..c694806b4ba 100644 --- a/src/doc/trpl/src/macros.md +++ b/src/doc/trpl/macros.md @@ -507,7 +507,7 @@ When this library is loaded with `#[use_macros] extern crate`, only `m2` will be imported. The Rust Reference has a [listing of macro-related -attributes](reference.html#macro--and-plugin-related-attributes). +attributes](../reference.html#macro--and-plugin-related-attributes). # The variable `$crate` @@ -567,7 +567,7 @@ intermediate states out, and passing the flag `--pretty expanded` as a command-line argument to the compiler will show the result of expansion. If Rust's macro system can't do what you need, you may want to write a -[compiler plugin](guide-plugin.html) instead. Compared to `macro_rules!` +[compiler plugin](plugin.html) instead. Compared to `macro_rules!` macros, this is significantly more work, the interfaces are much less stable, and the warnings about debugging apply ten-fold. In exchange you get the flexibility of running arbitrary Rust code within the compiler. Syntax diff --git a/src/doc/trpl/src/match.md b/src/doc/trpl/match.md similarity index 99% rename from src/doc/trpl/src/match.md rename to src/doc/trpl/match.md index 0170109def0..c120142cf5c 100644 --- a/src/doc/trpl/src/match.md +++ b/src/doc/trpl/match.md @@ -1,4 +1,4 @@ -# Match +% Match Often, a simple `if`/`else` isn't enough, because you have more than two possible options. Also, `else` conditions can get incredibly complicated, so diff --git a/src/doc/trpl/src/method-syntax.md b/src/doc/trpl/method-syntax.md similarity index 100% rename from src/doc/trpl/src/method-syntax.md rename to src/doc/trpl/method-syntax.md diff --git a/src/doc/trpl/src/ownership.md b/src/doc/trpl/ownership.md similarity index 100% rename from src/doc/trpl/src/ownership.md rename to src/doc/trpl/ownership.md diff --git a/src/doc/trpl/src/patterns.md b/src/doc/trpl/patterns.md similarity index 100% rename from src/doc/trpl/src/patterns.md rename to src/doc/trpl/patterns.md diff --git a/src/doc/trpl/src/plugins.md b/src/doc/trpl/plugins.md similarity index 81% rename from src/doc/trpl/src/plugins.md rename to src/doc/trpl/plugins.md index 025f0cced63..2a0710d018c 100644 --- a/src/doc/trpl/src/plugins.md +++ b/src/doc/trpl/plugins.md @@ -5,20 +5,20 @@ <p> <b>Warning:</b> Plugins are an advanced, unstable feature! For many details, the only available documentation is the <a -href="syntax/index.html"><code>libsyntax</code></a> and <a -href="rustc/index.html"><code>librustc</code></a> API docs, or even the source +href="../syntax/index.html"><code>libsyntax</code></a> and <a +href="../rustc/index.html"><code>librustc</code></a> API docs, or even the source code itself. These internal compiler APIs are also subject to change at any time. </p> <p> For defining new syntax it is often much easier to use Rust's <a -href="guide-macros.html">built-in macro system</a>. +href="macros.html">built-in macro system</a>. </p> <p style="margin-bottom: 0"> The code in this document uses language features not covered in the Rust -Guide. See the <a href="reference.html">Reference Manual</a> for more +Guide. See the <a href="../reference.html">Reference Manual</a> for more information. </p> @@ -32,19 +32,19 @@ 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 use these extensions by loading the plugin crate with `#[plugin] extern crate`. See the -[`rustc::plugin`](rustc/plugin/index.html) documentation for more about the +[`rustc::plugin`](../rustc/plugin/index.html) documentation for more about the mechanics of defining and loading a plugin. Arguments passed as `#[plugin=...]` or `#[plugin(...)]` are not interpreted by rustc itself. They are provided to the plugin through the `Registry`'s [`args` -method](rustc/plugin/registry/struct.Registry.html#method.args). +method](../rustc/plugin/registry/struct.Registry.html#method.args). # 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](guide-macros.html), but the expansion is performed by arbitrary Rust -code that manipulates [syntax trees](syntax/ast/index.html) at +macros](macros.html), but the expansion is performed by arbitrary Rust +code that manipulates [syntax trees](../syntax/ast/index.html) at compile time. Let's write a plugin @@ -126,14 +126,13 @@ The advantages over a simple `fn(&str) -> uint` are: a way to define new literal syntax for any data type. In addition to procedural macros, you can define new -[`deriving`](reference.html#deriving)-like attributes and other kinds of +[`deriving`](../reference.html#deriving)-like attributes and other kinds of extensions. See -[`Registry::register_syntax_extension`](rustc/plugin/registry/struct.Registry.html#method.register_syntax_extension) +[`Registry::register_syntax_extension`](../rustc/plugin/registry/struct.Registry.html#method.register_syntax_extension) and the [`SyntaxExtension` enum](http://doc.rust-lang.org/syntax/ext/base/enum.SyntaxExtension.html). For a more involved macro example, see -[`src/libregex_macros/lib.rs`](https://github.com/rust-lang/rust/blob/master/src/libregex_macros/lib.rs) -in the Rust distribution. +[`regex_macros`](https://github.com/rust-lang/regex/blob/master/regex_macros/src/lib.rs). ## Tips and tricks @@ -147,7 +146,7 @@ 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. -You can use [`syntax::parse`](syntax/parse/index.html) to turn token trees into +You can use [`syntax::parse`](../syntax/parse/index.html) to turn token trees into higher-level syntax elements like expressions: ```ignore @@ -163,23 +162,23 @@ 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](syntax/codemap/struct.Span.html) of +Keep the [`Span`s](../syntax/codemap/struct.Span.html) of everything you parse, for better error reporting. You can wrap -[`Spanned`](syntax/codemap/struct.Spanned.html) around +[`Spanned`](../syntax/codemap/struct.Spanned.html) around your custom data structures. Calling -[`ExtCtxt::span_fatal`](syntax/ext/base/struct.ExtCtxt.html#method.span_fatal) +[`ExtCtxt::span_fatal`](../syntax/ext/base/struct.ExtCtxt.html#method.span_fatal) will immediately abort compilation. It's better to instead call -[`ExtCtxt::span_err`](syntax/ext/base/struct.ExtCtxt.html#method.span_err) +[`ExtCtxt::span_err`](../syntax/ext/base/struct.ExtCtxt.html#method.span_err) and return -[`DummyResult`](syntax/ext/base/struct.DummyResult.html), +[`DummyResult`](../syntax/ext/base/struct.DummyResult.html), so that the compiler can continue and find further errors. The example above produced an integer literal using -[`AstBuilder::expr_uint`](syntax/ext/build/trait.AstBuilder.html#tymethod.expr_uint). +[`AstBuilder::expr_uint`](../syntax/ext/build/trait.AstBuilder.html#tymethod.expr_uint). As an alternative to the `AstBuilder` trait, `libsyntax` provides a set of -[quasiquote macros](syntax/ext/quote/index.html). They are undocumented and +[quasiquote macros](../syntax/ext/quote/index.html). 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. @@ -187,7 +186,7 @@ starting point for an improved quasiquote as an ordinary plugin library. # Lint plugins Plugins can extend [Rust's lint -infrastructure](reference.html#lint-check-attributes) with additional checks for +infrastructure](../reference.html#lint-check-attributes) with additional checks for code style, safety, etc. You can see [`src/test/auxiliary/lint_plugin_test.rs`](https://github.com/rust-lang/rust/blob/master/src/test/auxiliary/lint_plugin_test.rs) for a full example, the core of which is reproduced here: @@ -236,11 +235,11 @@ foo.rs:4 fn lintme() { } The components of a lint plugin are: * one or more `declare_lint!` invocations, which define static - [`Lint`](rustc/lint/struct.Lint.html) structs; + [`Lint`](../rustc/lint/struct.Lint.html) structs; * a struct holding any state needed by the lint pass (here, none); -* a [`LintPass`](rustc/lint/trait.LintPass.html) +* a [`LintPass`](../rustc/lint/trait.LintPass.html) 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. @@ -252,7 +251,7 @@ 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.html#lint-check-attributes), e.g. `#[allow(test_lint)]` or +flags](../reference.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. diff --git a/src/doc/trpl/src/pointers.md b/src/doc/trpl/pointers.md similarity index 98% rename from src/doc/trpl/src/pointers.md rename to src/doc/trpl/pointers.md index 4c35fae3ecc..ad80d2812d0 100644 --- a/src/doc/trpl/src/pointers.md +++ b/src/doc/trpl/pointers.md @@ -409,7 +409,7 @@ test.rs:4 let y = &x; As you might guess, this kind of analysis is complex for a human, and therefore hard for a computer, too! There is an entire [guide devoted to references, ownership, -and lifetimes](guide-ownership.html) that goes into this topic in +and lifetimes](ownership.html) that goes into this topic in great detail, so if you want the full details, check that out. ## Best practices @@ -542,7 +542,7 @@ with some improvements: 4. Rust enforces that no other writeable pointers alias to this heap memory, which means writing to an invalid pointer is not possible. -See the section on references or the [ownership guide](guide-ownership.html) +See the section on references or the [ownership guide](ownership.html) for more detail on how lifetimes work. Using boxes and references together is very common. For example: @@ -780,6 +780,6 @@ Here's a quick rundown of Rust's pointer types: # Related resources -* [API documentation for Box](std/boxed/index.html) -* [Ownership guide](guide-ownership.html) +* [API documentation for Box](../std/boxed/index.html) +* [Ownership guide](ownership.html) * [Cyclone paper on regions](http://www.cs.umd.edu/projects/cyclone/papers/cyclone-regions.pdf), which inspired Rust's lifetime system diff --git a/src/doc/trpl/src/guide-lifetimes.md b/src/doc/trpl/src/guide-lifetimes.md deleted file mode 100644 index 7a5c535827c..00000000000 --- a/src/doc/trpl/src/guide-lifetimes.md +++ /dev/null @@ -1,565 +0,0 @@ -% The Rust References and Lifetimes Guide - -# Introduction - -References are one of the more flexible and powerful tools available in -Rust. They can point anywhere: into the heap, stack, and even into the -interior of another data structure. A reference is as flexible as a C pointer -or C++ reference. - -Unlike C and C++ compilers, the Rust compiler includes special static -checks that ensure that programs use references safely. - -Despite their complete safety, a reference's representation at runtime -is the same as that of an ordinary pointer in a C program. They introduce zero -overhead. The compiler does all safety checks at compile time. - -Although references have rather elaborate theoretical underpinnings -(e.g. region pointers), the core concepts will be familiar to anyone -who has worked with C or C++. The best way to explain how they are -used—and their limitations—is probably just to work through several examples. - -# By example - -References, sometimes known as *borrowed pointers*, are only valid for -a limited duration. References never claim any kind of ownership -over the data that they point to. Instead, they are used for cases -where you would like to use data for a short time. - -Consider a simple struct type `Point`: - -~~~ -struct Point {x: f64, y: f64} -~~~ - -We can use this simple definition to allocate points in many different ways. For -example, in this code, each of these local variables contains a point, -but allocated in a different place: - -~~~ -# struct Point {x: f64, y: f64} -let on_the_stack : Point = Point {x: 3.0, y: 4.0}; -let on_the_heap : Box<Point> = box Point {x: 7.0, y: 9.0}; -~~~ - -Suppose we wanted to write a procedure that computed the distance between any -two points, no matter where they were stored. One option is to define a function -that takes two arguments of type `Point`—that is, it takes the points by value. -But if we define it this way, calling the function will cause the points to be -copied. For points, this is probably not so bad, but often copies are -expensive. So we'd like to define a function that takes the points just as -a reference. - -~~~ -# use std::num::Float; -# struct Point {x: f64, y: f64} -# fn sqrt(f: f64) -> f64 { 0.0 } -fn compute_distance(p1: &Point, p2: &Point) -> f64 { - let x_d = p1.x - p2.x; - let y_d = p1.y - p2.y; - (x_d * x_d + y_d * y_d).sqrt() -} -~~~ - -Now we can call `compute_distance()`: - -~~~ -# struct Point {x: f64, y: f64} -# let on_the_stack : Point = Point{x: 3.0, y: 4.0}; -# let on_the_heap : Box<Point> = box Point{x: 7.0, y: 9.0}; -# fn compute_distance(p1: &Point, p2: &Point) -> f64 { 0.0 } -compute_distance(&on_the_stack, &*on_the_heap); -~~~ - -Here, the `&` operator takes the address of the variable -`on_the_stack`; this is because `on_the_stack` has the type `Point` -(that is, a struct value) and we have to take its address to get a -value. We also call this _borrowing_ the local variable -`on_the_stack`, because we have created an alias: that is, another -name for the same data. - -Likewise, in the case of `on_the_heap`, -the `&` operator is used in conjunction with the `*` operator -to take a reference to the contents of the box. - -Whenever a caller lends data to a callee, there are some limitations on what -the caller can do with the original. For example, if the contents of a -variable have been lent out, you cannot send that variable to another task. In -addition, the compiler will reject any code that might cause the borrowed -value to be freed or overwrite its component fields with values of different -types (I'll get into what kinds of actions those are shortly). This rule -should make intuitive sense: you must wait for a borrower to return the value -that you lent it (that is, wait for the reference to go out of scope) -before you can make full use of it again. - -# Other uses for the & operator - -In the previous example, the value `on_the_stack` was defined like so: - -~~~ -# struct Point {x: f64, y: f64} -let on_the_stack: Point = Point {x: 3.0, y: 4.0}; -~~~ - -This declaration means that code can only pass `Point` by value to other -functions. As a consequence, we had to explicitly take the address of -`on_the_stack` to get a reference. Sometimes however it is more -convenient to move the & operator into the definition of `on_the_stack`: - -~~~ -# struct Point {x: f64, y: f64} -let on_the_stack2: &Point = &Point {x: 3.0, y: 4.0}; -~~~ - -Applying `&` to an rvalue (non-assignable location) is just a convenient -shorthand for creating a temporary and taking its address. A more verbose -way to write the same code is: - -~~~ -# struct Point {x: f64, y: f64} -let tmp = Point {x: 3.0, y: 4.0}; -let on_the_stack2 : &Point = &tmp; -~~~ - -# Taking the address of fields - -The `&` operator is not limited to taking the address of -local variables. It can also take the address of fields or -individual array elements. For example, consider this type definition -for `Rectangle`: - -~~~ -struct Point {x: f64, y: f64} // as before -struct Size {w: f64, h: f64} // as before -struct Rectangle {origin: Point, size: Size} -~~~ - -Now, as before, we can define rectangles in a few different ways: - -~~~ -# struct Point {x: f64, y: f64} -# struct Size {w: f64, h: f64} // as before -# struct Rectangle {origin: Point, size: Size} -let rect_stack = &Rectangle {origin: Point {x: 1.0, y: 2.0}, - size: Size {w: 3.0, h: 4.0}}; -let rect_heap = box Rectangle {origin: Point {x: 5.0, y: 6.0}, - size: Size {w: 3.0, h: 4.0}}; -~~~ - -In each case, we can extract out individual subcomponents with the `&` -operator. For example, I could write: - -~~~ -# struct Point {x: f64, y: f64} // as before -# struct Size {w: f64, h: f64} // as before -# struct Rectangle {origin: Point, size: Size} -# let rect_stack = &Rectangle {origin: Point {x: 1.0, y: 2.0}, size: Size {w: 3.0, h: 4.0}}; -# let rect_heap = box Rectangle {origin: Point {x: 5.0, y: 6.0}, size: Size {w: 3.0, h: 4.0}}; -# fn compute_distance(p1: &Point, p2: &Point) -> f64 { 0.0 } -compute_distance(&rect_stack.origin, &rect_heap.origin); -~~~ - -which would borrow the field `origin` from the rectangle on the stack -as well as from the owned box, and then compute the distance between them. - -# Lifetimes - -We’ve seen a few examples of borrowing data. To this point, we’ve glossed -over issues of safety. As stated in the introduction, at runtime a reference -is simply a pointer, nothing more. Therefore, avoiding C's problems with -dangling pointers requires a compile-time safety check. - -The basis for the check is the notion of _lifetimes_. A lifetime is a -static approximation of the span of execution during which the pointer -is valid: it always corresponds to some expression or block within the -program. - -The compiler will only allow a borrow *if it can guarantee that the data will -not be reassigned or moved for the lifetime of the pointer*. This does not -necessarily mean that the data is stored in immutable memory. For example, -the following function is legal: - -~~~ -# fn some_condition() -> bool { true } -# struct Foo { f: int } -fn example3() -> int { - let mut x = box Foo {f: 3}; - if some_condition() { - let y = &x.f; // -+ L - return *y; // | - } // -+ - x = box Foo {f: 4}; - // ... -# return 0; -} -~~~ - -Here, the interior of the variable `x` is being borrowed -and `x` is declared as mutable. However, the compiler can prove that -`x` is not assigned anywhere in the lifetime L of the variable -`y`. Therefore, it accepts the function, even though `x` is mutable -and in fact is mutated later in the function. - -It may not be clear why we are so concerned about mutating a borrowed -variable. The reason is that the runtime system frees any box -_as soon as its owning reference changes or goes out of -scope_. Therefore, a program like this is illegal (and would be -rejected by the compiler): - -~~~ {.ignore} -fn example3() -> int { - let mut x = box X {f: 3}; - let y = &x.f; - x = box X {f: 4}; // Error reported here. - *y -} -~~~ - -To make this clearer, consider this diagram showing the state of -memory immediately before the re-assignment of `x`: - -~~~ {.text} - Stack Exchange Heap - - x +-------------+ - | box {f:int} | ----+ - y +-------------+ | - | &int | ----+ - +-------------+ | +---------+ - +--> | f: 3 | - +---------+ -~~~ - -Once the reassignment occurs, the memory will look like this: - -~~~ {.text} - Stack Exchange Heap - - x +-------------+ +---------+ - | box {f:int} | -------> | f: 4 | - y +-------------+ +---------+ - | &int | ----+ - +-------------+ | +---------+ - +--> | (freed) | - +---------+ -~~~ - -Here you can see that the variable `y` still points at the old `f` -property of Foo, which has been freed. - -In fact, the compiler can apply the same kind of reasoning to any -memory that is (uniquely) owned by the stack frame. So we could -modify the previous example to introduce additional owned pointers -and structs, and the compiler will still be able to detect possible -mutations. This time, we'll use an analogy to illustrate the concept. - -~~~ {.ignore} -fn example3() -> int { - struct House { owner: Box<Person> } - struct Person { age: int } - - let mut house = box House { - owner: box Person {age: 30} - }; - - let owner_age = &house.owner.age; - house = box House {owner: box Person {age: 40}}; // Error reported here. - house.owner = box Person {age: 50}; // Error reported here. - *owner_age -} -~~~ - -In this case, two errors are reported, one when the variable `house` is -modified and another when `house.owner` is modified. Either modification would -invalidate the pointer `owner_age`. - -# Borrowing and enums - -The previous example showed that the type system forbids any mutations -of owned boxed values while they are being borrowed. In general, the type -system also forbids borrowing a value as mutable if it is already being -borrowed - either as a mutable reference or an immutable one. This restriction -prevents pointers from pointing into freed memory. There is one other -case where the compiler must be very careful to ensure that pointers -remain valid: pointers into the interior of an `enum`. - -Let’s look at the following `shape` type that can represent both rectangles -and circles: - -~~~ -struct Point {x: f64, y: f64}; // as before -struct Size {w: f64, h: f64}; // as before -enum Shape { - Circle(Point, f64), // origin, radius - Rectangle(Point, Size) // upper-left, dimensions -} -~~~ - -Now we might write a function to compute the area of a shape. This -function takes a reference to a shape, to avoid the need for -copying. - -~~~ -# struct Point {x: f64, y: f64}; // as before -# struct Size {w: f64, h: f64}; // as before -# enum Shape { -# Circle(Point, f64), // origin, radius -# Rectangle(Point, Size) // upper-left, dimensions -# } -fn compute_area(shape: &Shape) -> f64 { - match *shape { - Shape::Circle(_, radius) => std::f64::consts::PI * radius * radius, - Shape::Rectangle(_, ref size) => size.w * size.h - } -} -~~~ - -The first case matches against circles. Here, the pattern extracts the -radius from the shape variant and the action uses it to compute the -area of the circle. - -The second match is more interesting. Here we match against a -rectangle and extract its size: but rather than copy the `size` -struct, we use a by-reference binding to create a pointer to it. In -other words, a pattern binding like `ref size` binds the name `size` -to a pointer of type `&size` into the _interior of the enum_. - -To make this more clear, let's look at a diagram of memory layout in -the case where `shape` points at a rectangle: - -~~~ {.text} -Stack Memory - -+-------+ +---------------+ -| shape | ------> | rectangle( | -+-------+ | {x: f64, | -| size | -+ | y: f64}, | -+-------+ +----> | {w: f64, | - | h: f64}) | - +---------------+ -~~~ - -Here you can see that rectangular shapes are composed of five words of -memory. The first is a tag indicating which variant this enum is -(`rectangle`, in this case). The next two words are the `x` and `y` -fields for the point and the remaining two are the `w` and `h` fields -for the size. The binding `size` is then a pointer into the inside of -the shape. - -Perhaps you can see where the danger lies: if the shape were somehow -to be reassigned, perhaps to a circle, then although the memory used -to store that shape value would still be valid, _it would have a -different type_! The following diagram shows what memory would look -like if code overwrote `shape` with a circle: - -~~~ {.text} -Stack Memory - -+-------+ +---------------+ -| shape | ------> | circle( | -+-------+ | {x: f64, | -| size | -+ | y: f64}, | -+-------+ +----> | f64) | - | | - +---------------+ -~~~ - -As you can see, the `size` pointer would be pointing at a `f64` -instead of a struct. This is not good: dereferencing the second field -of a `f64` as if it were a struct with two fields would be a memory -safety violation. - -So, in fact, for every `ref` binding, the compiler will impose the -same rules as the ones we saw for borrowing the interior of an owned -box: it must be able to guarantee that the `enum` will not be -overwritten for the duration of the borrow. In fact, the compiler -would accept the example we gave earlier. The example is safe because -the shape pointer has type `&Shape`, which means "reference to -immutable memory containing a `shape`". If, however, the type of that -pointer were `&mut Shape`, then the ref binding would be ill-typed. -Just as with owned boxes, the compiler will permit `ref` bindings -into data owned by the stack frame even if the data are mutable, -but otherwise it requires that the data reside in immutable memory. - -# Returning references - -So far, all of the examples we have looked at, use references in a -“downward” direction. That is, a method or code block creates a -reference, then uses it within the same scope. It is also -possible to return references as the result of a function, but -as we'll see, doing so requires some explicit annotation. - -We could write a subroutine like this: - -~~~ -struct Point {x: f64, y: f64} -fn get_x<'r>(p: &'r Point) -> &'r f64 { &p.x } -~~~ - -Here, the function `get_x()` returns a pointer into the structure it -was given. The type of the parameter (`&'r Point`) and return type -(`&'r f64`) both use a new syntactic form that we have not seen so -far. Here the identifier `r` names the lifetime of the pointer -explicitly. So in effect, this function declares that it takes a -pointer with lifetime `r` and returns a pointer with that same -lifetime. - -In general, it is only possible to return references if they -are derived from a parameter to the procedure. In that case, the -pointer result will always have the same lifetime as one of the -parameters; named lifetimes indicate which parameter that -is. - -In the previous code samples, function parameter types did not include a -lifetime name. The compiler simply creates a fresh name for the lifetime -automatically: that is, the lifetime name is guaranteed to refer to a distinct -lifetime from the lifetimes of all other parameters. - -Named lifetimes that appear in function signatures are conceptually -the same as the other lifetimes we have seen before, but they are a bit -abstract: they don’t refer to a specific expression within `get_x()`, -but rather to some expression within the *caller of `get_x()`*. The -lifetime `r` is actually a kind of *lifetime parameter*: it is defined -by the caller to `get_x()`, just as the value for the parameter `p` is -defined by that caller. - -In any case, whatever the lifetime of `r` is, the pointer produced by -`&p.x` always has the same lifetime as `p` itself: a pointer to a -field of a struct is valid as long as the struct is valid. Therefore, -the compiler accepts the function `get_x()`. - -In general, if you borrow a struct or box to create a -reference, it will only be valid within the function -and cannot be returned. This is why the typical way to return references -is to take references as input (the only other case in -which it can be legal to return a reference is if it -points at a static constant). - -# Named lifetimes - -Lifetimes can be named and referenced. For example, the special lifetime -`'static`, which does not go out of scope, can be used to create global -variables and communicate between tasks (see the manual for use cases). - -## Parameter Lifetimes - -Named lifetimes allow for grouping of parameters by lifetime. -For example, consider this function: - -~~~ -# struct Point {x: f64, y: f64}; // as before -# struct Size {w: f64, h: f64}; // as before -# enum Shape { -# Circle(Point, f64), // origin, radius -# Rectangle(Point, Size) // upper-left, dimensions -# } -# fn compute_area(shape: &Shape) -> f64 { 0.0 } -fn select<'r, T>(shape: &'r Shape, threshold: f64, - a: &'r T, b: &'r T) -> &'r T { - if compute_area(shape) > threshold {a} else {b} -} -~~~ - -This function takes three references and assigns each the same -lifetime `r`. In practice, this means that, in the caller, the -lifetime `r` will be the *intersection of the lifetime of the three -region parameters*. This may be overly conservative, as in this -example: - -~~~ -# struct Point {x: f64, y: f64}; // as before -# struct Size {w: f64, h: f64}; // as before -# enum Shape { -# Circle(Point, f64), // origin, radius -# Rectangle(Point, Size) // upper-left, dimensions -# } -# fn compute_area(shape: &Shape) -> f64 { 0.0 } -# fn select<'r, T>(shape: &Shape, threshold: f64, -# a: &'r T, b: &'r T) -> &'r T { -# if compute_area(shape) > threshold {a} else {b} -# } - // -+ r -fn select_based_on_unit_circle<'r, T>( // |-+ B - threshold: f64, a: &'r T, b: &'r T) -> &'r T { // | | - // | | - let shape = Shape::Circle(Point {x: 0., y: 0.}, 1.); // | | - select(&shape, threshold, a, b) // | | -} // |-+ - // -+ -~~~ - -In this call to `select()`, the lifetime of the first parameter shape -is B, the function body. Both of the second two parameters `a` and `b` -share the same lifetime, `r`, which is a lifetime parameter of -`select_based_on_unit_circle()`. The caller will infer the -intersection of these two lifetimes as the lifetime of the returned -value, and hence the return value of `select()` will be assigned a -lifetime of B. This will in turn lead to a compilation error, because -`select_based_on_unit_circle()` is supposed to return a value with the -lifetime `r`. - -To address this, we can modify the definition of `select()` to -distinguish the lifetime of the first parameter from the lifetime of -the latter two. After all, the first parameter is not being -returned. Here is how the new `select()` might look: - -~~~ -# struct Point {x: f64, y: f64}; // as before -# struct Size {w: f64, h: f64}; // as before -# enum Shape { -# Circle(Point, f64), // origin, radius -# Rectangle(Point, Size) // upper-left, dimensions -# } -# fn compute_area(shape: &Shape) -> f64 { 0.0 } -fn select<'r, 'tmp, T>(shape: &'tmp Shape, threshold: f64, - a: &'r T, b: &'r T) -> &'r T { - if compute_area(shape) > threshold {a} else {b} -} -~~~ - -Here you can see that `shape`'s lifetime is now named `tmp`. The -parameters `a`, `b`, and the return value all have the lifetime `r`. -However, since the lifetime `tmp` is not returned, it would be more -concise to just omit the named lifetime for `shape` altogether: - -~~~ -# struct Point {x: f64, y: f64}; // as before -# struct Size {w: f64, h: f64}; // as before -# enum Shape { -# Circle(Point, f64), // origin, radius -# Rectangle(Point, Size) // upper-left, dimensions -# } -# fn compute_area(shape: &Shape) -> f64 { 0.0 } -fn select<'r, T>(shape: &Shape, threshold: f64, - a: &'r T, b: &'r T) -> &'r T { - if compute_area(shape) > threshold {a} else {b} -} -~~~ - -This is equivalent to the previous definition. - -## Labeled Control Structures - -Named lifetime notation can also be used to control the flow of execution: - -~~~ -'h: for i in range(0u, 10) { - 'g: loop { - if i % 2 == 0 { continue 'h; } - if i == 9 { break 'h; } - break 'g; - } -} -~~~ - -> *Note:* Labelled breaks are not currently supported within `while` loops. - -Named labels are hygienic and can be used safely within macros. -See the macros guide section on hygiene for more details. - -# Conclusion - -So there you have it: a (relatively) brief tour of the lifetime -system. For more details, we refer to the (yet to be written) reference -document on references, which will explain the full notation -and give more examples. diff --git a/src/doc/trpl/src/standard-input.md b/src/doc/trpl/standard-input.md similarity index 99% rename from src/doc/trpl/src/standard-input.md rename to src/doc/trpl/standard-input.md index 5a150594f0c..2d31f06ebaa 100644 --- a/src/doc/trpl/src/standard-input.md +++ b/src/doc/trpl/standard-input.md @@ -1,4 +1,4 @@ -# Standard Input +% Standard Input Getting input from the keyboard is pretty easy, but uses some things we haven't seen before. Here's a simple program that reads some input, diff --git a/src/doc/trpl/src/strings.md b/src/doc/trpl/strings.md similarity index 99% rename from src/doc/trpl/src/strings.md rename to src/doc/trpl/strings.md index be1d09f6e95..a40e748dae7 100644 --- a/src/doc/trpl/src/strings.md +++ b/src/doc/trpl/strings.md @@ -1,4 +1,4 @@ -# Strings +% 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 diff --git a/src/doc/trpl/src/tasks.md b/src/doc/trpl/tasks.md similarity index 99% rename from src/doc/trpl/src/tasks.md rename to src/doc/trpl/tasks.md index 8eb13187e58..8e9f40b0f4e 100644 --- a/src/doc/trpl/src/tasks.md +++ b/src/doc/trpl/tasks.md @@ -369,7 +369,7 @@ Unlike `spawn`, the function spawned using `try` may return a value, which child thread terminates successfully, `try` will return an `Ok` result; if the child thread panics, `try` will return an `Error` result. -[`Result`]: std/result/index.html +[`Result`]: ../std/result/index.html > *Note:* A panicked thread does not currently produce a useful error > value (`try` always returns `Err(())`). In the diff --git a/src/doc/trpl/src/testing.md b/src/doc/trpl/testing.md similarity index 100% rename from src/doc/trpl/src/testing.md rename to src/doc/trpl/testing.md diff --git a/src/doc/trpl/src/traits.md b/src/doc/trpl/traits.md similarity index 100% rename from src/doc/trpl/src/traits.md rename to src/doc/trpl/traits.md diff --git a/src/doc/trpl/src/unsafe.md b/src/doc/trpl/unsafe.md similarity index 98% rename from src/doc/trpl/src/unsafe.md rename to src/doc/trpl/unsafe.md index 25ca07ad74f..3e0a1ef1345 100644 --- a/src/doc/trpl/src/unsafe.md +++ b/src/doc/trpl/unsafe.md @@ -12,7 +12,7 @@ block which allows the programmer to dodge some of the compiler's checks and do a wide range of operations, such as: - dereferencing [raw pointers](#raw-pointers) -- calling a function via FFI ([covered by the FFI guide](guide-ffi.html)) +- calling a function via FFI ([covered by the FFI guide](ffi.html)) - casting between types bitwise (`transmute`, aka "reinterpret cast") - [inline assembly](#inline-assembly) @@ -37,7 +37,7 @@ build safe interfaces. ## References One of Rust's biggest features is memory safety. This is achieved in -part via [the ownership system](guide-ownership.html), which is how the +part via [the ownership system](ownership.html), which is how the compiler can guarantee that every `&` reference is always valid, and, for example, never pointing to freed memory. @@ -504,7 +504,7 @@ shouldn't get triggered. The second of these three functions, `eh_personality`, is used by the failure mechanisms of the compiler. This is often mapped to GCC's personality function (see the -[libstd implementation](std/rt/unwind/index.html) for more +[libstd implementation](../std/rt/unwind/index.html) for more information), but crates which do not trigger a panic can be assured that this function is never called. The final function, `panic_fmt`, is also used by the failure mechanisms of the compiler. @@ -517,7 +517,7 @@ also used by the failure mechanisms of the compiler. With the above techniques, we've got a bare-metal executable running some Rust code. There is a good deal of functionality provided by the standard library, however, that is necessary to be productive in Rust. If the standard library is -not sufficient, then [libcore](core/index.html) is designed to be used +not sufficient, then [libcore](../core/index.html) is designed to be used instead. The core library has very few dependencies and is much more portable than the diff --git a/src/doc/trpl/src/variable-bindings.md b/src/doc/trpl/variable-bindings.md similarity index 98% rename from src/doc/trpl/src/variable-bindings.md rename to src/doc/trpl/variable-bindings.md index 8cf2522b9af..4e2e7bd2fe2 100644 --- a/src/doc/trpl/src/variable-bindings.md +++ b/src/doc/trpl/variable-bindings.md @@ -1,4 +1,4 @@ -# Variable bindings +% Variable bindings The first thing we'll learn about are 'variable bindings.' They look like this: @@ -170,5 +170,5 @@ arguments we pass to functions and macros, if you're passing more than one. When you just 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](std/fmt/index.html). For now, we'll just stick to the default: +available](../std/fmt/index.html). For now, we'll just stick to the default: integers aren't very complicated to print. diff --git a/src/rustbook/book.rs b/src/rustbook/book.rs index 45a864e3378..1d16de2a2fe 100644 --- a/src/rustbook/book.rs +++ b/src/rustbook/book.rs @@ -29,8 +29,8 @@ pub struct Book { /// A depth-first iterator over a book. pub struct BookItems<'a> { cur_items: &'a [BookItem], - cur_idx: uint, - stack: Vec<(&'a [BookItem], uint)>, + cur_idx: usize, + stack: Vec<(&'a [BookItem], usize)>, } impl<'a> Iterator for BookItems<'a> { @@ -80,7 +80,7 @@ impl Book { pub fn parse_summary<R: Reader>(input: R, src: &Path) -> Result<Book, Vec<String>> { fn collapse(stack: &mut Vec<BookItem>, top_items: &mut Vec<BookItem>, - to_level: uint) { + to_level: usize) { loop { if stack.len() < to_level { return } if stack.len() == 1 { @@ -141,7 +141,7 @@ pub fn parse_summary<R: Reader>(input: R, src: &Path) -> Result<Book, Vec<String }; let level = cap.name("indent").unwrap().chars().map(|c| { match c { - ' ' => 1u, + ' ' => 1us, '\t' => 4, _ => unreachable!() } diff --git a/src/rustbook/build.rs b/src/rustbook/build.rs old mode 100755 new mode 100644 index db79e0b45e0..1cb5e38e190 --- a/src/rustbook/build.rs +++ b/src/rustbook/build.rs @@ -130,8 +130,8 @@ fn render(book: &Book, tgt: &Path) -> CliResult<()> { ]; let output_result = rustdoc::main_args(rustdoc_args); if output_result != 0 { - - let message = format!("Could not execute `rustdoc`: {}", output_result); + let message = format!("Could not execute `rustdoc` with {:?}: {}", + rustdoc_args, output_result); return Err(box message as Box<Error>); } } @@ -172,12 +172,13 @@ impl Subcommand for Build { match book::parse_summary(summary, &src) { Ok(book) => { // execute rustdoc on the whole book - let _ = render(&book, &tgt).map_err(|err| { + try!(render(&book, &tgt).map_err(|err| { term.err(&format!("error: {}", err.description())[]); err.detail().map(|detail| { term.err(&format!("detail: {}", detail)[]); - }) - }); + }); + err + })) } Err(errors) => { for err in errors.into_iter() { diff --git a/src/rustbook/error.rs b/src/rustbook/error.rs index 1d3baef8c1c..a5915ed4d73 100644 --- a/src/rustbook/error.rs +++ b/src/rustbook/error.rs @@ -56,6 +56,12 @@ impl Error for String { } } +impl<'a> Error for Box<Error + 'a> { + fn description(&self) -> &str { (**self).description() } + fn detail(&self) -> Option<&str> { (**self).detail() } + fn cause(&self) -> Option<&Error> { (**self).cause() } +} + impl FromError<()> for () { fn from_err(_: ()) -> () { () } } diff --git a/src/rustbook/main.rs b/src/rustbook/main.rs old mode 100755 new mode 100644 diff --git a/src/rustbook/term.rs b/src/rustbook/term.rs index 18306d6ec20..471e22ce7c1 100644 --- a/src/rustbook/term.rs +++ b/src/rustbook/term.rs @@ -11,6 +11,7 @@ //! An abstraction of the terminal. Eventually, provide color and //! verbosity support. For now, just a wrapper around stdout/stderr. +use std::os; use std::io::stdio; pub struct Term { @@ -27,5 +28,6 @@ impl Term { pub fn err(&mut self, msg: &str) { // swallow any errors let _ = self.err.write_line(msg); + os::set_exit_status(101); } }