Auto merge of #39981 - frewsxcv:rollup, r=frewsxcv
Rollup of 3 pull requests - Successful merges: #39913, #39937, #39976 - Failed merges:
This commit is contained in:
commit
c1368fc4f4
6
src/Cargo.lock
generated
6
src/Cargo.lock
generated
@ -270,7 +270,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "mdbook"
|
||||
version = "0.0.15"
|
||||
version = "0.0.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"clap 2.20.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -401,7 +401,7 @@ name = "rustbook"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap 2.20.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mdbook 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mdbook 0.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -991,7 +991,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6abe0ee2e758cd6bc8a2cd56726359007748fbf4128da998b65d0b70f881e19b"
|
||||
"checksum libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "684f330624d8c3784fb9558ca46c4ce488073a8d22450415c5eb4f4cfb0d11b5"
|
||||
"checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054"
|
||||
"checksum mdbook 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "9a6b8e6eb10d1c6beeca799fe5919778cf5c6f22a4f2abb5f50faea1221adeae"
|
||||
"checksum mdbook 0.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "14e8a6aca534ac51bad1c1886b10f6d6948a14fa70b1b20a1e41c9e5c0fe3019"
|
||||
"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
|
||||
"checksum num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "a16a42856a256b39c6d3484f097f6713e14feacd9bfb02290917904fae46c81c"
|
||||
"checksum num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "cee7e88156f3f9e19bdd598f8d6c9db7bf4078f99f8381f43a55b09648d1a6e3"
|
||||
|
@ -8,7 +8,7 @@ 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%20coercions).
|
||||
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
|
||||
|
@ -463,7 +463,7 @@ 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%20Elision) doesn’t kick in here. Then what
|
||||
[elision](lifetimes.html#lifetime-elision) doesn’t kick in here. Then what
|
||||
choices do we have? Try `'static`:
|
||||
|
||||
```rust,ignore
|
||||
|
@ -127,7 +127,7 @@ enum. For a more involved macro example, see
|
||||
|
||||
## Tips and tricks
|
||||
|
||||
Some of the [macro debugging tips](macros.html#Debugging%20macro%20code) are applicable.
|
||||
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:
|
||||
|
@ -55,7 +55,7 @@ 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#RefCell%3CT%3E) does not implement
|
||||
[`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
|
||||
@ -126,7 +126,7 @@ 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%20closures); basically
|
||||
closures are explained in depth [here](closures.html#move-closures); basically
|
||||
they move variables from their environment into themselves.
|
||||
|
||||
```rust
|
||||
|
@ -21,35 +21,35 @@ 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%20Basics)
|
||||
* [Unwrapping explained](#Unwrapping%20explained)
|
||||
* [The `Option` type](#The%20Option%20type)
|
||||
* [Composing `Option<T>` values](#Composing%20Option%3CT%3E%20values)
|
||||
* [The `Result` type](#The%20Result%20type)
|
||||
* [Parsing integers](#Parsing%20integers)
|
||||
* [The `Result` type alias idiom](#The%20Result%20type%20alias%20idiom)
|
||||
* [A brief interlude: unwrapping isn't evil](#A%20brief%20interlude:%20unwrapping%20isnt%20evil)
|
||||
* [Working with multiple error types](#Working%20with%20multiple%20error%20types)
|
||||
* [Composing `Option` and `Result`](#Composing%20Option%20and%20Result)
|
||||
* [The limits of combinators](#The%20limits%20of%20combinators)
|
||||
* [Early returns](#Early%20returns)
|
||||
* [The `try!` macro](#The%20try%20macro)
|
||||
* [Defining your own error type](#Defining%20your%20own%20error%20type)
|
||||
* [Standard library traits used for error handling](#Standard%20library%20traits%20used%20for%20error%20handling)
|
||||
* [The `Error` trait](#The%20Error%20trait)
|
||||
* [The `From` trait](#The%20From%20trait)
|
||||
* [The real `try!` macro](#The%20real%20try%20macro)
|
||||
* [Composing custom error types](#Composing%20custom%20error%20types)
|
||||
* [Advice for library writers](#Advice%20for%20library%20writers)
|
||||
* [Case study: A program to read population data](#Case%20study:%20A%20program%20to%20read%20population%20data)
|
||||
* [Initial setup](#Initial%20setup)
|
||||
* [Argument parsing](#Argument%20parsing)
|
||||
* [Writing the logic](#Writing%20the%20logic)
|
||||
* [Error handling with `Box<Error>`](#Error%20handling%20with%20Box%3CError%3E)
|
||||
* [Reading from stdin](#Reading%20from%20stdin)
|
||||
* [Error handling with a custom type](#Error%20handling%20with%20a%20custom%20type)
|
||||
* [Adding functionality](#Adding%20functionality)
|
||||
* [The short story](#The%20short%20story)
|
||||
* [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
|
||||
|
||||
@ -796,7 +796,7 @@ 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%20Result%20type%20alias%20idiom) described previously. If you
|
||||
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
|
||||
@ -1120,7 +1120,7 @@ returns an `&Error`, which is itself a trait object. We'll revisit the
|
||||
|
||||
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%20your%20own%20error%20type):
|
||||
[previous section](#defining-your-own-error-type):
|
||||
|
||||
```rust
|
||||
use std::io;
|
||||
@ -1493,19 +1493,19 @@ 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%20real%20try%20macro). Implementing the `Error` trait also
|
||||
[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%20custom%20error%20types). For example,
|
||||
[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%20Result%20type%20alias%20idiom), particularly if your
|
||||
[`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).
|
||||
@ -1538,7 +1538,7 @@ and [`rustc-serialize`](https://crates.io/crates/rustc-serialize) crates.
|
||||
|
||||
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%20Cargo) and [Cargo's documentation][14].
|
||||
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:
|
||||
@ -1729,7 +1729,7 @@ 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%20limits%20of%20combinators) we started refactoring our code by
|
||||
[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`?
|
||||
|
@ -680,7 +680,7 @@ pub extern fn hello_rust() -> *const u8 {
|
||||
|
||||
The `extern` makes this function adhere to the C calling convention, as
|
||||
discussed above in "[Foreign Calling
|
||||
Conventions](ffi.html#Foreign%20calling%20conventions)". The `no_mangle`
|
||||
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
|
||||
|
@ -236,7 +236,7 @@ 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%20Language
|
||||
[expression-oriented language]: glossary.html#expression-oriented-language
|
||||
|
||||
## Compiling and Running Are Separate Steps
|
||||
|
||||
|
@ -56,7 +56,7 @@ They can be used to manage control flow in a modular fashion.
|
||||
|
||||
A type without a statically known size or alignment. ([more info][link])
|
||||
|
||||
[link]: ../nomicon/exotic-sizes.html#Dynamically%20Sized%20Types%20(DSTs)
|
||||
[link]: ../nomicon/exotic-sizes.html#dynamically-sized-types-dsts
|
||||
|
||||
### Expression
|
||||
|
||||
@ -76,8 +76,8 @@ 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
|
||||
[expression]: glossary.html#expression
|
||||
[statement]: glossary.html#statement
|
||||
|
||||
### Statement
|
||||
|
||||
|
@ -119,7 +119,7 @@ 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
|
||||
[tuples]: primitive-types.html#tuples
|
||||
|
||||
```rust,ignore
|
||||
println!("Guess the number!");
|
||||
@ -727,7 +727,7 @@ 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%20types
|
||||
[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
|
||||
|
@ -139,7 +139,7 @@ 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%20Elision
|
||||
[lifetime-elision]: #lifetime-elision
|
||||
|
||||
```rust,ignore
|
||||
fn bar<'a>(...)
|
||||
|
@ -430,7 +430,7 @@ Even when Rust code contains un-expanded macros, it can be parsed as a full
|
||||
tools that process code. It also has a few consequences for the design of
|
||||
Rust’s macro system.
|
||||
|
||||
[ast]: glossary.html#Abstract%20Syntax%20Tree
|
||||
[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
|
||||
|
@ -89,7 +89,7 @@ philosophy, memory safety, and the mechanism by which Rust guarantees it, the
|
||||
> * exactly one mutable reference (`&mut T`).
|
||||
|
||||
[ownership]: ownership.html
|
||||
[borrowing]: references-and-borrowing.html#Borrowing
|
||||
[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
|
||||
|
@ -65,10 +65,10 @@ 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
|
||||
[arrays]: primitive-types.html#arrays
|
||||
[vectors]: vectors.html
|
||||
[heap]: the-stack-and-the-heap.html#The%20Heap
|
||||
[stack]: the-stack-and-the-heap.html#The%20Stack
|
||||
[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
|
||||
|
||||
@ -136,7 +136,7 @@ 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%20types
|
||||
[i32]: primitive-types.html#numeric-types
|
||||
|
||||
Now consider the following code fragment:
|
||||
|
||||
|
@ -232,7 +232,7 @@ 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
|
||||
[arity]: glossary.html#arity
|
||||
|
||||
```rust
|
||||
let mut x = (1, 2); // x: (i32, i32)
|
||||
|
@ -196,18 +196,18 @@
|
||||
[Associated Types]: associated-types.html
|
||||
[Attributes]: attributes.html
|
||||
[Casting Between Types (`as`)]: casting-between-types.html#as
|
||||
[Closures (`move` closures)]: closures.html#move%20closures
|
||||
[Closures (`move` closures)]: closures.html#move-closures
|
||||
[Closures]: closures.html
|
||||
[Comments]: comments.html
|
||||
[Crates and Modules (Defining Modules)]: crates-and-modules.html#Defining%20modules
|
||||
[Crates and Modules (Exporting a Public Interface)]: crates-and-modules.html#Exporting%20a%20public%20interface
|
||||
[Crates and Modules (Importing External Crates)]: crates-and-modules.html#Importing%20external%20crates
|
||||
[Crates and Modules (Importing Modules with `use`)]: crates-and-modules.html#Importing%20modules%20with%20use
|
||||
[Crates and Modules (Re-exporting with `pub use`)]: crates-and-modules.html#Re-exporting%20with%20pub%20use
|
||||
[Diverging Functions]: functions.html#Diverging%20functions
|
||||
[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%20returns
|
||||
[Functions (Early Returns)]: functions.html#early-returns
|
||||
[Functions]: functions.html
|
||||
[Generics]: generics.html
|
||||
[Iterators]: iterators.html
|
||||
@ -216,24 +216,24 @@
|
||||
[Loops (`for`)]: loops.html#for
|
||||
[Loops (`loop`)]: loops.html#loop
|
||||
[Loops (`while`)]: loops.html#while
|
||||
[Loops (Ending Iteration Early)]: loops.html#Ending%20iteration%20early
|
||||
[Loops (Loops Labels)]: loops.html#Loop%20labels
|
||||
[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%20calls
|
||||
[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%20and%20ref%20mut
|
||||
[Patterns (Bindings)]: patterns.html#Bindings
|
||||
[Patterns (Ignoring bindings)]: patterns.html#Ignoring%20bindings
|
||||
[Patterns (Multiple patterns)]: patterns.html#Multiple%20patterns
|
||||
[Patterns (Ranges)]: patterns.html#Ranges
|
||||
[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%20indexing
|
||||
[Primitive Types (Tuples)]: primitive-types.html#Tuples
|
||||
[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.html#byte-string-literals
|
||||
[Reference (Integer literals)]: ../reference.html#integer-literals
|
||||
@ -241,13 +241,13 @@
|
||||
[Reference (Raw String Literals)]: ../reference.html#raw-string-literals
|
||||
[References and Borrowing]: references-and-borrowing.html
|
||||
[Strings]: strings.html
|
||||
[Structs (Update syntax)]: structs.html#Update%20syntax
|
||||
[Structs (Update syntax)]: structs.html#update-syntax
|
||||
[Structs]: structs.html
|
||||
[Traits (`where` clause)]: traits.html#Where%20clause
|
||||
[Traits (Multiple Trait Bounds)]: traits.html#Multiple%20trait%20bounds
|
||||
[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%20Form
|
||||
[Universal Function Call Syntax (Angle-bracket Form)]: ufcs.html#angle-bracket-form
|
||||
[Unsafe]: unsafe.html
|
||||
[Unsized Types (`?Sized`)]: unsized-types.html#Sized
|
||||
[Unsized Types (`?Sized`)]: unsized-types.html#sized
|
||||
[Variable Bindings]: variable-bindings.html
|
||||
|
@ -81,7 +81,7 @@ 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
|
||||
[bounds]: glossary.html#bounds
|
||||
|
||||
```rust,ignore
|
||||
fn print_area<T>(shape: T) {
|
||||
|
@ -55,7 +55,7 @@ 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%20structs
|
||||
[tuple struct]: structs.html#tuple-structs
|
||||
|
||||
You can also use type aliases with generics:
|
||||
|
||||
|
@ -151,6 +151,6 @@ API documentation][vec].
|
||||
[vec]: ../std/vec/index.html
|
||||
[box]: ../std/boxed/index.html
|
||||
[generic]: generics.html
|
||||
[panic]: concurrency.html#Panics
|
||||
[panic]: concurrency.html#panics
|
||||
[get]: ../std/vec/struct.Vec.html#method.get
|
||||
[get_mut]: ../std/vec/struct.Vec.html#method.get_mut
|
||||
|
@ -78,4 +78,4 @@ TODO: other common problems? SEME regions stuff, mostly?
|
||||
|
||||
|
||||
|
||||
[ex2]: lifetimes.html#Example%3A%20aliasing%20a%20mutable%20reference
|
||||
[ex2]: lifetimes.html#example-aliasing-a-mutable-reference
|
||||
|
@ -151,4 +151,4 @@ use fairly elaborate algorithms to cache bits throughout nested types with
|
||||
special constrained representations. As such it is *especially* desirable that
|
||||
we leave enum layout unspecified today.
|
||||
|
||||
[dst]: exotic-sizes.html#Dynamically%20Sized%20Types%20(DSTs)
|
||||
[dst]: exotic-sizes.html#dynamically-sized-types-dsts
|
||||
|
@ -2108,7 +2108,7 @@ On `struct`s:
|
||||
list of names `#[macro_use(foo, bar)]` restricts the import to just those
|
||||
macros named. The `extern crate` must appear at the crate root, not inside
|
||||
`mod`, which ensures proper function of the [`$crate` macro
|
||||
variable](book/macros.html#The%20variable%20%24crate).
|
||||
variable](book/macros.html#the-variable-crate).
|
||||
|
||||
- `macro_reexport` on an `extern crate` — re-export the named macros.
|
||||
|
||||
@ -2118,7 +2118,7 @@ On `struct`s:
|
||||
link it into the output.
|
||||
|
||||
See the [macros section of the
|
||||
book](book/macros.html#Scoping%20and%20macro%20import%2Fexport) for more information on
|
||||
book](book/macros.html#scoping-and-macro-importexport) for more information on
|
||||
macro scope.
|
||||
|
||||
|
||||
@ -2277,7 +2277,7 @@ For any lint check `C`:
|
||||
|
||||
The lint checks supported by the compiler can be found via `rustc -W help`,
|
||||
along with their default settings. [Compiler
|
||||
plugins](book/compiler-plugins.html#Lint%20plugins) can provide additional lint checks.
|
||||
plugins](book/compiler-plugins.html#lint-plugins) can provide additional lint checks.
|
||||
|
||||
```{.ignore}
|
||||
pub mod m1 {
|
||||
|
@ -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%20functions
|
||||
/// [assoc]: ../../book/method-syntax.html#associated-functions
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -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%20functions
|
||||
//! [assoc]: ../../book/method-syntax.html#associated-functions
|
||||
//! [mutability]: ../../std/cell/index.html#introducing-mutability-inside-of-something-immutable
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -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%20types),
|
||||
/// [types which implement `Copy`](../../book/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.
|
||||
///
|
||||
|
@ -25,7 +25,7 @@
|
||||
/// Book][moreinfo] contains more details about the precise nature of
|
||||
/// these internals.
|
||||
///
|
||||
/// [moreinfo]: ../../book/trait-objects.html#Representation
|
||||
/// [moreinfo]: ../../book/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
|
||||
|
@ -65,9 +65,6 @@ use super::region_inference::ConcreteFailure;
|
||||
use super::region_inference::SubSupConflict;
|
||||
use super::region_inference::GenericBoundFailure;
|
||||
use super::region_inference::GenericKind;
|
||||
use super::region_inference::ProcessedErrors;
|
||||
use super::region_inference::ProcessedErrorOrigin;
|
||||
use super::region_inference::SameRegions;
|
||||
|
||||
use hir::map as hir_map;
|
||||
use hir;
|
||||
@ -77,11 +74,10 @@ use infer;
|
||||
use middle::region;
|
||||
use traits::{ObligationCause, ObligationCauseCode};
|
||||
use ty::{self, TyCtxt, TypeFoldable};
|
||||
use ty::{Region, ReFree, Issue32330};
|
||||
use ty::{Region, Issue32330};
|
||||
use ty::error::TypeError;
|
||||
|
||||
use std::fmt;
|
||||
use syntax::ast;
|
||||
use syntax_pos::{Pos, Span};
|
||||
use errors::DiagnosticBuilder;
|
||||
|
||||
@ -255,8 +251,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
// try to pre-process the errors, which will group some of them
|
||||
// together into a `ProcessedErrors` group:
|
||||
let processed_errors = self.process_errors(errors);
|
||||
let errors = processed_errors.as_ref().unwrap_or(errors);
|
||||
let errors = self.process_errors(errors);
|
||||
|
||||
debug!("report_region_errors: {} errors after preprocessing", errors.len());
|
||||
|
||||
@ -278,13 +273,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
sub_origin, sub_r,
|
||||
sup_origin, sup_r);
|
||||
}
|
||||
|
||||
ProcessedErrors(ref origins,
|
||||
ref same_regions) => {
|
||||
if !same_regions.is_empty() {
|
||||
self.report_processed_errors(origins);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -300,202 +288,31 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
// duplicates that will be unhelpful to the end-user. But
|
||||
// obviously it never weeds out ALL errors.
|
||||
fn process_errors(&self, errors: &Vec<RegionResolutionError<'tcx>>)
|
||||
-> Option<Vec<RegionResolutionError<'tcx>>> {
|
||||
-> Vec<RegionResolutionError<'tcx>> {
|
||||
debug!("process_errors()");
|
||||
let mut origins = Vec::new();
|
||||
|
||||
// we collect up ConcreteFailures and SubSupConflicts that are
|
||||
// relating free-regions bound on the fn-header and group them
|
||||
// together into this vector
|
||||
let mut same_regions = Vec::new();
|
||||
// We want to avoid reporting generic-bound failures if we can
|
||||
// avoid it: these have a very high rate of being unhelpful in
|
||||
// practice. This is because they are basically secondary
|
||||
// checks that test the state of the region graph after the
|
||||
// rest of inference is done, and the other kinds of errors
|
||||
// indicate that the region constraint graph is internally
|
||||
// inconsistent, so these test results are likely to be
|
||||
// meaningless.
|
||||
//
|
||||
// Therefore, we filter them out of the list unless they are
|
||||
// the only thing in the list.
|
||||
|
||||
// here we put errors that we will not be able to process nicely
|
||||
let mut other_errors = Vec::new();
|
||||
let is_bound_failure = |e: &RegionResolutionError<'tcx>| match *e {
|
||||
ConcreteFailure(..) => false,
|
||||
SubSupConflict(..) => false,
|
||||
GenericBoundFailure(..) => true,
|
||||
};
|
||||
|
||||
// we collect up GenericBoundFailures in here.
|
||||
let mut bound_failures = Vec::new();
|
||||
|
||||
for error in errors {
|
||||
// Check whether we can process this error into some other
|
||||
// form; if not, fall through.
|
||||
match *error {
|
||||
ConcreteFailure(ref origin, sub, sup) => {
|
||||
debug!("processing ConcreteFailure");
|
||||
if let SubregionOrigin::CompareImplMethodObligation { .. } = *origin {
|
||||
// When comparing an impl method against a
|
||||
// trait method, it is not helpful to suggest
|
||||
// changes to the impl method. This is
|
||||
// because the impl method signature is being
|
||||
// checked using the trait's environment, so
|
||||
// usually the changes we suggest would
|
||||
// actually have to be applied to the *trait*
|
||||
// method (and it's not clear that the trait
|
||||
// method is even under the user's control).
|
||||
} else if let Some(same_frs) = free_regions_from_same_fn(self.tcx, sub, sup) {
|
||||
origins.push(
|
||||
ProcessedErrorOrigin::ConcreteFailure(
|
||||
origin.clone(),
|
||||
sub,
|
||||
sup));
|
||||
append_to_same_regions(&mut same_regions, &same_frs);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
SubSupConflict(ref var_origin, ref sub_origin, sub, ref sup_origin, sup) => {
|
||||
debug!("processing SubSupConflict sub: {:?} sup: {:?}", sub, sup);
|
||||
match (sub_origin, sup_origin) {
|
||||
(&SubregionOrigin::CompareImplMethodObligation { .. }, _) => {
|
||||
// As above, when comparing an impl method
|
||||
// against a trait method, it is not helpful
|
||||
// to suggest changes to the impl method.
|
||||
}
|
||||
(_, &SubregionOrigin::CompareImplMethodObligation { .. }) => {
|
||||
// See above.
|
||||
}
|
||||
_ => {
|
||||
if let Some(same_frs) = free_regions_from_same_fn(self.tcx, sub, sup) {
|
||||
origins.push(
|
||||
ProcessedErrorOrigin::VariableFailure(
|
||||
var_origin.clone()));
|
||||
append_to_same_regions(&mut same_regions, &same_frs);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
GenericBoundFailure(ref origin, ref kind, region) => {
|
||||
bound_failures.push((origin.clone(), kind.clone(), region));
|
||||
continue;
|
||||
}
|
||||
ProcessedErrors(..) => {
|
||||
bug!("should not encounter a `ProcessedErrors` yet: {:?}", error)
|
||||
}
|
||||
}
|
||||
|
||||
// No changes to this error.
|
||||
other_errors.push(error.clone());
|
||||
}
|
||||
|
||||
// ok, let's pull together the errors, sorted in an order that
|
||||
// we think will help user the best
|
||||
let mut processed_errors = vec![];
|
||||
|
||||
// first, put the processed errors, if any
|
||||
if !same_regions.is_empty() {
|
||||
let common_scope_id = same_regions[0].scope_id;
|
||||
for sr in &same_regions {
|
||||
// Since ProcessedErrors is used to reconstruct the function
|
||||
// declaration, we want to make sure that they are, in fact,
|
||||
// from the same scope
|
||||
if sr.scope_id != common_scope_id {
|
||||
debug!("returning empty result from process_errors because
|
||||
{} != {}", sr.scope_id, common_scope_id);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
assert!(origins.len() > 0);
|
||||
let pe = ProcessedErrors(origins, same_regions);
|
||||
debug!("errors processed: {:?}", pe);
|
||||
processed_errors.push(pe);
|
||||
}
|
||||
|
||||
// next, put the other misc errors
|
||||
processed_errors.extend(other_errors);
|
||||
|
||||
// finally, put the `T: 'a` errors, but only if there were no
|
||||
// other errors. otherwise, these have a very high rate of
|
||||
// being unhelpful in practice. This is because they are
|
||||
// basically secondary checks that test the state of the
|
||||
// region graph after the rest of inference is done, and the
|
||||
// other kinds of errors indicate that the region constraint
|
||||
// graph is internally inconsistent, so these test results are
|
||||
// likely to be meaningless.
|
||||
if processed_errors.is_empty() {
|
||||
for (origin, kind, region) in bound_failures {
|
||||
processed_errors.push(GenericBoundFailure(origin, kind, region));
|
||||
}
|
||||
}
|
||||
|
||||
// we should always wind up with SOME errors, unless there were no
|
||||
// errors to start
|
||||
assert!(if errors.len() > 0 {processed_errors.len() > 0} else {true});
|
||||
|
||||
return Some(processed_errors);
|
||||
|
||||
#[derive(Debug)]
|
||||
struct FreeRegionsFromSameFn {
|
||||
sub_fr: ty::FreeRegion,
|
||||
sup_fr: ty::FreeRegion,
|
||||
scope_id: ast::NodeId
|
||||
}
|
||||
|
||||
impl FreeRegionsFromSameFn {
|
||||
fn new(sub_fr: ty::FreeRegion,
|
||||
sup_fr: ty::FreeRegion,
|
||||
scope_id: ast::NodeId)
|
||||
-> FreeRegionsFromSameFn {
|
||||
FreeRegionsFromSameFn {
|
||||
sub_fr: sub_fr,
|
||||
sup_fr: sup_fr,
|
||||
scope_id: scope_id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn free_regions_from_same_fn<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
sub: &'tcx Region,
|
||||
sup: &'tcx Region)
|
||||
-> Option<FreeRegionsFromSameFn> {
|
||||
debug!("free_regions_from_same_fn(sub={:?}, sup={:?})", sub, sup);
|
||||
let (scope_id, fr1, fr2) = match (sub, sup) {
|
||||
(&ReFree(fr1), &ReFree(fr2)) => {
|
||||
if fr1.scope != fr2.scope {
|
||||
return None
|
||||
}
|
||||
assert!(fr1.scope == fr2.scope);
|
||||
(fr1.scope.node_id(&tcx.region_maps), fr1, fr2)
|
||||
},
|
||||
_ => return None
|
||||
};
|
||||
let parent = tcx.hir.get_parent(scope_id);
|
||||
let parent_node = tcx.hir.find(parent);
|
||||
match parent_node {
|
||||
Some(node) => match node {
|
||||
hir_map::NodeItem(item) => match item.node {
|
||||
hir::ItemFn(..) => {
|
||||
Some(FreeRegionsFromSameFn::new(fr1, fr2, scope_id))
|
||||
},
|
||||
_ => None
|
||||
},
|
||||
hir_map::NodeImplItem(..) |
|
||||
hir_map::NodeTraitItem(..) => {
|
||||
Some(FreeRegionsFromSameFn::new(fr1, fr2, scope_id))
|
||||
},
|
||||
_ => None
|
||||
},
|
||||
None => {
|
||||
debug!("no parent node of scope_id {}", scope_id);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn append_to_same_regions(same_regions: &mut Vec<SameRegions>,
|
||||
same_frs: &FreeRegionsFromSameFn) {
|
||||
debug!("append_to_same_regions(same_regions={:?}, same_frs={:?})",
|
||||
same_regions, same_frs);
|
||||
let scope_id = same_frs.scope_id;
|
||||
let (sub_fr, sup_fr) = (same_frs.sub_fr, same_frs.sup_fr);
|
||||
for sr in same_regions.iter_mut() {
|
||||
if sr.contains(&sup_fr.bound_region) && scope_id == sr.scope_id {
|
||||
sr.push(sub_fr.bound_region);
|
||||
return
|
||||
}
|
||||
}
|
||||
same_regions.push(SameRegions {
|
||||
scope_id: scope_id,
|
||||
regions: vec![sub_fr.bound_region, sup_fr.bound_region]
|
||||
})
|
||||
if errors.iter().all(|e| is_bound_failure(e)) {
|
||||
errors.clone()
|
||||
} else {
|
||||
errors.iter().filter(|&e| !is_bound_failure(e)).cloned().collect()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1072,20 +889,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
self.note_region_origin(&mut err, &sub_origin);
|
||||
err.emit();
|
||||
}
|
||||
|
||||
fn report_processed_errors(&self,
|
||||
origins: &[ProcessedErrorOrigin<'tcx>]) {
|
||||
for origin in origins.iter() {
|
||||
let mut err = match *origin {
|
||||
ProcessedErrorOrigin::VariableFailure(ref var_origin) =>
|
||||
self.report_inference_failure(var_origin.clone()),
|
||||
ProcessedErrorOrigin::ConcreteFailure(ref sr_origin, sub, sup) =>
|
||||
self.report_concrete_failure(sr_origin.clone(), sub, sup),
|
||||
};
|
||||
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
|
@ -24,7 +24,7 @@ use rustc_data_structures::graph::{self, Direction, NodeIndex, OUTGOING};
|
||||
use rustc_data_structures::unify::{self, UnificationTable};
|
||||
use middle::free_region::FreeRegionMap;
|
||||
use ty::{self, Ty, TyCtxt};
|
||||
use ty::{BoundRegion, Region, RegionVid};
|
||||
use ty::{Region, RegionVid};
|
||||
use ty::{ReEmpty, ReStatic, ReFree, ReEarlyBound, ReErased};
|
||||
use ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh};
|
||||
|
||||
@ -171,13 +171,6 @@ pub enum RegionResolutionError<'tcx> {
|
||||
&'tcx Region,
|
||||
SubregionOrigin<'tcx>,
|
||||
&'tcx Region),
|
||||
|
||||
/// For subsets of `ConcreteFailure` and `SubSupConflict`, we can derive
|
||||
/// more specific errors message by suggesting to the user where they
|
||||
/// should put a lifetime. In those cases we process and put those errors
|
||||
/// into `ProcessedErrors` before we do any reporting.
|
||||
ProcessedErrors(Vec<ProcessedErrorOrigin<'tcx>>,
|
||||
Vec<SameRegions>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@ -186,33 +179,6 @@ pub enum ProcessedErrorOrigin<'tcx> {
|
||||
VariableFailure(RegionVariableOrigin),
|
||||
}
|
||||
|
||||
/// SameRegions is used to group regions that we think are the same and would
|
||||
/// like to indicate so to the user.
|
||||
/// For example, the following function
|
||||
/// ```
|
||||
/// struct Foo { bar: i32 }
|
||||
/// fn foo2<'a, 'b>(x: &'a Foo) -> &'b i32 {
|
||||
/// &x.bar
|
||||
/// }
|
||||
/// ```
|
||||
/// would report an error because we expect 'a and 'b to match, and so we group
|
||||
/// 'a and 'b together inside a SameRegions struct
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SameRegions {
|
||||
pub scope_id: ast::NodeId,
|
||||
pub regions: Vec<BoundRegion>,
|
||||
}
|
||||
|
||||
impl SameRegions {
|
||||
pub fn contains(&self, other: &BoundRegion) -> bool {
|
||||
self.regions.contains(other)
|
||||
}
|
||||
|
||||
pub fn push(&mut self, other: BoundRegion) {
|
||||
self.regions.push(other);
|
||||
}
|
||||
}
|
||||
|
||||
pub type CombineMap<'tcx> = FxHashMap<TwoRegions<'tcx>, RegionVid>;
|
||||
|
||||
pub struct RegionVarBindings<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
|
@ -182,15 +182,15 @@ impl DefaultResizePolicy {
|
||||
// ----------------------
|
||||
// To protect against degenerate performance scenarios (including DOS attacks),
|
||||
// the implementation includes an adaptive behavior that can resize the map
|
||||
// early (before it's capacity is exceeded) when suspiciously long probe or
|
||||
// foward shifts sequences are encounted.
|
||||
// early (before its capacity is exceeded) when suspiciously long probe or
|
||||
// forward shifts sequences are encountered.
|
||||
//
|
||||
// With this algorithm in place it would be possible to turn a CPU attack into
|
||||
// a memory attack due to the agressive resizing. To prevent that the
|
||||
// a memory attack due to the aggressive resizing. To prevent that the
|
||||
// adaptive behavior only triggers when the map occupancy is half the maximum occupancy.
|
||||
// This reduces the effectivenes of the algorithm but also makes it completelly safe.
|
||||
// This reduces the effectiveness of the algorithm but also makes it completely safe.
|
||||
//
|
||||
// The previous safety measure that also prevents degenerate iteractions with
|
||||
// The previous safety measure also prevents degenerate interactions with
|
||||
// really bad quality hash algorithms that can make normal inputs look like a
|
||||
// DOS attack.
|
||||
//
|
||||
|
@ -189,8 +189,8 @@
|
||||
//! [`sync`]: sync/index.html
|
||||
//! [`thread`]: thread/index.html
|
||||
//! [`use std::env`]: env/index.html
|
||||
//! [`use`]: ../book/crates-and-modules.html#Importing%20Modules%20with%20use
|
||||
//! [crate root]: ../book/crates-and-modules.html#Basic%20terminology%3A%20Crates%20and%20Modules
|
||||
//! [`use`]: ../book/crates-and-modules.html#importing-modules-with-use
|
||||
//! [crate root]: ../book/crates-and-modules.html#basic-terminology-crates-and-modules
|
||||
//! [crates.io]: https://crates.io
|
||||
//! [deref coercions]: ../book/deref-coercions.html
|
||||
//! [files]: fs/struct.File.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/primitive-types.html#tuples).
|
||||
///
|
||||
/// # Trait implementations
|
||||
///
|
||||
|
@ -108,9 +108,6 @@ impl Debug for Player {
|
||||
|
||||
fn str_to_direction(to_parse: &str) -> RoomDirection {
|
||||
match to_parse { //~ ERROR match arms have incompatible types
|
||||
//~^ expected enum `RoomDirection`, found enum `std::option::Option`
|
||||
//~| expected type `RoomDirection`
|
||||
//~| found type `std::option::Option<_>`
|
||||
"w" | "west" => RoomDirection::West,
|
||||
"e" | "east" => RoomDirection::East,
|
||||
"n" | "north" => RoomDirection::North,
|
||||
@ -119,7 +116,7 @@ fn str_to_direction(to_parse: &str) -> RoomDirection {
|
||||
"out" => RoomDirection::Out,
|
||||
"up" => RoomDirection::Up,
|
||||
"down" => RoomDirection::Down,
|
||||
_ => None //~ NOTE match arm with an incompatible type
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,9 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum E { V1(isize), V0 }
|
||||
|
||||
const C: &'static [E] = &[E::V0, E::V1(0xDEADBEE)];
|
||||
static C0: E = C[0];
|
||||
static C1: E = C[1];
|
||||
|
@ -0,0 +1,15 @@
|
||||
// Copyright 2016 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<'a>(x: &'a i32, y: &i32) -> &'a i32 {
|
||||
if x > y { x } else { y }
|
||||
}
|
||||
|
||||
fn main() { }
|
@ -0,0 +1,25 @@
|
||||
error[E0312]: lifetime of reference outlives lifetime of borrowed content...
|
||||
--> $DIR/ex1-return-one-existing-name-if-else.rs:12:27
|
||||
|
|
||||
12 | if x > y { x } else { y }
|
||||
| ^
|
||||
|
|
||||
note: ...the reference is valid for the lifetime 'a as defined on the body at 11:43...
|
||||
--> $DIR/ex1-return-one-existing-name-if-else.rs:11:44
|
||||
|
|
||||
11 | fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
|
||||
| ____________________________________________^ starting here...
|
||||
12 | | if x > y { x } else { y }
|
||||
13 | | }
|
||||
| |_^ ...ending here
|
||||
note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the body at 11:43
|
||||
--> $DIR/ex1-return-one-existing-name-if-else.rs:11:44
|
||||
|
|
||||
11 | fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
|
||||
| ____________________________________________^ starting here...
|
||||
12 | | if x > y { x } else { y }
|
||||
13 | | }
|
||||
| |_^ ...ending here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
15
src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.rs
Normal file
15
src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright 2016 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(x: &i32, y: &i32) -> &i32 {
|
||||
if x > y { x } else { y }
|
||||
}
|
||||
|
||||
fn main() { }
|
@ -0,0 +1,10 @@
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/ex1b-return-no-names-if-else.rs:11:29
|
||||
|
|
||||
11 | fn foo(x: &i32, y: &i32) -> &i32 {
|
||||
| ^ expected lifetime parameter
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
19
src/test/ui/lifetime-errors/ex2a-push-one-existing-name.rs
Normal file
19
src/test/ui/lifetime-errors/ex2a-push-one-existing-name.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
struct Ref<'a, T: 'a> {
|
||||
data: &'a T
|
||||
}
|
||||
|
||||
fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
|
||||
x.push(y);
|
||||
}
|
||||
|
||||
fn main() { }
|
@ -0,0 +1,27 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/ex2a-push-one-existing-name.rs:16:12
|
||||
|
|
||||
16 | x.push(y);
|
||||
| ^ lifetime mismatch
|
||||
|
|
||||
= note: expected type `Ref<'a, i32>`
|
||||
found type `Ref<'_, i32>`
|
||||
note: the anonymous lifetime #2 defined on the body at 15:51...
|
||||
--> $DIR/ex2a-push-one-existing-name.rs:15:52
|
||||
|
|
||||
15 | fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
|
||||
| ____________________________________________________^ starting here...
|
||||
16 | | x.push(y);
|
||||
17 | | }
|
||||
| |_^ ...ending here
|
||||
note: ...does not necessarily outlive the lifetime 'a as defined on the body at 15:51
|
||||
--> $DIR/ex2a-push-one-existing-name.rs:15:52
|
||||
|
|
||||
15 | fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
|
||||
| ____________________________________________________^ starting here...
|
||||
16 | | x.push(y);
|
||||
17 | | }
|
||||
| |_^ ...ending here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
19
src/test/ui/lifetime-errors/ex2b-push-no-existing-names.rs
Normal file
19
src/test/ui/lifetime-errors/ex2b-push-no-existing-names.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
struct Ref<'a, T: 'a> {
|
||||
data: &'a T
|
||||
}
|
||||
|
||||
fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
|
||||
x.push(y);
|
||||
}
|
||||
|
||||
fn main() { }
|
@ -0,0 +1,27 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/ex2b-push-no-existing-names.rs:16:12
|
||||
|
|
||||
16 | x.push(y);
|
||||
| ^ lifetime mismatch
|
||||
|
|
||||
= note: expected type `Ref<'_, i32>`
|
||||
found type `Ref<'_, i32>`
|
||||
note: the anonymous lifetime #3 defined on the body at 15:43...
|
||||
--> $DIR/ex2b-push-no-existing-names.rs:15:44
|
||||
|
|
||||
15 | fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
|
||||
| ____________________________________________^ starting here...
|
||||
16 | | x.push(y);
|
||||
17 | | }
|
||||
| |_^ ...ending here
|
||||
note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 15:43
|
||||
--> $DIR/ex2b-push-no-existing-names.rs:15:44
|
||||
|
|
||||
15 | fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
|
||||
| ____________________________________________^ starting here...
|
||||
16 | | x.push(y);
|
||||
17 | | }
|
||||
| |_^ ...ending here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
20
src/test/ui/lifetime-errors/ex2c-push-inference-variable.rs
Normal file
20
src/test/ui/lifetime-errors/ex2c-push-inference-variable.rs
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
struct Ref<'a, T: 'a> {
|
||||
data: &'a T
|
||||
}
|
||||
|
||||
fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
|
||||
let z = Ref { data: y.data };
|
||||
x.push(z);
|
||||
}
|
||||
|
||||
fn main() { }
|
@ -0,0 +1,37 @@
|
||||
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
|
||||
--> $DIR/ex2c-push-inference-variable.rs:16:13
|
||||
|
|
||||
16 | let z = Ref { data: y.data };
|
||||
| ^^^
|
||||
|
|
||||
note: first, the lifetime cannot outlive the lifetime 'c as defined on the body at 15:66...
|
||||
--> $DIR/ex2c-push-inference-variable.rs:15:67
|
||||
|
|
||||
15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
|
||||
| ___________________________________________________________________^ starting here...
|
||||
16 | | let z = Ref { data: y.data };
|
||||
17 | | x.push(z);
|
||||
18 | | }
|
||||
| |_^ ...ending here
|
||||
note: ...so that reference does not outlive borrowed content
|
||||
--> $DIR/ex2c-push-inference-variable.rs:16:25
|
||||
|
|
||||
16 | let z = Ref { data: y.data };
|
||||
| ^^^^^^
|
||||
note: but, the lifetime must be valid for the lifetime 'b as defined on the body at 15:66...
|
||||
--> $DIR/ex2c-push-inference-variable.rs:15:67
|
||||
|
|
||||
15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
|
||||
| ___________________________________________________________________^ starting here...
|
||||
16 | | let z = Ref { data: y.data };
|
||||
17 | | x.push(z);
|
||||
18 | | }
|
||||
| |_^ ...ending here
|
||||
note: ...so that expression is assignable (expected Ref<'b, i32>, found Ref<'_, i32>)
|
||||
--> $DIR/ex2c-push-inference-variable.rs:17:12
|
||||
|
|
||||
17 | x.push(z);
|
||||
| ^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -0,0 +1,21 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
struct Ref<'a, T: 'a> {
|
||||
data: &'a T
|
||||
}
|
||||
|
||||
fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
|
||||
let a: &mut Vec<Ref<i32>> = x;
|
||||
let b = Ref { data: y.data };
|
||||
a.push(b);
|
||||
}
|
||||
|
||||
fn main() { }
|
@ -0,0 +1,39 @@
|
||||
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
|
||||
--> $DIR/ex2d-push-inference-variable-2.rs:17:13
|
||||
|
|
||||
17 | let b = Ref { data: y.data };
|
||||
| ^^^
|
||||
|
|
||||
note: first, the lifetime cannot outlive the lifetime 'c as defined on the body at 15:66...
|
||||
--> $DIR/ex2d-push-inference-variable-2.rs:15:67
|
||||
|
|
||||
15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
|
||||
| ___________________________________________________________________^ starting here...
|
||||
16 | | let a: &mut Vec<Ref<i32>> = x;
|
||||
17 | | let b = Ref { data: y.data };
|
||||
18 | | a.push(b);
|
||||
19 | | }
|
||||
| |_^ ...ending here
|
||||
note: ...so that reference does not outlive borrowed content
|
||||
--> $DIR/ex2d-push-inference-variable-2.rs:17:25
|
||||
|
|
||||
17 | let b = Ref { data: y.data };
|
||||
| ^^^^^^
|
||||
note: but, the lifetime must be valid for the lifetime 'b as defined on the body at 15:66...
|
||||
--> $DIR/ex2d-push-inference-variable-2.rs:15:67
|
||||
|
|
||||
15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
|
||||
| ___________________________________________________________________^ starting here...
|
||||
16 | | let a: &mut Vec<Ref<i32>> = x;
|
||||
17 | | let b = Ref { data: y.data };
|
||||
18 | | a.push(b);
|
||||
19 | | }
|
||||
| |_^ ...ending here
|
||||
note: ...so that expression is assignable (expected &mut std::vec::Vec<Ref<'_, i32>>, found &mut std::vec::Vec<Ref<'b, i32>>)
|
||||
--> $DIR/ex2d-push-inference-variable-2.rs:16:33
|
||||
|
|
||||
16 | let a: &mut Vec<Ref<i32>> = x;
|
||||
| ^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -0,0 +1,21 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
struct Ref<'a, T: 'a> {
|
||||
data: &'a T
|
||||
}
|
||||
|
||||
fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
|
||||
let a: &mut Vec<Ref<i32>> = x;
|
||||
let b = Ref { data: y.data };
|
||||
Vec::push(a, b);
|
||||
}
|
||||
|
||||
fn main() { }
|
@ -0,0 +1,39 @@
|
||||
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
|
||||
--> $DIR/ex2e-push-inference-variable-3.rs:17:13
|
||||
|
|
||||
17 | let b = Ref { data: y.data };
|
||||
| ^^^
|
||||
|
|
||||
note: first, the lifetime cannot outlive the lifetime 'c as defined on the body at 15:66...
|
||||
--> $DIR/ex2e-push-inference-variable-3.rs:15:67
|
||||
|
|
||||
15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
|
||||
| ___________________________________________________________________^ starting here...
|
||||
16 | | let a: &mut Vec<Ref<i32>> = x;
|
||||
17 | | let b = Ref { data: y.data };
|
||||
18 | | Vec::push(a, b);
|
||||
19 | | }
|
||||
| |_^ ...ending here
|
||||
note: ...so that reference does not outlive borrowed content
|
||||
--> $DIR/ex2e-push-inference-variable-3.rs:17:25
|
||||
|
|
||||
17 | let b = Ref { data: y.data };
|
||||
| ^^^^^^
|
||||
note: but, the lifetime must be valid for the lifetime 'b as defined on the body at 15:66...
|
||||
--> $DIR/ex2e-push-inference-variable-3.rs:15:67
|
||||
|
|
||||
15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
|
||||
| ___________________________________________________________________^ starting here...
|
||||
16 | | let a: &mut Vec<Ref<i32>> = x;
|
||||
17 | | let b = Ref { data: y.data };
|
||||
18 | | Vec::push(a, b);
|
||||
19 | | }
|
||||
| |_^ ...ending here
|
||||
note: ...so that expression is assignable (expected &mut std::vec::Vec<Ref<'_, i32>>, found &mut std::vec::Vec<Ref<'b, i32>>)
|
||||
--> $DIR/ex2e-push-inference-variable-3.rs:16:33
|
||||
|
|
||||
16 | let a: &mut Vec<Ref<i32>> = x;
|
||||
| ^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -65,6 +65,7 @@ enum Redirect {
|
||||
struct FileEntry {
|
||||
source: String,
|
||||
ids: HashSet<String>,
|
||||
names: HashSet<String>,
|
||||
}
|
||||
|
||||
type Cache = HashMap<PathBuf, FileEntry>;
|
||||
@ -81,6 +82,15 @@ impl FileEntry {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_names(&mut self, contents: &str) {
|
||||
if self.names.is_empty() {
|
||||
with_attrs_in_source(contents, " name", |fragment, _| {
|
||||
let frag = fragment.trim_left_matches("#").to_owned();
|
||||
self.names.insert(frag);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn walk(cache: &mut Cache, root: &Path, dir: &Path, errors: &mut bool) {
|
||||
@ -139,6 +149,9 @@ fn check(cache: &mut Cache,
|
||||
cache.get_mut(&pretty_file)
|
||||
.unwrap()
|
||||
.parse_ids(&pretty_file, &contents, errors);
|
||||
cache.get_mut(&pretty_file)
|
||||
.unwrap()
|
||||
.parse_names(&contents);
|
||||
}
|
||||
|
||||
// Search for anything that's the regex 'href[ ]*=[ ]*".*?"'
|
||||
@ -209,13 +222,6 @@ fn check(cache: &mut Cache,
|
||||
Err(LoadError::IsRedirect) => unreachable!(),
|
||||
};
|
||||
|
||||
// we don't check the book for fragments because they're added via JS
|
||||
for book in ["book/", "nomicon/"].iter() {
|
||||
if !pretty_path.to_str().unwrap().starts_with(book) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref fragment) = fragment {
|
||||
// Fragments like `#1-6` are most likely line numbers to be
|
||||
// interpreted by javascript, so we're ignoring these
|
||||
@ -226,8 +232,9 @@ fn check(cache: &mut Cache,
|
||||
|
||||
let entry = &mut cache.get_mut(&pretty_path).unwrap();
|
||||
entry.parse_ids(&pretty_path, &contents, errors);
|
||||
entry.parse_names(&contents);
|
||||
|
||||
if !entry.ids.contains(*fragment) {
|
||||
if !(entry.ids.contains(*fragment) || entry.names.contains(*fragment)) {
|
||||
*errors = true;
|
||||
print!("{}:{}: broken link fragment ",
|
||||
pretty_file.display(),
|
||||
@ -277,6 +284,7 @@ fn load_file(cache: &mut Cache,
|
||||
entry.insert(FileEntry {
|
||||
source: contents.clone(),
|
||||
ids: HashSet::new(),
|
||||
names: HashSet::new(),
|
||||
});
|
||||
}
|
||||
maybe
|
||||
|
@ -8,5 +8,5 @@ license = "MIT/Apache-2.0"
|
||||
clap = "2.19.3"
|
||||
|
||||
[dependencies.mdbook]
|
||||
version = "0.0.15"
|
||||
version = "0.0.16"
|
||||
default-features = false
|
||||
|
Loading…
Reference in New Issue
Block a user