From c1f938d7b834852aede4f865a18ee2226668a8e6 Mon Sep 17 00:00:00 2001 From: Jan Likar Date: Tue, 4 Aug 2015 20:22:42 +0200 Subject: [PATCH 1/5] Rearrange sections in "Patterns" - Move "Destructuring" after "Multiple patterns", because some of later sections include examples which make use of destructuring. - Move "Ignoring bindings" after "Destructoring", because the former features Result destructuring. Some of examples in later sections use "_" and "..", so "Ignoring bindings" must be positioned before them. - Fix #27347 by moving "Ref and mut ref" before "Ranges" and "Bindings", because "Bindings" section includes a somewhat difficult example, which also makes use of "ref" and "mut ref" operators. --- src/doc/trpl/patterns.md | 394 +++++++++++++++++++-------------------- 1 file changed, 197 insertions(+), 197 deletions(-) diff --git a/src/doc/trpl/patterns.md b/src/doc/trpl/patterns.md index 1abd4ca6c21..26574f15c2c 100644 --- a/src/doc/trpl/patterns.md +++ b/src/doc/trpl/patterns.md @@ -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, -} - -let name = "Steve".to_string(); -let mut x: Option = 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`: - -```rust -# let some_value: Result = 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`: + +```rust +# let some_value: Result = 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, +} + +let name = "Steve".to_string(); +let mut x: Option = 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 From 5af1b3f3a3361abf79573295b0847d8fecf782aa Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Tue, 4 Aug 2015 15:57:54 -0400 Subject: [PATCH 2/5] Improve docs for mem::forget() We were burying the reason to use this function below a bunch of caveats about its usage. That's backwards. Why a function should be used belongs at the top of the docs, not the bottom. Also, add some extra links to related functions mentioned in the body. --- src/libcore/mem.rs | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 7e63c8d71f9..86b331d220a 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -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; From 67455e29a1d611a71a3a528544649b1b3ac4df16 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Tue, 4 Aug 2015 15:09:47 -0700 Subject: [PATCH 3/5] Fix variance ordering I thought this was actually a huge error and I'd have to rewrite a bunch but it looks like everything else was correct. Closes #27457 --- src/doc/nomicon/subtyping.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/nomicon/subtyping.md b/src/doc/nomicon/subtyping.md index 3c57297f323..65dcb6a94e1 100644 --- a/src/doc/nomicon/subtyping.md +++ b/src/doc/nomicon/subtyping.md @@ -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 From 2accd295c603799c4d42ced7683fd653b21a666d Mon Sep 17 00:00:00 2001 From: Ivan Jager Date: Tue, 4 Aug 2015 17:09:44 -0500 Subject: [PATCH 4/5] Fix some grammar in The Advanced Rust Programming Language --- src/doc/nomicon/atomics.md | 2 +- src/doc/nomicon/concurrency.md | 2 +- src/doc/nomicon/destructors.md | 2 +- src/doc/nomicon/drop-flags.md | 2 +- src/doc/nomicon/dropck.md | 2 +- src/doc/nomicon/send-and-sync.md | 4 ++-- src/doc/nomicon/unchecked-uninit.md | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/doc/nomicon/atomics.md b/src/doc/nomicon/atomics.md index 2d567e39f8f..d781e59d7c9 100644 --- a/src/doc/nomicon/atomics.md +++ b/src/doc/nomicon/atomics.md @@ -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. diff --git a/src/doc/nomicon/concurrency.md b/src/doc/nomicon/concurrency.md index 9dcbecdd5b3..802f3204cd4 100644 --- a/src/doc/nomicon/concurrency.md +++ b/src/doc/nomicon/concurrency.md @@ -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. diff --git a/src/doc/nomicon/destructors.md b/src/doc/nomicon/destructors.md index 568f7c07f59..29a866063e9 100644 --- a/src/doc/nomicon/destructors.md +++ b/src/doc/nomicon/destructors.md @@ -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. diff --git a/src/doc/nomicon/drop-flags.md b/src/doc/nomicon/drop-flags.md index 1e81c97479b..5655c5d245c 100644 --- a/src/doc/nomicon/drop-flags.md +++ b/src/doc/nomicon/drop-flags.md @@ -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 diff --git a/src/doc/nomicon/dropck.md b/src/doc/nomicon/dropck.md index df09d1a1744..98d269ff762 100644 --- a/src/doc/nomicon/dropck.md +++ b/src/doc/nomicon/dropck.md @@ -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 diff --git a/src/doc/nomicon/send-and-sync.md b/src/doc/nomicon/send-and-sync.md index 334d5c9dd55..8724b97546e 100644 --- a/src/doc/nomicon/send-and-sync.md +++ b/src/doc/nomicon/send-and-sync.md @@ -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 diff --git a/src/doc/nomicon/unchecked-uninit.md b/src/doc/nomicon/unchecked-uninit.md index da9fb294a1e..5ae1818dc63 100644 --- a/src/doc/nomicon/unchecked-uninit.md +++ b/src/doc/nomicon/unchecked-uninit.md @@ -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 From eaf27799bbed40f7360e13282b5ebce216b5b177 Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Tue, 4 Aug 2015 20:00:59 -0500 Subject: [PATCH 5/5] add `meta` designator to macro reference --- src/doc/reference.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index 5988d62bd79..fdb45c32a1d 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -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