Auto merge of #30800 - steveklabnik:rollup, r=steveklabnik
- Successful merges: #30766, #30771, #30789 - Failed merges:
This commit is contained in:
commit
0672ed4e82
|
@ -24,7 +24,7 @@ fn distance<N, E, G: Graph<N, E>>(graph: &G, start: &N, end: &N) -> u32 { ... }
|
|||
```
|
||||
|
||||
Our distance calculation works regardless of our `Edge` type, so the `E` stuff in
|
||||
this signature is just a distraction.
|
||||
this signature is a distraction.
|
||||
|
||||
What we really want to say is that a certain `E`dge and `N`ode type come together
|
||||
to form each kind of `Graph`. We can do that with associated types:
|
||||
|
@ -118,10 +118,10 @@ impl Graph for MyGraph {
|
|||
This silly implementation always returns `true` and an empty `Vec<Edge>`, but it
|
||||
gives you an idea of how to implement this kind of thing. We first need three
|
||||
`struct`s, one for the graph, one for the node, and one for the edge. If it made
|
||||
more sense to use a different type, that would work as well, we’re just going to
|
||||
more sense to use a different type, that would work as well, we’re going to
|
||||
use `struct`s for all three here.
|
||||
|
||||
Next is the `impl` line, which is just like implementing any other trait.
|
||||
Next is the `impl` line, which is an implementation like any other trait.
|
||||
|
||||
From here, we use `=` to define our associated types. The name the trait uses
|
||||
goes on the left of the `=`, and the concrete type we’re `impl`ementing this
|
||||
|
|
|
@ -154,7 +154,7 @@ implemented. For this, we need something more dangerous.
|
|||
The `transmute` function is provided by a [compiler intrinsic][intrinsics], and
|
||||
what it does is very simple, but very scary. It tells Rust to treat a value of
|
||||
one type as though it were another type. It does this regardless of the
|
||||
typechecking system, and just completely trusts you.
|
||||
typechecking system, and completely trusts you.
|
||||
|
||||
[intrinsics]: intrinsics.html
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ These pointers cannot be copied in such a way that they outlive the lifetime ass
|
|||
|
||||
## `*const T` and `*mut T`
|
||||
|
||||
These are C-like raw pointers with no lifetime or ownership attached to them. They just point to
|
||||
These are C-like raw pointers with no lifetime or ownership attached to them. They point to
|
||||
some location in memory with no other restrictions. The only guarantee that these provide is that
|
||||
they cannot be dereferenced except in code marked `unsafe`.
|
||||
|
||||
|
@ -255,7 +255,7 @@ major ones will be covered below.
|
|||
|
||||
## `Arc<T>`
|
||||
|
||||
[`Arc<T>`][arc] is just a version of `Rc<T>` that uses an atomic reference count (hence, "Arc").
|
||||
[`Arc<T>`][arc] is a version of `Rc<T>` that uses an atomic reference count (hence, "Arc").
|
||||
This can be sent freely between threads.
|
||||
|
||||
C++'s `shared_ptr` is similar to `Arc`, however in the case of C++ the inner data is always mutable.
|
||||
|
|
|
@ -253,7 +253,7 @@ use it.
|
|||
# Taking closures as arguments
|
||||
|
||||
Now that we know that closures are traits, we already know how to accept and
|
||||
return closures: just like any other trait!
|
||||
return closures: the same as any other trait!
|
||||
|
||||
This also means that we can choose static vs dynamic dispatch as well. First,
|
||||
let’s write a function which takes something callable, calls it, and returns
|
||||
|
@ -271,7 +271,7 @@ let answer = call_with_one(|x| x + 2);
|
|||
assert_eq!(3, answer);
|
||||
```
|
||||
|
||||
We pass our closure, `|x| x + 2`, to `call_with_one`. It just does what it
|
||||
We pass our closure, `|x| x + 2`, to `call_with_one`. It does what it
|
||||
suggests: it calls the closure, giving it `1` as an argument.
|
||||
|
||||
Let’s examine the signature of `call_with_one` in more depth:
|
||||
|
@ -448,7 +448,7 @@ This error is letting us know that we don’t have a `&'static Fn(i32) -> i32`,
|
|||
we have a `[closure@<anon>:7:9: 7:20]`. Wait, what?
|
||||
|
||||
Because each closure generates its own environment `struct` and implementation
|
||||
of `Fn` and friends, these types are anonymous. They exist just solely for
|
||||
of `Fn` and friends, these types are anonymous. They exist solely for
|
||||
this closure. So Rust shows them as `closure@<anon>`, rather than some
|
||||
autogenerated name.
|
||||
|
||||
|
|
|
@ -305,10 +305,10 @@ fn main() {
|
|||
}
|
||||
```
|
||||
|
||||
We use the `mpsc::channel()` method to construct a new channel. We just `send`
|
||||
We use the `mpsc::channel()` method to construct a new channel. We `send`
|
||||
a simple `()` down the channel, and then wait for ten of them to come back.
|
||||
|
||||
While this channel is just sending a generic signal, we can send any data that
|
||||
While this channel is sending a generic signal, we can send any data that
|
||||
is `Send` over the channel!
|
||||
|
||||
```rust
|
||||
|
|
|
@ -222,7 +222,7 @@ fn hello() -> String {
|
|||
}
|
||||
```
|
||||
|
||||
Of course, you can copy and paste this from this web page, or just type
|
||||
Of course, you can copy and paste this from this web page, or type
|
||||
something else. It’s not important that you actually put ‘konnichiwa’ to learn
|
||||
about the module system.
|
||||
|
||||
|
@ -299,7 +299,7 @@ depth.
|
|||
Rust allows you to precisely control which aspects of your interface are
|
||||
public, and so private is the default. To make things public, you use the `pub`
|
||||
keyword. Let’s focus on the `english` module first, so let’s reduce our `src/main.rs`
|
||||
to just this:
|
||||
to only this:
|
||||
|
||||
```rust,ignore
|
||||
extern crate phrases;
|
||||
|
@ -447,7 +447,7 @@ use phrases::english::{greetings, farewells};
|
|||
|
||||
## Re-exporting with `pub use`
|
||||
|
||||
You don’t just use `use` to shorten identifiers. You can also use it inside of your crate
|
||||
You don’t only use `use` to shorten identifiers. You can also use it inside of your crate
|
||||
to re-export a function inside another module. This allows you to present an external
|
||||
interface that may not directly map to your internal code organization.
|
||||
|
||||
|
@ -584,5 +584,5 @@ use sayings::english::farewells as en_farewells;
|
|||
```
|
||||
|
||||
As you can see, the curly brackets compress `use` statements for several items
|
||||
under the same path, and in this context `self` just refers back to that path.
|
||||
under the same path, and in this context `self` refers back to that path.
|
||||
Note: The curly brackets cannot be nested or mixed with star globbing.
|
||||
|
|
|
@ -13,7 +13,7 @@ own allocator up and running.
|
|||
|
||||
The compiler currently ships two default allocators: `alloc_system` and
|
||||
`alloc_jemalloc` (some targets don't have jemalloc, however). These allocators
|
||||
are just normal Rust crates and contain an implementation of the routines to
|
||||
are normal Rust crates and contain an implementation of the routines to
|
||||
allocate and deallocate memory. The standard library is not compiled assuming
|
||||
either one, and the compiler will decide which allocator is in use at
|
||||
compile-time depending on the type of output artifact being produced.
|
||||
|
@ -134,7 +134,7 @@ pub extern fn __rust_usable_size(size: usize, _align: usize) -> usize {
|
|||
size
|
||||
}
|
||||
|
||||
# // just needed to get rustdoc to test this
|
||||
# // only needed to get rustdoc to test this
|
||||
# fn main() {}
|
||||
# #[lang = "panic_fmt"] fn panic_fmt() {}
|
||||
# #[lang = "eh_personality"] fn eh_personality() {}
|
||||
|
|
|
@ -193,7 +193,7 @@ If you want something that's not Rust code, you can add an annotation:
|
|||
```
|
||||
|
||||
This will highlight according to whatever language you're showing off.
|
||||
If you're just showing plain text, choose `text`.
|
||||
If you're only showing plain text, choose `text`.
|
||||
|
||||
It's important to choose the correct annotation here, because `rustdoc` uses it
|
||||
in an interesting way: It can be used to actually test your examples in a
|
||||
|
@ -273,7 +273,7 @@ be hidden from the output, but will be used when compiling your code. You
|
|||
can use this to your advantage. In this case, documentation comments need
|
||||
to apply to some kind of function, so if I want to show you just a
|
||||
documentation comment, I need to add a little function definition below
|
||||
it. At the same time, it's just there to satisfy the compiler, so hiding
|
||||
it. At the same time, it's only there to satisfy the compiler, so hiding
|
||||
it makes the example more clear. You can use this technique to explain
|
||||
longer examples in detail, while still preserving the testability of your
|
||||
documentation.
|
||||
|
@ -512,7 +512,7 @@ the documentation with comments. For example:
|
|||
# fn foo() {}
|
||||
```
|
||||
|
||||
is just
|
||||
is:
|
||||
|
||||
~~~markdown
|
||||
# Examples
|
||||
|
|
|
@ -62,7 +62,6 @@ learn in the next section. We don’t know enough about Rust to implement
|
|||
equality yet, but we’ll find out in the [`traits`][traits] section.
|
||||
|
||||
[match]: match.html
|
||||
[if-let]: if-let.html
|
||||
[traits]: traits.html
|
||||
|
||||
# Constructors as functions
|
||||
|
|
|
@ -117,8 +117,8 @@ the first example. This is because the
|
|||
panic is embedded in the calls to `unwrap`.
|
||||
|
||||
To “unwrap” something in Rust is to say, “Give me the result of the
|
||||
computation, and if there was an error, just panic and stop the program.”
|
||||
It would be better if we just showed the code for unwrapping because it is so
|
||||
computation, and if there was an error, panic and stop the program.”
|
||||
It would be better if we showed the code for unwrapping because it is so
|
||||
simple, but to do that, we will first need to explore the `Option` and `Result`
|
||||
types. Both of these types have a method called `unwrap` defined on them.
|
||||
|
||||
|
@ -154,7 +154,7 @@ fn find(haystack: &str, needle: char) -> Option<usize> {
|
|||
}
|
||||
```
|
||||
|
||||
Notice that when this function finds a matching character, it doesn't just
|
||||
Notice that when this function finds a matching character, it doesn't only
|
||||
return the `offset`. Instead, it returns `Some(offset)`. `Some` is a variant or
|
||||
a *value constructor* for the `Option` type. You can think of it as a function
|
||||
with the type `fn<T>(value: T) -> Option<T>`. Correspondingly, `None` is also a
|
||||
|
@ -216,7 +216,7 @@ we saw how to use `find` to discover the extension in a file name. Of course,
|
|||
not all file names have a `.` in them, so it's possible that the file name has
|
||||
no extension. This *possibility of absence* is encoded into the types using
|
||||
`Option<T>`. In other words, the compiler will force us to address the
|
||||
possibility that an extension does not exist. In our case, we just print out a
|
||||
possibility that an extension does not exist. In our case, we only print out a
|
||||
message saying as such.
|
||||
|
||||
Getting the extension of a file name is a pretty common operation, so it makes
|
||||
|
@ -248,7 +248,7 @@ tiresome.
|
|||
|
||||
In fact, the case analysis in `extension_explicit` follows a very common
|
||||
pattern: *map* a function on to the value inside of an `Option<T>`, unless the
|
||||
option is `None`, in which case, just return `None`.
|
||||
option is `None`, in which case, return `None`.
|
||||
|
||||
Rust has parametric polymorphism, so it is very easy to define a combinator
|
||||
that abstracts this pattern:
|
||||
|
@ -350,7 +350,7 @@ fn file_name(file_path: &str) -> Option<&str> {
|
|||
}
|
||||
```
|
||||
|
||||
You might think that we could just use the `map` combinator to reduce the case
|
||||
You might think that we could use the `map` combinator to reduce the case
|
||||
analysis, but its type doesn't quite fit. Namely, `map` takes a function that
|
||||
does something only with the inner value. The result of that function is then
|
||||
*always* [rewrapped with `Some`](#code-option-map). Instead, we need something
|
||||
|
@ -670,7 +670,7 @@ The tricky aspect here is that `argv.nth(1)` produces an `Option` while
|
|||
with both an `Option` and a `Result`, the solution is *usually* to convert the
|
||||
`Option` to a `Result`. In our case, the absence of a command line parameter
|
||||
(from `env::args()`) means the user didn't invoke the program correctly. We
|
||||
could just use a `String` to describe the error. Let's try:
|
||||
could use a `String` to describe the error. Let's try:
|
||||
|
||||
<span id="code-error-double-string"></span>
|
||||
|
||||
|
@ -709,7 +709,7 @@ fn ok_or<T, E>(option: Option<T>, err: E) -> Result<T, E> {
|
|||
|
||||
The other new combinator used here is
|
||||
[`Result::map_err`](../std/result/enum.Result.html#method.map_err).
|
||||
This is just like `Result::map`, except it maps a function on to the *error*
|
||||
This is like `Result::map`, except it maps a function on to the *error*
|
||||
portion of a `Result` value. If the `Result` is an `Ok(...)` value, then it is
|
||||
returned unmodified.
|
||||
|
||||
|
@ -841,7 +841,7 @@ example, the very last call to `map` multiplies the `Ok(...)` value (which is
|
|||
an `i32`) by `2`. If an error had occurred before that point, this operation
|
||||
would have been skipped because of how `map` is defined.
|
||||
|
||||
`map_err` is the trick that makes all of this work. `map_err` is just like
|
||||
`map_err` is the trick that makes all of this work. `map_err` is like
|
||||
`map`, except it applies a function to the `Err(...)` value of a `Result`. In
|
||||
this case, we want to convert all of our errors to one type: `String`. Since
|
||||
both `io::Error` and `num::ParseIntError` implement `ToString`, we can call the
|
||||
|
@ -901,7 +901,7 @@ reduce explicit case analysis. Combinators aren't the only way.
|
|||
## The `try!` macro
|
||||
|
||||
A cornerstone of error handling in Rust is the `try!` macro. The `try!` macro
|
||||
abstracts case analysis just like combinators, but unlike combinators, it also
|
||||
abstracts case analysis like combinators, but unlike combinators, it also
|
||||
abstracts *control flow*. Namely, it can abstract the *early return* pattern
|
||||
seen above.
|
||||
|
||||
|
@ -1461,7 +1461,7 @@ expose its representation (like
|
|||
[`ErrorKind`](../std/io/enum.ErrorKind.html)) or keep it hidden (like
|
||||
[`ParseIntError`](../std/num/struct.ParseIntError.html)). Regardless
|
||||
of how you do it, it's usually good practice to at least provide some
|
||||
information about the error beyond just its `String`
|
||||
information about the error beyond its `String`
|
||||
representation. But certainly, this will vary depending on use cases.
|
||||
|
||||
At a minimum, you should probably implement the
|
||||
|
@ -1499,7 +1499,7 @@ that can go wrong!
|
|||
The data we'll be using comes from the [Data Science
|
||||
Toolkit][11]. I've prepared some data from it for this exercise. You
|
||||
can either grab the [world population data][12] (41MB gzip compressed,
|
||||
145MB uncompressed) or just the [US population data][13] (2.2MB gzip
|
||||
145MB uncompressed) or only the [US population data][13] (2.2MB gzip
|
||||
compressed, 7.2MB uncompressed).
|
||||
|
||||
Up until now, we've kept the code limited to Rust's standard library. For a real
|
||||
|
@ -1706,7 +1706,7 @@ compiler can no longer reason about its underlying type.
|
|||
|
||||
[Previously](#the-limits-of-combinators) we started refactoring our code by
|
||||
changing the type of our function from `T` to `Result<T, OurErrorType>`. In
|
||||
this case, `OurErrorType` is just `Box<Error>`. But what's `T`? And can we add
|
||||
this case, `OurErrorType` is only `Box<Error>`. But what's `T`? And can we add
|
||||
a return type to `main`?
|
||||
|
||||
The answer to the second question is no, we can't. That means we'll need to
|
||||
|
@ -1924,7 +1924,7 @@ parser out of
|
|||
But how can we use the same code over both types? There's actually a
|
||||
couple ways we could go about this. One way is to write `search` such
|
||||
that it is generic on some type parameter `R` that satisfies
|
||||
`io::Read`. Another way is to just use trait objects:
|
||||
`io::Read`. Another way is to use trait objects:
|
||||
|
||||
```rust,ignore
|
||||
fn search<P: AsRef<Path>>
|
||||
|
@ -2081,7 +2081,7 @@ opts.optflag("q", "quiet", "Silences errors and warnings.");
|
|||
...
|
||||
```
|
||||
|
||||
Now we just need to implement our “quiet” functionality. This requires us to
|
||||
Now we only need to implement our “quiet” functionality. This requires us to
|
||||
tweak the case analysis in `main`:
|
||||
|
||||
```rust,ignore
|
||||
|
@ -2114,7 +2114,7 @@ handling in Rust. These are some good “rules of thumb." They are emphatically
|
|||
heuristics!
|
||||
|
||||
* If you're writing short example code that would be overburdened by error
|
||||
handling, it's probably just fine to use `unwrap` (whether that's
|
||||
handling, it's probably fine to use `unwrap` (whether that's
|
||||
[`Result::unwrap`](../std/result/enum.Result.html#method.unwrap),
|
||||
[`Option::unwrap`](../std/option/enum.Option.html#method.unwrap)
|
||||
or preferably
|
||||
|
|
|
@ -367,7 +367,7 @@ artifact.
|
|||
A few examples of how this model can be used are:
|
||||
|
||||
* A native build dependency. Sometimes some C/C++ glue is needed when writing
|
||||
some Rust code, but distribution of the C/C++ code in a library format is just
|
||||
some Rust code, but distribution of the C/C++ code in a library format is
|
||||
a burden. In this case, the code will be archived into `libfoo.a` and then the
|
||||
Rust crate would declare a dependency via `#[link(name = "foo", kind =
|
||||
"static")]`.
|
||||
|
@ -490,7 +490,7 @@ interoperating with the target's libraries. For example, on win32 with a x86
|
|||
architecture, this means that the abi used would be `stdcall`. On x86_64,
|
||||
however, windows uses the `C` calling convention, so `C` would be used. This
|
||||
means that in our previous example, we could have used `extern "system" { ... }`
|
||||
to define a block for all windows systems, not just x86 ones.
|
||||
to define a block for all windows systems, not only x86 ones.
|
||||
|
||||
# Interoperability with foreign code
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ statement `x + 1;` doesn’t return a value. There are two kinds of statements i
|
|||
Rust: ‘declaration statements’ and ‘expression statements’. Everything else is
|
||||
an expression. Let’s talk about declaration statements first.
|
||||
|
||||
In some languages, variable bindings can be written as expressions, not just
|
||||
In some languages, variable bindings can be written as expressions, not
|
||||
statements. Like Ruby:
|
||||
|
||||
```ruby
|
||||
|
@ -145,7 +145,7 @@ Note that assigning to an already-bound variable (e.g. `y = 5`) is still an
|
|||
expression, although its value is not particularly useful. Unlike other
|
||||
languages where an assignment evaluates to the assigned value (e.g. `5` in the
|
||||
previous example), in Rust the value of an assignment is an empty tuple `()`
|
||||
because the assigned value can have [just one owner](ownership.html), and any
|
||||
because the assigned value can have [only one owner](ownership.html), and any
|
||||
other returned value would be too surprising:
|
||||
|
||||
```rust
|
||||
|
|
|
@ -37,7 +37,7 @@ let x: Option<f64> = Some(5);
|
|||
// found `core::option::Option<_>` (expected f64 but found integral variable)
|
||||
```
|
||||
|
||||
That doesn’t mean we can’t make `Option<T>`s that hold an `f64`! They just have
|
||||
That doesn’t mean we can’t make `Option<T>`s that hold an `f64`! They have
|
||||
to match up:
|
||||
|
||||
```rust
|
||||
|
@ -118,7 +118,7 @@ let float_origin = Point { x: 0.0, y: 0.0 };
|
|||
Similar to functions, the `<T>` is where we declare the generic parameters,
|
||||
and we then use `x: T` in the type declaration, too.
|
||||
|
||||
When you want to add an implementation for the generic `struct`, you just
|
||||
When you want to add an implementation for the generic `struct`, you
|
||||
declare the type parameter after the `impl`:
|
||||
|
||||
```rust
|
||||
|
|
|
@ -140,7 +140,7 @@ If you're on Windows, please download the appropriate [installer][install-page].
|
|||
|
||||
## Uninstalling
|
||||
|
||||
Uninstalling Rust is as easy as installing it. On Linux or Mac, just run
|
||||
Uninstalling Rust is as easy as installing it. On Linux or Mac, run
|
||||
the uninstall script:
|
||||
|
||||
```bash
|
||||
|
@ -192,7 +192,7 @@ that tradition.
|
|||
|
||||
The nice thing about starting with such a simple program is that you can
|
||||
quickly verify that your compiler is installed, and that it's working properly.
|
||||
Printing information to the screen is also just a pretty common thing to do, so
|
||||
Printing information to the screen is also a pretty common thing to do, so
|
||||
practicing it early on is good.
|
||||
|
||||
> Note: This book assumes basic familiarity with the command line. Rust itself
|
||||
|
@ -248,7 +248,7 @@ $ ./main
|
|||
Hello, world!
|
||||
```
|
||||
|
||||
In Windows, just replace `main` with `main.exe`. Regardless of your operating
|
||||
In Windows, replace `main` with `main.exe`. Regardless of your operating
|
||||
system, you should see the string `Hello, world!` print to the terminal. If you
|
||||
did, then congratulations! You've officially written a Rust program. That makes
|
||||
you a Rust programmer! Welcome.
|
||||
|
@ -289,7 +289,7 @@ that it’s indented with four spaces, not tabs.
|
|||
The second important part is the `println!()` line. This is calling a Rust
|
||||
*[macro]*, which is how metaprogramming is done in Rust. If it were calling a
|
||||
function instead, it would look like this: `println()` (without the !). We'll
|
||||
discuss Rust macros in more detail later, but for now you just need to
|
||||
discuss Rust macros in more detail later, but for now you only need to
|
||||
know that when you see a `!` that means that you’re calling a macro instead of
|
||||
a normal function.
|
||||
|
||||
|
@ -456,7 +456,7 @@ authors = [ "Your name <you@example.com>" ]
|
|||
|
||||
The first line, `[package]`, indicates that the following statements are
|
||||
configuring a package. As we add more information to this file, we’ll add other
|
||||
sections, but for now, we just have the package configuration.
|
||||
sections, but for now, we only have the package configuration.
|
||||
|
||||
The other three lines set the three bits of configuration that Cargo needs to
|
||||
know to compile your program: its name, what version it is, and who wrote it.
|
||||
|
@ -507,7 +507,7 @@ rebuilds your project if they’ve changed since the last time you built it.
|
|||
With simple projects, Cargo doesn't bring a whole lot over just using `rustc`,
|
||||
but it will become useful in future. With complex projects composed of multiple
|
||||
crates, it’s much easier to let Cargo coordinate the build. With Cargo, you can
|
||||
just run `cargo build`, and it should work the right way.
|
||||
run `cargo build`, and it should work the right way.
|
||||
|
||||
## Building for Release
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ Hello, world!
|
|||
```
|
||||
|
||||
Great! The `run` command comes in handy when you need to rapidly iterate on a
|
||||
project. Our game is just such a project, we need to quickly test each
|
||||
project. Our game is such a project, we need to quickly test each
|
||||
iteration before moving on to the next one.
|
||||
|
||||
# Processing a Guess
|
||||
|
@ -294,12 +294,12 @@ src/main.rs:10 io::stdin().read_line(&mut guess);
|
|||
Rust warns us that we haven’t used the `Result` value. This warning comes from
|
||||
a special annotation that `io::Result` has. Rust is trying to tell you that
|
||||
you haven’t handled a possible error. The right way to suppress the error is
|
||||
to actually write error handling. Luckily, if we just want to crash if there’s
|
||||
to actually write error handling. Luckily, if we want to crash if there’s
|
||||
a problem, we can use these two little methods. If we can recover from the
|
||||
error somehow, we’d do something else, but we’ll save that for a future
|
||||
project.
|
||||
|
||||
There’s just one line of this first example left:
|
||||
There’s only one line of this first example left:
|
||||
|
||||
```rust,ignore
|
||||
println!("You guessed: {}", guess);
|
||||
|
@ -408,7 +408,7 @@ $ cargo build
|
|||
That’s right, no output! Cargo knows that our project has been built, and that
|
||||
all of its dependencies are built, and so there’s no reason to do all that
|
||||
stuff. With nothing to do, it simply exits. If we open up `src/main.rs` again,
|
||||
make a trivial change, and then save it again, we’ll just see one line:
|
||||
make a trivial change, and then save it again, we’ll only see one line:
|
||||
|
||||
```bash
|
||||
$ cargo build
|
||||
|
@ -504,7 +504,7 @@ so we need `1` and `101` to get a number ranging from one to a hundred.
|
|||
|
||||
[concurrency]: concurrency.html
|
||||
|
||||
The second line just prints out the secret number. This is useful while
|
||||
The second line prints out the secret number. This is useful while
|
||||
we’re developing our program, so we can easily test it out. But we’ll be
|
||||
deleting it for the final version. It’s not much of a game if it prints out
|
||||
the answer when you start it up!
|
||||
|
@ -705,7 +705,7 @@ input in it. The `trim()` method on `String`s will eliminate any white space at
|
|||
the beginning and end of our string. This is important, as we had to press the
|
||||
‘return’ key to satisfy `read_line()`. This means that if we type `5` and hit
|
||||
return, `guess` looks like this: `5\n`. The `\n` represents ‘newline’, the
|
||||
enter key. `trim()` gets rid of this, leaving our string with just the `5`. The
|
||||
enter key. `trim()` gets rid of this, leaving our string with only the `5`. The
|
||||
[`parse()` method on strings][parse] parses a string into some kind of number.
|
||||
Since it can parse a variety of numbers, we need to give Rust a hint as to the
|
||||
exact type of number we want. Hence, `let guess: u32`. The colon (`:`) after
|
||||
|
@ -853,8 +853,8 @@ fn main() {
|
|||
|
||||
By adding the `break` line after the `You win!`, we’ll exit the loop when we
|
||||
win. Exiting the loop also means exiting the program, since it’s the last
|
||||
thing in `main()`. We have just one more tweak to make: when someone inputs a
|
||||
non-number, we don’t want to quit, we just want to ignore it. We can do that
|
||||
thing in `main()`. We have only one more tweak to make: when someone inputs a
|
||||
non-number, we don’t want to quit, we want to ignore it. We can do that
|
||||
like this:
|
||||
|
||||
```rust,ignore
|
||||
|
@ -908,12 +908,12 @@ let guess: u32 = match guess.trim().parse() {
|
|||
```
|
||||
|
||||
This is how you generally move from ‘crash on error’ to ‘actually handle the
|
||||
returned by `parse()` is an `enum` just like `Ordering`, but in this case, each
|
||||
returned by `parse()` is an `enum` like `Ordering`, but in this case, each
|
||||
variant has some data associated with it: `Ok` is a success, and `Err` is a
|
||||
failure. Each contains more information: the successfully parsed integer, or an
|
||||
error type. In this case, we `match` on `Ok(num)`, which sets the inner value
|
||||
of the `Ok` to the name `num`, and then we just return it on the right-hand
|
||||
side. In the `Err` case, we don’t care what kind of error it is, so we just
|
||||
of the `Ok` to the name `num`, and then we return it on the right-hand
|
||||
side. In the `Err` case, we don’t care what kind of error it is, so we
|
||||
use `_` instead of a name. This ignores the error, and `continue` causes us
|
||||
to go to the next iteration of the `loop`.
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ which gives us a reference to the next value of the iterator. `next` returns an
|
|||
`None`, we `break` out of the loop.
|
||||
|
||||
This code sample is basically the same as our `for` loop version. The `for`
|
||||
loop is just a handy way to write this `loop`/`match`/`break` construct.
|
||||
loop is a handy way to write this `loop`/`match`/`break` construct.
|
||||
|
||||
`for` loops aren't the only thing that uses iterators, however. Writing your
|
||||
own iterator involves implementing the `Iterator` trait. While doing that is
|
||||
|
@ -94,8 +94,8 @@ Now we're explicitly dereferencing `num`. Why does `&nums` give us
|
|||
references? Firstly, because we explicitly asked it to with
|
||||
`&`. Secondly, if it gave us the data itself, we would have to be its
|
||||
owner, which would involve making a copy of the data and giving us the
|
||||
copy. With references, we're just borrowing a reference to the data,
|
||||
and so it's just passing a reference, without needing to do the move.
|
||||
copy. With references, we're only borrowing a reference to the data,
|
||||
and so it's only passing a reference, without needing to do the move.
|
||||
|
||||
So, now that we've established that ranges are often not what you want, let's
|
||||
talk about what you do want instead.
|
||||
|
@ -278,7 +278,7 @@ doesn't print any numbers:
|
|||
```
|
||||
|
||||
If you are trying to execute a closure on an iterator for its side effects,
|
||||
just use `for` instead.
|
||||
use `for` instead.
|
||||
|
||||
There are tons of interesting iterator adaptors. `take(n)` will return an
|
||||
iterator over the next `n` elements of the original iterator. Let's try it out
|
||||
|
|
|
@ -84,7 +84,7 @@ We previously talked a little about [function syntax][functions], but we didn’
|
|||
discuss the `<>`s after a function’s name. A function can have ‘generic
|
||||
parameters’ between the `<>`s, of which lifetimes are one kind. We’ll discuss
|
||||
other kinds of generics [later in the book][generics], but for now, let’s
|
||||
just focus on the lifetimes aspect.
|
||||
focus on the lifetimes aspect.
|
||||
|
||||
[functions]: functions.html
|
||||
[generics]: generics.html
|
||||
|
@ -109,7 +109,7 @@ If we wanted a `&mut` reference, we’d do this:
|
|||
...(x: &'a mut i32)
|
||||
```
|
||||
|
||||
If you compare `&mut i32` to `&'a mut i32`, they’re the same, it’s just that
|
||||
If you compare `&mut i32` to `&'a mut i32`, they’re the same, it’s that
|
||||
the lifetime `'a` has snuck in between the `&` and the `mut i32`. We read `&mut
|
||||
i32` as ‘a mutable reference to an `i32`’ and `&'a mut i32` as ‘a mutable
|
||||
reference to an `i32` with the lifetime `'a`’.
|
||||
|
@ -175,7 +175,7 @@ fn main() {
|
|||
```
|
||||
|
||||
As you can see, we need to declare a lifetime for `Foo` in the `impl` line. We repeat
|
||||
`'a` twice, just like on functions: `impl<'a>` defines a lifetime `'a`, and `Foo<'a>`
|
||||
`'a` twice, like on functions: `impl<'a>` defines a lifetime `'a`, and `Foo<'a>`
|
||||
uses it.
|
||||
|
||||
## Multiple lifetimes
|
||||
|
|
|
@ -49,11 +49,11 @@ and inside it, define a method, `area`.
|
|||
Methods take a special first parameter, of which there are three variants:
|
||||
`self`, `&self`, and `&mut self`. You can think of this first parameter as
|
||||
being the `foo` in `foo.bar()`. The three variants correspond to the three
|
||||
kinds of things `foo` could be: `self` if it’s just a value on the stack,
|
||||
kinds of things `foo` could be: `self` if it’s a value on the stack,
|
||||
`&self` if it’s a reference, and `&mut self` if it’s a mutable reference.
|
||||
Because we took the `&self` parameter to `area`, we can use it just like any
|
||||
Because we took the `&self` parameter to `area`, we can use it like any
|
||||
other parameter. Because we know it’s a `Circle`, we can access the `radius`
|
||||
just like we would with any other `struct`.
|
||||
like we would with any other `struct`.
|
||||
|
||||
We should default to using `&self`, as you should prefer borrowing over taking
|
||||
ownership, as well as taking immutable references over mutable ones. Here’s an
|
||||
|
@ -151,7 +151,7 @@ fn grow(&self, increment: f64) -> Circle {
|
|||
# Circle } }
|
||||
```
|
||||
|
||||
We just say we’re returning a `Circle`. With this method, we can grow a new
|
||||
We say we’re returning a `Circle`. With this method, we can grow a new
|
||||
`Circle` to any arbitrary size.
|
||||
|
||||
# Associated functions
|
||||
|
|
|
@ -39,7 +39,7 @@ script:
|
|||
$ sudo /usr/local/lib/rustlib/uninstall.sh
|
||||
```
|
||||
|
||||
If you used the Windows installer, just re-run the `.msi` and it will give you
|
||||
If you used the Windows installer, re-run the `.msi` and it will give you
|
||||
an uninstall option.
|
||||
|
||||
Some people, and somewhat rightfully so, get very upset when we tell you to
|
||||
|
@ -66,7 +66,7 @@ Finally, a comment about Windows. Rust considers Windows to be a first-class
|
|||
platform upon release, but if we're honest, the Windows experience isn't as
|
||||
integrated as the Linux/OS X experience is. We're working on it! If anything
|
||||
does not work, it is a bug. Please let us know if that happens. Each and every
|
||||
commit is tested against Windows just like any other platform.
|
||||
commit is tested against Windows like any other platform.
|
||||
|
||||
If you've got Rust installed, you can open up a shell, and type this:
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ instead.
|
|||
The core library has very few dependencies and is much more portable than the
|
||||
standard library itself. Additionally, the core library has most of the
|
||||
necessary functionality for writing idiomatic and effective Rust code. When
|
||||
using `#![no_std]`, Rust will automatically inject the `core` crate, just like
|
||||
using `#![no_std]`, Rust will automatically inject the `core` crate, like
|
||||
we do for `std` when we’re using it.
|
||||
|
||||
As an example, here is a program that will calculate the dot product of two
|
||||
|
|
|
@ -120,7 +120,7 @@ fn main() {
|
|||
}
|
||||
```
|
||||
|
||||
For `HasArea` and `Square`, we just declare a type parameter `T` and replace
|
||||
For `HasArea` and `Square`, we declare a type parameter `T` and replace
|
||||
`f64` with it. The `impl` needs more involved modifications:
|
||||
|
||||
```ignore
|
||||
|
|
|
@ -118,7 +118,7 @@ match origin {
|
|||
|
||||
This prints `x is 0`.
|
||||
|
||||
You can do this kind of match on any member, not just the first:
|
||||
You can do this kind of match on any member, not only the first:
|
||||
|
||||
```rust
|
||||
struct Point {
|
||||
|
@ -155,7 +155,7 @@ match some_value {
|
|||
```
|
||||
|
||||
In the first arm, we bind the value inside the `Ok` variant to `value`. But
|
||||
in the `Err` arm, we use `_` to disregard the specific error, and just print
|
||||
in the `Err` arm, we use `_` to disregard the specific error, and print
|
||||
a general error message.
|
||||
|
||||
`_` is valid in any pattern that creates a binding. This can be useful to
|
||||
|
@ -326,7 +326,7 @@ match x {
|
|||
```
|
||||
|
||||
This prints `no`, because the `if` applies to the whole of `4 | 5`, and not to
|
||||
just the `5`. In other words, the precedence of `if` behaves like this:
|
||||
only the `5`. In other words, the precedence of `if` behaves like this:
|
||||
|
||||
```text
|
||||
(4 | 5) if y => ...
|
||||
|
|
|
@ -160,7 +160,7 @@ documentation][array].
|
|||
|
||||
A ‘slice’ is a reference to (or “view” into) another data structure. They are
|
||||
useful for allowing safe, efficient access to a portion of an array without
|
||||
copying. For example, you might want to reference just one line of a file read
|
||||
copying. For example, you might want to reference only one line of a file read
|
||||
into memory. By nature, a slice is not created directly, but from an existing
|
||||
variable binding. Slices have a defined length, can be mutable or immutable.
|
||||
|
||||
|
@ -176,7 +176,7 @@ length of the slice:
|
|||
```rust
|
||||
let a = [0, 1, 2, 3, 4];
|
||||
let complete = &a[..]; // A slice containing all of the elements in a
|
||||
let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3
|
||||
let middle = &a[1..4]; // A slice of a: only the elements 1, 2, and 3
|
||||
```
|
||||
|
||||
Slices have type `&[T]`. We’ll talk about that `T` when we cover
|
||||
|
@ -220,11 +220,11 @@ with the type annotated:
|
|||
let x: (i32, &str) = (1, "hello");
|
||||
```
|
||||
|
||||
As you can see, the type of a tuple looks just like the tuple, but with each
|
||||
As you can see, the type of a tuple looks like the tuple, but with each
|
||||
position having a type name rather than the value. Careful readers will also
|
||||
note that tuples are heterogeneous: we have an `i32` and a `&str` in this tuple.
|
||||
In systems programming languages, strings are a bit more complex than in other
|
||||
languages. For now, just read `&str` as a *string slice*, and we’ll learn more
|
||||
languages. For now, read `&str` as a *string slice*, and we’ll learn more
|
||||
soon.
|
||||
|
||||
You can assign one tuple into another, if they have the same contained types
|
||||
|
@ -249,7 +249,7 @@ println!("x is {}", x);
|
|||
```
|
||||
|
||||
Remember [before][let] when I said the left-hand side of a `let` statement was more
|
||||
powerful than just assigning a binding? Here we are. We can put a pattern on
|
||||
powerful than assigning a binding? Here we are. We can put a pattern on
|
||||
the left-hand side of the `let`, and if it matches up to the right-hand side,
|
||||
we can assign multiple bindings at once. In this case, `let` “destructures”
|
||||
or “breaks up” the tuple, and assigns the bits to three bindings.
|
||||
|
|
|
@ -84,7 +84,7 @@ it borrows ownership. A binding that borrows something does not deallocate the
|
|||
resource when it goes out of scope. This means that after the call to `foo()`,
|
||||
we can use our original bindings again.
|
||||
|
||||
References are immutable, just like bindings. This means that inside of `foo()`,
|
||||
References are immutable, like bindings. This means that inside of `foo()`,
|
||||
the vectors can’t be changed at all:
|
||||
|
||||
```rust,ignore
|
||||
|
@ -129,7 +129,7 @@ You'll also notice we added an asterisk (`*`) in front of `y`, making it `*y`,
|
|||
this is because `y` is a `&mut` reference. You'll also need to use them for
|
||||
accessing the contents of a reference as well.
|
||||
|
||||
Otherwise, `&mut` references are just like references. There _is_ a large
|
||||
Otherwise, `&mut` references are like references. There _is_ a large
|
||||
difference between the two, and how they interact, though. You can tell
|
||||
something is fishy in the above example, because we need that extra scope, with
|
||||
the `{` and `}`. If we remove them, we get an error:
|
||||
|
|
|
@ -44,7 +44,7 @@ let s = "foo\
|
|||
assert_eq!("foobar", s);
|
||||
```
|
||||
|
||||
Rust has more than just `&str`s though. A `String`, is a heap-allocated string.
|
||||
Rust has more than only `&str`s though. A `String`, is a heap-allocated string.
|
||||
This string is growable, and is also guaranteed to be UTF-8. `String`s are
|
||||
commonly created by converting from a string slice using the `to_string`
|
||||
method.
|
||||
|
|
|
@ -202,7 +202,7 @@ println!("length is {} inches", integer_length);
|
|||
```
|
||||
|
||||
As you can see here, you can extract the inner integer type through a
|
||||
destructuring `let`, just as with regular tuples. In this case, the
|
||||
destructuring `let`, as with regular tuples. In this case, the
|
||||
`let Inches(integer_length)` assigns `10` to `integer_length`.
|
||||
|
||||
# Unit-like structs
|
||||
|
@ -223,7 +223,7 @@ This is rarely useful on its own (although sometimes it can serve as a
|
|||
marker type), but in combination with other features, it can become
|
||||
useful. For instance, a library may ask you to create a structure that
|
||||
implements a certain [trait][trait] to handle events. If you don’t have
|
||||
any data you need to store in the structure, you can just create a
|
||||
any data you need to store in the structure, you can create a
|
||||
unit-like `struct`.
|
||||
|
||||
[trait]: traits.html
|
||||
|
|
|
@ -365,7 +365,7 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
|
|||
It works!
|
||||
|
||||
The current convention is to use the `tests` module to hold your "unit-style"
|
||||
tests. Anything that just tests one small bit of functionality makes sense to
|
||||
tests. Anything that tests one small bit of functionality makes sense to
|
||||
go here. But what about "integration-style" tests instead? For that, we have
|
||||
the `tests` directory.
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ values ‘go on the stack’. What does that mean?
|
|||
Well, when a function gets called, some memory gets allocated for all of its
|
||||
local variables and some other information. This is called a ‘stack frame’, and
|
||||
for the purpose of this tutorial, we’re going to ignore the extra information
|
||||
and just consider the local variables we’re allocating. So in this case, when
|
||||
and only consider the local variables we’re allocating. So in this case, when
|
||||
`main()` is run, we’ll allocate a single 32-bit integer for our stack frame.
|
||||
This is automatically handled for you, as you can see; we didn’t have to write
|
||||
any special Rust code or anything.
|
||||
|
@ -177,7 +177,7 @@ And then `bold()` calls `italic()`:
|
|||
| 0 | x | 42 |
|
||||
Whew! Our stack is growing tall.
|
||||
|
||||
After `italic()` is over, its frame is deallocated, leaving just `bold()` and
|
||||
After `italic()` is over, its frame is deallocated, leaving only `bold()` and
|
||||
`main()`:
|
||||
|
||||
| Address | Name | Value |
|
||||
|
@ -187,7 +187,7 @@ After `italic()` is over, its frame is deallocated, leaving just `bold()` and
|
|||
| **1** | **a**| **5** |
|
||||
| 0 | x | 42 |
|
||||
|
||||
And then `bold()` ends, leaving just `main()`:
|
||||
And then `bold()` ends, leaving only `main()`:
|
||||
|
||||
| Address | Name | Value |
|
||||
|---------|------|-------|
|
||||
|
@ -247,7 +247,7 @@ location we’ve asked for.
|
|||
We haven’t really talked too much about what it actually means to allocate and
|
||||
deallocate memory in these contexts. Getting into very deep detail is out of
|
||||
the scope of this tutorial, but what’s important to point out here is that
|
||||
the heap isn’t just a stack that grows from the opposite end. We’ll have an
|
||||
the heap isn’t a stack that grows from the opposite end. We’ll have an
|
||||
example of this later in the book, but because the heap can be allocated and
|
||||
freed in any order, it can end up with ‘holes’. Here’s a diagram of the memory
|
||||
layout of a program which has been running for a while now:
|
||||
|
@ -332,13 +332,13 @@ What about when we call `foo()`, passing `y` as an argument?
|
|||
| 1 | y | → 0 |
|
||||
| 0 | x | 5 |
|
||||
|
||||
Stack frames aren’t just for local bindings, they’re for arguments too. So in
|
||||
Stack frames aren’t only for local bindings, they’re for arguments too. So in
|
||||
this case, we need to have both `i`, our argument, and `z`, our local variable
|
||||
binding. `i` is a copy of the argument, `y`. Since `y`’s value is `0`, so is
|
||||
`i`’s.
|
||||
|
||||
This is one reason why borrowing a variable doesn’t deallocate any memory: the
|
||||
value of a reference is just a pointer to a memory location. If we got rid of
|
||||
value of a reference is a pointer to a memory location. If we got rid of
|
||||
the underlying memory, things wouldn’t work very well.
|
||||
|
||||
# A complex example
|
||||
|
@ -454,7 +454,7 @@ Next, `foo()` calls `bar()` with `x` and `z`:
|
|||
| 0 | h | 3 |
|
||||
|
||||
We end up allocating another value on the heap, and so we have to subtract one
|
||||
from (2<sup>30</sup>) - 1. It’s easier to just write that than `1,073,741,822`. In any
|
||||
from (2<sup>30</sup>) - 1. It’s easier to write that than `1,073,741,822`. In any
|
||||
case, we set up the variables as usual.
|
||||
|
||||
At the end of `bar()`, it calls `baz()`:
|
||||
|
@ -550,7 +550,7 @@ has two big impacts: runtime efficiency and semantic impact.
|
|||
|
||||
## Runtime Efficiency
|
||||
|
||||
Managing the memory for the stack is trivial: The machine just
|
||||
Managing the memory for the stack is trivial: The machine
|
||||
increments or decrements a single value, the so-called “stack pointer”.
|
||||
Managing memory for the heap is non-trivial: heap-allocated memory is freed at
|
||||
arbitrary points, and each block of heap-allocated memory can be of arbitrary
|
||||
|
|
|
@ -272,7 +272,7 @@ made more flexible.
|
|||
|
||||
Suppose we’ve got some values that implement `Foo`. The explicit form of
|
||||
construction and use of `Foo` trait objects might look a bit like (ignoring the
|
||||
type mismatches: they’re all just pointers anyway):
|
||||
type mismatches: they’re all pointers anyway):
|
||||
|
||||
```rust,ignore
|
||||
let a: String = "foo".to_string();
|
||||
|
|
|
@ -44,8 +44,8 @@ impl HasArea for Circle {
|
|||
```
|
||||
|
||||
As you can see, the `trait` block looks very similar to the `impl` block,
|
||||
but we don’t define a body, just a type signature. When we `impl` a trait,
|
||||
we use `impl Trait for Item`, rather than just `impl Item`.
|
||||
but we don’t define a body, only a type signature. When we `impl` a trait,
|
||||
we use `impl Trait for Item`, rather than only `impl Item`.
|
||||
|
||||
## Trait bounds on generic functions
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ that you normally can not do. Just three. Here they are:
|
|||
|
||||
That’s it. It’s important that `unsafe` does not, for example, ‘turn off the
|
||||
borrow checker’. Adding `unsafe` to some random Rust code doesn’t change its
|
||||
semantics, it won’t just start accepting anything. But it will let you write
|
||||
semantics, it won’t start accepting anything. But it will let you write
|
||||
things that _do_ break some of the rules.
|
||||
|
||||
You will also encounter the `unsafe` keyword when writing bindings to foreign
|
||||
|
|
|
@ -11,7 +11,7 @@ Rust understands a few of these types, but they have some restrictions. There
|
|||
are three:
|
||||
|
||||
1. We can only manipulate an instance of an unsized type via a pointer. An
|
||||
`&[T]` works just fine, but a `[T]` does not.
|
||||
`&[T]` works fine, but a `[T]` does not.
|
||||
2. Variables and arguments cannot have dynamically sized types.
|
||||
3. Only the last field in a `struct` may have a dynamically sized type; the
|
||||
other fields must not. Enum variants must not have dynamically sized types as
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Virtually every non-'Hello World’ Rust program uses *variable bindings*. They
|
||||
bind some value to a name, so it can be used later. `let` is
|
||||
used to introduce a binding, just like this:
|
||||
used to introduce a binding, like this:
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
|
@ -18,7 +18,7 @@ function, rather than leaving it off. Otherwise, you’ll get an error.
|
|||
|
||||
In many languages, a variable binding would be called a *variable*, but Rust’s
|
||||
variable bindings have a few tricks up their sleeves. For example the
|
||||
left-hand side of a `let` expression is a ‘[pattern][pattern]’, not just a
|
||||
left-hand side of a `let` expression is a ‘[pattern][pattern]’, not a
|
||||
variable name. This means we can do things like:
|
||||
|
||||
```rust
|
||||
|
@ -27,7 +27,7 @@ let (x, y) = (1, 2);
|
|||
|
||||
After this expression is evaluated, `x` will be one, and `y` will be two.
|
||||
Patterns are really powerful, and have [their own section][pattern] in the
|
||||
book. We don’t need those features for now, so we’ll just keep this in the back
|
||||
book. We don’t need those features for now, so we’ll keep this in the back
|
||||
of our minds as we go forward.
|
||||
|
||||
[pattern]: patterns.html
|
||||
|
@ -169,10 +169,10 @@ in the middle of a string." We add a comma, and then `x`, to indicate that we
|
|||
want `x` to be the value we’re interpolating. The comma is used to separate
|
||||
arguments we pass to functions and macros, if you’re passing more than one.
|
||||
|
||||
When you just use the curly braces, Rust will attempt to display the value in a
|
||||
When you use the curly braces, Rust will attempt to display the value in a
|
||||
meaningful way by checking out its type. If you want to specify the format in a
|
||||
more detailed manner, there are a [wide number of options available][format].
|
||||
For now, we'll just stick to the default: integers aren't very complicated to
|
||||
For now, we'll stick to the default: integers aren't very complicated to
|
||||
print.
|
||||
|
||||
[format]: ../std/fmt/index.html
|
||||
|
|
|
@ -39,7 +39,7 @@ fn write_basic_block<W: Write>(block: BasicBlock, mir: &Mir, w: &mut W) -> io::R
|
|||
}
|
||||
|
||||
// Terminator at the bottom.
|
||||
try!(writeln!(w, "{0}{0}{1:?};", INDENT, data.terminator));
|
||||
try!(writeln!(w, "{0}{0}{1:?};", INDENT, data.terminator()));
|
||||
|
||||
writeln!(w, "{}}}", INDENT)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue