mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Auto merge of #27530 - Manishearth:rollup, r=Manishearth
- Successful merges: #27519, #27521, #27525, #27527, #27528 - Failed merges:
This commit is contained in:
commit
6210dcdddb
@ -127,7 +127,7 @@ fundamentally unsynchronized and compilers are free to aggressively optimize
|
||||
them. In particular, data accesses are free to be reordered by the compiler on
|
||||
the assumption that the program is single-threaded. The hardware is also free to
|
||||
propagate the changes made in data accesses to other threads as lazily and
|
||||
inconsistently as it wants. Mostly critically, data accesses are how data races
|
||||
inconsistently as it wants. Most critically, data accesses are how data races
|
||||
happen. Data accesses are very friendly to the hardware and compiler, but as
|
||||
we've seen they offer *awful* semantics to try to write synchronized code with.
|
||||
Actually, that's too weak.
|
||||
|
@ -7,7 +7,7 @@ an abstraction over them in a relatively uncontroversial way. Message passing,
|
||||
green threads, and async APIs are all diverse enough that any abstraction over
|
||||
them tends to involve trade-offs that we weren't willing to commit to for 1.0.
|
||||
|
||||
However the way Rust models concurrency makes it relatively easy design your own
|
||||
However the way Rust models concurrency makes it relatively easy to design your own
|
||||
concurrency paradigm as a library and have everyone else's code Just Work
|
||||
with yours. Just require the right lifetimes and Send and Sync where appropriate
|
||||
and you're off to the races. Or rather, off to the... not... having... races.
|
||||
|
@ -120,7 +120,7 @@ enum Link {
|
||||
will have its inner Box field dropped if and only if an instance stores the
|
||||
Next variant.
|
||||
|
||||
In general this works really nice because you don't need to worry about
|
||||
In general this works really nicely because you don't need to worry about
|
||||
adding/removing drops when you refactor your data layout. Still there's
|
||||
certainly many valid usecases for needing to do trickier things with
|
||||
destructors.
|
||||
|
@ -1,7 +1,7 @@
|
||||
% Drop Flags
|
||||
|
||||
The examples in the previous section introduce an interesting problem for Rust.
|
||||
We have seen that's possible to conditionally initialize, deinitialize, and
|
||||
We have seen that it's possible to conditionally initialize, deinitialize, and
|
||||
reinitialize locations of memory totally safely. For Copy types, this isn't
|
||||
particularly notable since they're just a random pile of bits. However types
|
||||
with destructors are a different story: Rust needs to know whether to call a
|
||||
|
@ -1,7 +1,7 @@
|
||||
% Drop Check
|
||||
|
||||
We have seen how lifetimes provide us some fairly simple rules for ensuring
|
||||
that never read dangling references. However up to this point we have only ever
|
||||
that we never read dangling references. However up to this point we have only ever
|
||||
interacted with the *outlives* relationship in an inclusive manner. That is,
|
||||
when we talked about `'a: 'b`, it was ok for `'a` to live *exactly* as long as
|
||||
`'b`. At first glance, this seems to be a meaningless distinction. Nothing ever
|
||||
|
@ -3,7 +3,7 @@
|
||||
Not everything obeys inherited mutability, though. Some types allow you to
|
||||
multiply alias a location in memory while mutating it. Unless these types use
|
||||
synchronization to manage this access, they are absolutely not thread safe. Rust
|
||||
captures this with through the `Send` and `Sync` traits.
|
||||
captures this through the `Send` and `Sync` traits.
|
||||
|
||||
* A type is Send if it is safe to send it to another thread.
|
||||
* A type is Sync if it is safe to share between threads (`&T` is Send).
|
||||
@ -11,7 +11,7 @@ captures this with through the `Send` and `Sync` traits.
|
||||
Send and Sync are fundamental to Rust's concurrency story. As such, a
|
||||
substantial amount of special tooling exists to make them work right. First and
|
||||
foremost, they're [unsafe traits][]. This means that they are unsafe to
|
||||
implement, and other unsafe code can that they are correctly
|
||||
implement, and other unsafe code can assume that they are correctly
|
||||
implemented. Since they're *marker traits* (they have no associated items like
|
||||
methods), correctly implemented simply means that they have the intrinsic
|
||||
properties an implementor should have. Incorrectly implementing Send or Sync can
|
||||
|
@ -93,8 +93,8 @@ fn main() {
|
||||
|
||||
The signature of `overwrite` is clearly valid: it takes mutable references to
|
||||
two values of the same type, and overwrites one with the other. If `&mut T` was
|
||||
variant over T, then `&mut &'a str` would be a subtype of `&mut &'static str`,
|
||||
since `&'a str` is a subtype of `&'static str`. Therefore the lifetime of
|
||||
variant over T, then `&mut &'static str` would be a subtype of `&mut &'a str`,
|
||||
since `&'static str` is a subtype of `&'a str`. Therefore the lifetime of
|
||||
`forever_str` would successfully be "shrunk" down to the shorter lifetime of
|
||||
`string`, and `overwrite` would be called successfully. `string` would
|
||||
subsequently be dropped, and `forever_str` would point to freed memory when we
|
||||
|
@ -77,7 +77,7 @@ contain any `Drop` types.
|
||||
However when working with uninitialized memory you need to be ever-vigilant for
|
||||
Rust trying to drop values you make like this before they're fully initialized.
|
||||
Every control path through that variable's scope must initialize the value
|
||||
before it ends, if has a destructor.
|
||||
before it ends, if it has a destructor.
|
||||
*[This includes code panicking](unwinding.html)*.
|
||||
|
||||
And that's about it for working with uninitialized memory! Basically nothing
|
||||
|
@ -538,8 +538,9 @@ balanced, but they are otherwise not special.
|
||||
In the matcher, `$` _name_ `:` _designator_ matches the nonterminal in the Rust
|
||||
syntax named by _designator_. Valid designators are `item`, `block`, `stmt`,
|
||||
`pat`, `expr`, `ty` (type), `ident`, `path`, `tt` (either side of the `=>`
|
||||
in macro rules). In the transcriber, the designator is already known, and so
|
||||
only the name of a matched nonterminal comes after the dollar sign.
|
||||
in macro rules), and `meta` (contents of an attribute). In the transcriber, the
|
||||
designator is already known, and so only the name of a matched nonterminal comes
|
||||
after the dollar sign.
|
||||
|
||||
In both the matcher and transcriber, the Kleene star-like operator indicates
|
||||
repetition. The Kleene star operator consists of `$` and parentheses, optionally
|
||||
|
@ -39,203 +39,6 @@ match x {
|
||||
|
||||
This prints `one or two`.
|
||||
|
||||
# Ranges
|
||||
|
||||
You can match a range of values with `...`:
|
||||
|
||||
```rust
|
||||
let x = 1;
|
||||
|
||||
match x {
|
||||
1 ... 5 => println!("one through five"),
|
||||
_ => println!("anything"),
|
||||
}
|
||||
```
|
||||
|
||||
This prints `one through five`.
|
||||
|
||||
Ranges are mostly used with integers and `char`s:
|
||||
|
||||
```rust
|
||||
let x = '💅';
|
||||
|
||||
match x {
|
||||
'a' ... 'j' => println!("early letter"),
|
||||
'k' ... 'z' => println!("late letter"),
|
||||
_ => println!("something else"),
|
||||
}
|
||||
```
|
||||
|
||||
This prints `something else`.
|
||||
|
||||
# Bindings
|
||||
|
||||
You can bind values to names with `@`:
|
||||
|
||||
```rust
|
||||
let x = 1;
|
||||
|
||||
match x {
|
||||
e @ 1 ... 5 => println!("got a range element {}", e),
|
||||
_ => println!("anything"),
|
||||
}
|
||||
```
|
||||
|
||||
This prints `got a range element 1`. This is useful when you want to
|
||||
do a complicated match of part of a data structure:
|
||||
|
||||
```rust
|
||||
#[derive(Debug)]
|
||||
struct Person {
|
||||
name: Option<String>,
|
||||
}
|
||||
|
||||
let name = "Steve".to_string();
|
||||
let mut x: Option<Person> = Some(Person { name: Some(name) });
|
||||
match x {
|
||||
Some(Person { name: ref a @ Some(_), .. }) => println!("{:?}", a),
|
||||
_ => {}
|
||||
}
|
||||
```
|
||||
|
||||
This prints `Some("Steve")`: We’ve bound the inner `name` to `a`.
|
||||
|
||||
If you use `@` with `|`, you need to make sure the name is bound in each part
|
||||
of the pattern:
|
||||
|
||||
```rust
|
||||
let x = 5;
|
||||
|
||||
match x {
|
||||
e @ 1 ... 5 | e @ 8 ... 10 => println!("got a range element {}", e),
|
||||
_ => println!("anything"),
|
||||
}
|
||||
```
|
||||
|
||||
# Ignoring bindings
|
||||
|
||||
You can use `_` in a pattern to disregard the type and value.
|
||||
For example, here’s a `match` against a `Result<T, E>`:
|
||||
|
||||
```rust
|
||||
# let some_value: Result<i32, &'static str> = Err("There was an error");
|
||||
match some_value {
|
||||
Ok(value) => println!("got a value: {}", value),
|
||||
Err(_) => println!("an error occurred"),
|
||||
}
|
||||
```
|
||||
|
||||
In the first arm, we bind the value inside the `Ok` variant to `value`. But
|
||||
in the `Err` arm, we use `_` to disregard the specific error, and just print
|
||||
a general error message.
|
||||
|
||||
`_` is valid in any pattern that creates a binding. This can be useful to
|
||||
ignore parts of a larger structure:
|
||||
|
||||
```rust
|
||||
fn coordinate() -> (i32, i32, i32) {
|
||||
// generate and return some sort of triple tuple
|
||||
# (1, 2, 3)
|
||||
}
|
||||
|
||||
let (x, _, z) = coordinate();
|
||||
```
|
||||
|
||||
Here, we bind the first and last element of the tuple to `x` and `z`, but
|
||||
ignore the middle element.
|
||||
|
||||
Similarly, you can use `..` in a pattern to disregard multiple values.
|
||||
|
||||
```rust
|
||||
enum OptionalTuple {
|
||||
Value(i32, i32, i32),
|
||||
Missing,
|
||||
}
|
||||
|
||||
let x = OptionalTuple::Value(5, -2, 3);
|
||||
|
||||
match x {
|
||||
OptionalTuple::Value(..) => println!("Got a tuple!"),
|
||||
OptionalTuple::Missing => println!("No such luck."),
|
||||
}
|
||||
```
|
||||
|
||||
This prints `Got a tuple!`.
|
||||
|
||||
# Guards
|
||||
|
||||
You can introduce ‘match guards’ with `if`:
|
||||
|
||||
```rust
|
||||
enum OptionalInt {
|
||||
Value(i32),
|
||||
Missing,
|
||||
}
|
||||
|
||||
let x = OptionalInt::Value(5);
|
||||
|
||||
match x {
|
||||
OptionalInt::Value(i) if i > 5 => println!("Got an int bigger than five!"),
|
||||
OptionalInt::Value(..) => println!("Got an int!"),
|
||||
OptionalInt::Missing => println!("No such luck."),
|
||||
}
|
||||
```
|
||||
|
||||
This prints `Got an int!`.
|
||||
|
||||
If you’re using `if` with multiple patterns, the `if` applies to both sides:
|
||||
|
||||
```rust
|
||||
let x = 4;
|
||||
let y = false;
|
||||
|
||||
match x {
|
||||
4 | 5 if y => println!("yes"),
|
||||
_ => println!("no"),
|
||||
}
|
||||
```
|
||||
|
||||
This prints `no`, because the `if` applies to the whole of `4 | 5`, and not to
|
||||
just the `5`, In other words, the the precedence of `if` behaves like this:
|
||||
|
||||
```text
|
||||
(4 | 5) if y => ...
|
||||
```
|
||||
|
||||
not this:
|
||||
|
||||
```text
|
||||
4 | (5 if y) => ...
|
||||
```
|
||||
|
||||
# ref and ref mut
|
||||
|
||||
If you want to get a [reference][ref], use the `ref` keyword:
|
||||
|
||||
```rust
|
||||
let x = 5;
|
||||
|
||||
match x {
|
||||
ref r => println!("Got a reference to {}", r),
|
||||
}
|
||||
```
|
||||
|
||||
This prints `Got a reference to 5`.
|
||||
|
||||
[ref]: references-and-borrowing.html
|
||||
|
||||
Here, the `r` inside the `match` has the type `&i32`. In other words, the `ref`
|
||||
keyword _creates_ a reference, for use in the pattern. If you need a mutable
|
||||
reference, `ref mut` will work in the same way:
|
||||
|
||||
```rust
|
||||
let mut x = 5;
|
||||
|
||||
match x {
|
||||
ref mut mr => println!("Got a mutable reference to {}", mr),
|
||||
}
|
||||
```
|
||||
|
||||
# Destructuring
|
||||
|
||||
If you have a compound data type, like a [`struct`][struct], you can destructure it
|
||||
@ -311,6 +114,203 @@ This ‘destructuring’ behavior works on any compound data type, like
|
||||
[tuples]: primitive-types.html#tuples
|
||||
[enums]: enums.html
|
||||
|
||||
# Ignoring bindings
|
||||
|
||||
You can use `_` in a pattern to disregard the type and value.
|
||||
For example, here’s a `match` against a `Result<T, E>`:
|
||||
|
||||
```rust
|
||||
# let some_value: Result<i32, &'static str> = Err("There was an error");
|
||||
match some_value {
|
||||
Ok(value) => println!("got a value: {}", value),
|
||||
Err(_) => println!("an error occurred"),
|
||||
}
|
||||
```
|
||||
|
||||
In the first arm, we bind the value inside the `Ok` variant to `value`. But
|
||||
in the `Err` arm, we use `_` to disregard the specific error, and just print
|
||||
a general error message.
|
||||
|
||||
`_` is valid in any pattern that creates a binding. This can be useful to
|
||||
ignore parts of a larger structure:
|
||||
|
||||
```rust
|
||||
fn coordinate() -> (i32, i32, i32) {
|
||||
// generate and return some sort of triple tuple
|
||||
# (1, 2, 3)
|
||||
}
|
||||
|
||||
let (x, _, z) = coordinate();
|
||||
```
|
||||
|
||||
Here, we bind the first and last element of the tuple to `x` and `z`, but
|
||||
ignore the middle element.
|
||||
|
||||
Similarly, you can use `..` in a pattern to disregard multiple values.
|
||||
|
||||
```rust
|
||||
enum OptionalTuple {
|
||||
Value(i32, i32, i32),
|
||||
Missing,
|
||||
}
|
||||
|
||||
let x = OptionalTuple::Value(5, -2, 3);
|
||||
|
||||
match x {
|
||||
OptionalTuple::Value(..) => println!("Got a tuple!"),
|
||||
OptionalTuple::Missing => println!("No such luck."),
|
||||
}
|
||||
```
|
||||
|
||||
This prints `Got a tuple!`.
|
||||
|
||||
# ref and ref mut
|
||||
|
||||
If you want to get a [reference][ref], use the `ref` keyword:
|
||||
|
||||
```rust
|
||||
let x = 5;
|
||||
|
||||
match x {
|
||||
ref r => println!("Got a reference to {}", r),
|
||||
}
|
||||
```
|
||||
|
||||
This prints `Got a reference to 5`.
|
||||
|
||||
[ref]: references-and-borrowing.html
|
||||
|
||||
Here, the `r` inside the `match` has the type `&i32`. In other words, the `ref`
|
||||
keyword _creates_ a reference, for use in the pattern. If you need a mutable
|
||||
reference, `ref mut` will work in the same way:
|
||||
|
||||
```rust
|
||||
let mut x = 5;
|
||||
|
||||
match x {
|
||||
ref mut mr => println!("Got a mutable reference to {}", mr),
|
||||
}
|
||||
```
|
||||
|
||||
# Ranges
|
||||
|
||||
You can match a range of values with `...`:
|
||||
|
||||
```rust
|
||||
let x = 1;
|
||||
|
||||
match x {
|
||||
1 ... 5 => println!("one through five"),
|
||||
_ => println!("anything"),
|
||||
}
|
||||
```
|
||||
|
||||
This prints `one through five`.
|
||||
|
||||
Ranges are mostly used with integers and `char`s:
|
||||
|
||||
```rust
|
||||
let x = '💅';
|
||||
|
||||
match x {
|
||||
'a' ... 'j' => println!("early letter"),
|
||||
'k' ... 'z' => println!("late letter"),
|
||||
_ => println!("something else"),
|
||||
}
|
||||
```
|
||||
|
||||
This prints `something else`.
|
||||
|
||||
# Bindings
|
||||
|
||||
You can bind values to names with `@`:
|
||||
|
||||
```rust
|
||||
let x = 1;
|
||||
|
||||
match x {
|
||||
e @ 1 ... 5 => println!("got a range element {}", e),
|
||||
_ => println!("anything"),
|
||||
}
|
||||
```
|
||||
|
||||
This prints `got a range element 1`. This is useful when you want to
|
||||
do a complicated match of part of a data structure:
|
||||
|
||||
```rust
|
||||
#[derive(Debug)]
|
||||
struct Person {
|
||||
name: Option<String>,
|
||||
}
|
||||
|
||||
let name = "Steve".to_string();
|
||||
let mut x: Option<Person> = Some(Person { name: Some(name) });
|
||||
match x {
|
||||
Some(Person { name: ref a @ Some(_), .. }) => println!("{:?}", a),
|
||||
_ => {}
|
||||
}
|
||||
```
|
||||
|
||||
This prints `Some("Steve")`: We’ve bound the inner `name` to `a`.
|
||||
|
||||
If you use `@` with `|`, you need to make sure the name is bound in each part
|
||||
of the pattern:
|
||||
|
||||
```rust
|
||||
let x = 5;
|
||||
|
||||
match x {
|
||||
e @ 1 ... 5 | e @ 8 ... 10 => println!("got a range element {}", e),
|
||||
_ => println!("anything"),
|
||||
}
|
||||
```
|
||||
|
||||
# Guards
|
||||
|
||||
You can introduce ‘match guards’ with `if`:
|
||||
|
||||
```rust
|
||||
enum OptionalInt {
|
||||
Value(i32),
|
||||
Missing,
|
||||
}
|
||||
|
||||
let x = OptionalInt::Value(5);
|
||||
|
||||
match x {
|
||||
OptionalInt::Value(i) if i > 5 => println!("Got an int bigger than five!"),
|
||||
OptionalInt::Value(..) => println!("Got an int!"),
|
||||
OptionalInt::Missing => println!("No such luck."),
|
||||
}
|
||||
```
|
||||
|
||||
This prints `Got an int!`.
|
||||
|
||||
If you’re using `if` with multiple patterns, the `if` applies to both sides:
|
||||
|
||||
```rust
|
||||
let x = 4;
|
||||
let y = false;
|
||||
|
||||
match x {
|
||||
4 | 5 if y => println!("yes"),
|
||||
_ => println!("no"),
|
||||
}
|
||||
```
|
||||
|
||||
This prints `no`, because the `if` applies to the whole of `4 | 5`, and not to
|
||||
just the `5`, In other words, the the precedence of `if` behaves like this:
|
||||
|
||||
```text
|
||||
(4 | 5) if y => ...
|
||||
```
|
||||
|
||||
not this:
|
||||
|
||||
```text
|
||||
4 | (5 if y) => ...
|
||||
```
|
||||
|
||||
# Mix and Match
|
||||
|
||||
Whew! That’s a lot of different ways to match things, and they can all be
|
||||
|
@ -29,6 +29,19 @@ pub use intrinsics::transmute;
|
||||
/// `mem::drop` function in that it **does not run the destructor**, leaking the
|
||||
/// value and any resources that it owns.
|
||||
///
|
||||
/// There's only a few reasons to use this function. They mainly come
|
||||
/// up in unsafe code or FFI code.
|
||||
///
|
||||
/// * You have an uninitialized value, perhaps for performance reasons, and
|
||||
/// need to prevent the destructor from running on it.
|
||||
/// * You have two copies of a value (like when writing something like
|
||||
/// [`mem::swap`][swap]), but need the destructor to only run once to
|
||||
/// prevent a double `free`.
|
||||
/// * Transferring resources across [FFI][ffi] boundries.
|
||||
///
|
||||
/// [swap]: fn.swap.html
|
||||
/// [ffi]: ../../book/ffi.html
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is not marked as `unsafe` as Rust does not guarantee that the
|
||||
@ -52,20 +65,9 @@ pub use intrinsics::transmute;
|
||||
/// * `mpsc::{Sender, Receiver}` cycles (they use `Arc` internally)
|
||||
/// * Panicking destructors are likely to leak local resources
|
||||
///
|
||||
/// # When To Use
|
||||
///
|
||||
/// There's only a few reasons to use this function. They mainly come
|
||||
/// up in unsafe code or FFI code.
|
||||
///
|
||||
/// * You have an uninitialized value, perhaps for performance reasons, and
|
||||
/// need to prevent the destructor from running on it.
|
||||
/// * You have two copies of a value (like `std::mem::swap`), but need the
|
||||
/// destructor to only run once to prevent a double free.
|
||||
/// * Transferring resources across FFI boundries.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// Leak some heap memory by never deallocating it.
|
||||
/// Leak some heap memory by never deallocating it:
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::mem;
|
||||
@ -74,7 +76,7 @@ pub use intrinsics::transmute;
|
||||
/// mem::forget(heap_memory);
|
||||
/// ```
|
||||
///
|
||||
/// Leak an I/O object, never closing the file.
|
||||
/// Leak an I/O object, never closing the file:
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use std::mem;
|
||||
@ -84,7 +86,7 @@ pub use intrinsics::transmute;
|
||||
/// mem::forget(file);
|
||||
/// ```
|
||||
///
|
||||
/// The swap function uses forget to good effect.
|
||||
/// The `mem::swap` function uses `mem::forget` to good effect:
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::mem;
|
||||
|
Loading…
Reference in New Issue
Block a user