diff --git a/src/doc/reference.md b/src/doc/reference.md index bb9eeab24e7bd..a61d635af7df9 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -149,9 +149,11 @@ sequence (`/**`), are interpreted as a special syntax for `doc` `#[doc="..."]` around the body of the comment (this includes the comment characters themselves, i.e. `/// Foo` turns into `#[doc="/// Foo"]`). -`//!` comments apply to the parent of the comment, rather than the item that -follows. `//!` comments are usually used to display information on the crate -index page. +Line comments beginning with `//!` and block comments beginning with `/*!` are +doc comments that apply to the parent of the comment, rather than the item +that follows. That is, they are equivalent to writing `#![doc="..."]` around +the body of the comment. `//!` comments are usually used to display +information on the crate index page. Non-doc comments are interpreted as a form of whitespace. @@ -196,10 +198,11 @@ grammar as double-quoted strings. Other tokens have exact rules given. | fn | for | if | impl | in | | let | loop | macro | match | mod | | move | mut | offsetof | override | priv | -| pub | pure | ref | return | sizeof | -| static | self | struct | super | true | -| trait | type | typeof | unsafe | unsized | -| use | virtual | where | while | yield | +| proc | pub | pure | ref | return | +| Self | self | sizeof | static | struct | +| super | trait | true | type | typeof | +| unsafe | unsized | use | virtual | where | +| while | yield | | | | Each of these keywords has special meaning in its grammar, and all of them are @@ -697,9 +700,9 @@ 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 both the matcher and transcriber, the Kleene star-like operator indicates -repetition. The Kleene star operator consists of `$` and parenthesis, optionally +repetition. The Kleene star operator consists of `$` and parentheses, optionally followed by a separator token, followed by `*` or `+`. `*` means zero or more -repetitions, `+` means at least one repetition. The parenthesis are not matched or +repetitions, `+` means at least one repetition. The parentheses are not matched or transcribed. On the matcher side, a name is bound to _all_ of the names it matches, in a structure that mimics the structure of the repetition encountered on a successful match. The job of the transcriber is to sort that structure @@ -1099,40 +1102,31 @@ signature. Each type parameter must be explicitly declared, in an angle-bracket-enclosed, comma-separated list following the function name. ```{.ignore} -fn iter(seq: &[T], f: |T|) { - for elt in seq.iter() { f(elt); } +fn iter(seq: &[T], f: F) where T: Copy, F: Fn(T) { + for elt in seq { f(*elt); } } -fn map(seq: &[T], f: |T| -> U) -> Vec { +fn map(seq: &[T], f: F) -> Vec where T: Copy, U: Copy, F: Fn(T) -> U { let mut acc = vec![]; - for elt in seq.iter() { acc.push(f(elt)); } + for elt in seq { acc.push(f(*elt)); } acc } ``` Inside the function signature and body, the name of the type parameter can be -used as a type name. +used as a type name. [Trait](#traits) bounds can be specified for type parameters +to allow methods with that trait to be called on values of that type. This is +specified using the `where` syntax, as in the above example. When a generic function is referenced, its type is instantiated based on the context of the reference. For example, calling the `iter` function defined above on `[1, 2]` will instantiate type parameter `T` with `i32`, and require -the closure parameter to have type `fn(i32)`. +the closure parameter to have type `Fn(i32)`. The type parameters can also be explicitly supplied in a trailing [path](#paths) component after the function name. This might be necessary if there is not sufficient context to determine the type parameters. For example, `mem::size_of::() == 4`. -Since a parameter type is opaque to the generic function, the set of operations -that can be performed on it is limited. Values of parameter type can only be -moved, not copied. - -``` -fn id(x: T) -> T { x } -``` - -Similarly, [trait](#traits) bounds can be specified for type parameters to -allow methods with that trait to be called on values of that type. - #### Unsafety Unsafe operations are those that potentially violate the memory-safety @@ -1555,7 +1549,7 @@ fn draw_twice(surface: Surface, sh: T) { } ``` -Traits also define an [object type](#object-types) with the same name as the +Traits also define an [trait object](#trait-objects) with the same name as the trait. Values of this type are created by [casting](#type-cast-expressions) pointer values (pointing to a type for which an implementation of the given trait is in scope) to pointers to the trait name, used as a type. @@ -2146,7 +2140,7 @@ The following configurations must be defined by the implementation: `"unix"` or `"windows"`. The value of this configuration option is defined as a configuration itself, like `unix` or `windows`. * `target_os = "..."`. Operating system of the target, examples include - `"win32"`, `"macos"`, `"linux"`, `"android"`, `"freebsd"`, `"dragonfly"`, + `"windows"`, `"macos"`, `"ios"`, `"linux"`, `"android"`, `"freebsd"`, `"dragonfly"`, `"bitrig"` or `"openbsd"`. * `target_pointer_width = "..."`. Target pointer width in bits. This is set to `"32"` for targets with 32-bit pointers, and likewise set to `"64"` for @@ -2744,7 +2738,7 @@ A _method call_ consists of an expression followed by a single dot, an identifier, and a parenthesized expression-list. Method calls are resolved to methods on specific traits, either statically dispatching to a method if the exact `self`-type of the left-hand-side is known, or dynamically dispatching if -the left-hand-side expression is an indirect [object type](#object-types). +the left-hand-side expression is an indirect [trait object](#trait-objects). ### Field expressions @@ -2812,6 +2806,33 @@ _panicked state_. (["a", "b"])[10]; // panics ``` +### Range expressions + +```{.ebnf .gram} +range_expr : expr ".." expr | + expr ".." | + ".." expr | + ".." ; +``` + +The `..` operator will construct an object of one of the `std::ops::Range` variants. + +``` +1..2; // std::ops::Range +3..; // std::ops::RangeFrom +..4; // std::ops::RangeTo +..; // std::ops::RangeFull +``` + +The following expressions are equivalent. + +``` +let x = std::ops::Range {start: 0, end: 10}; +let y = 0..10; + +assert_eq!(x,y); +``` + ### Unary operator expressions Rust defines three unary operators. They are all written as prefix operators, @@ -3078,28 +3099,6 @@ fn ten_times(f: F) where F: Fn(i32) { ten_times(|j| println!("hello, {}", j)); ``` -### While loops - -```{.ebnf .gram} -while_expr : [ lifetime ':' ] "while" no_struct_literal_expr '{' block '}' ; -``` - -A `while` loop begins by evaluating the boolean loop conditional expression. -If the loop conditional expression evaluates to `true`, the loop body block -executes and control returns to the loop conditional expression. If the loop -conditional expression evaluates to `false`, the `while` expression completes. - -An example: - -``` -let mut i = 0; - -while i < 10 { - println!("hello"); - i = i + 1; -} -``` - ### Infinite loops A `loop` expression denotes an infinite loop. @@ -3108,10 +3107,11 @@ A `loop` expression denotes an infinite loop. loop_expr : [ lifetime ':' ] "loop" '{' block '}'; ``` -A `loop` expression may optionally have a _label_. If a label is present, then -labeled `break` and `continue` expressions nested within this loop may exit out -of this loop or return control to its head. See [Break -expressions](#break-expressions) and [Continue +A `loop` expression may optionally have a _label_. The label is written as +a lifetime preceding the loop expression, as in `'foo: loop{ }`. If a +label is present, then labeled `break` and `continue` expressions nested +within this loop may exit out of this loop or return control to its head. +See [Break expressions](#break-expressions) and [Continue expressions](#continue-expressions). ### Break expressions @@ -3123,7 +3123,7 @@ break_expr : "break" [ lifetime ]; A `break` expression has an optional _label_. If the label is absent, then executing a `break` expression immediately terminates the innermost loop enclosing it. It is only permitted in the body of a loop. If the label is -present, then `break foo` terminates the loop with label `foo`, which need not +present, then `break 'foo` terminates the loop with label `'foo`, which need not be the innermost label enclosing the `break` expression, but must enclose it. ### Continue expressions @@ -3137,12 +3137,39 @@ executing a `continue` expression immediately terminates the current iteration of the innermost loop enclosing it, returning control to the loop *head*. In the case of a `while` loop, the head is the conditional expression controlling the loop. In the case of a `for` loop, the head is the call-expression -controlling the loop. If the label is present, then `continue foo` returns -control to the head of the loop with label `foo`, which need not be the +controlling the loop. If the label is present, then `continue 'foo` returns +control to the head of the loop with label `'foo`, which need not be the innermost label enclosing the `break` expression, but must enclose it. A `continue` expression is only permitted in the body of a loop. +### While loops + +```{.ebnf .gram} +while_expr : [ lifetime ':' ] "while" no_struct_literal_expr '{' block '}' ; +``` + +A `while` loop begins by evaluating the boolean loop conditional expression. +If the loop conditional expression evaluates to `true`, the loop body block +executes and control returns to the loop conditional expression. If the loop +conditional expression evaluates to `false`, the `while` expression completes. + +An example: + +``` +let mut i = 0; + +while i < 10 { + println!("hello"); + i = i + 1; +} +``` + +Like `loop` expressions, `while` loops can be controlled with `break` or +`continue`, and may optionally have a _label_. See [infinite +loops](#infinite-loops), [break expressions](#break-expressions), and +[continue expressions](#continue-expressions) for more information. + ### For expressions ```{.ebnf .gram} @@ -3177,6 +3204,11 @@ for i in 0..256 { } ``` +Like `loop` expressions, `for` loops can be controlled with `break` or +`continue`, and may optionally have a _label_. See [infinite +loops](#infinite-loops), [break expressions](#break-expressions), and +[continue expressions](#continue-expressions) for more information. + ### If expressions ```{.ebnf .gram} @@ -3649,23 +3681,23 @@ call_closure(closure_no_args, closure_args); ``` -### Object types +### Trait objects Every trait item (see [traits](#traits)) defines a type with the same name as -the trait. This type is called the _object type_ of the trait. Object types +the trait. This type is called the _trait object_ of the trait. Trait objects permit "late binding" of methods, dispatched using _virtual method tables_ ("vtables"). Whereas most calls to trait methods are "early bound" (statically resolved) to specific implementations at compile time, a call to a method on an -object type is only resolved to a vtable entry at compile time. The actual +trait objects is only resolved to a vtable entry at compile time. The actual implementation for each vtable entry can vary on an object-by-object basis. Given a pointer-typed expression `E` of type `&T` or `Box`, where `T` implements trait `R`, casting `E` to the corresponding pointer type `&R` or -`Box` results in a value of the _object type_ `R`. This result is +`Box` results in a value of the _trait object_ `R`. This result is represented as a pair of pointers: the vtable pointer for the `T` implementation of `R`, and the pointer value of `E`. -An example of an object type: +An example of a trait object: ``` trait Printable { @@ -3685,7 +3717,7 @@ fn main() { } ``` -In this example, the trait `Printable` occurs as an object type in both the +In this example, the trait `Printable` occurs as a trait object in both the type signature of `print`, and the cast expression in `main`. ### Type parameters diff --git a/src/doc/trpl/macros.md b/src/doc/trpl/macros.md index 9fa870ab1ac7c..9d01f104ddaaf 100644 --- a/src/doc/trpl/macros.md +++ b/src/doc/trpl/macros.md @@ -57,8 +57,7 @@ let x: Vec = { We can implement this shorthand, using a macro: [^actual] [^actual]: The actual definition of `vec!` in libcollections differs from the - one presented here, for reasons of efficiency and reusability. Some - of these are mentioned in the [advanced macros chapter][]. + one presented here, for reasons of efficiency and reusability. ```rust macro_rules! vec { @@ -106,7 +105,7 @@ These have [their own little grammar] within the language. The matcher `$x:expr` will match any Rust expression, binding that syntax tree to the ‘metavariable’ `$x`. The identifier `expr` is a ‘fragment specifier’; -the full possibilities are enumerated in the [advanced macros chapter][]. +the full possibilities are enumerated later in this chapter. Surrounding the matcher with `$(...),*` will match zero or more expressions, separated by commas. @@ -566,7 +565,7 @@ When this library is loaded with `#[macro_use] extern crate`, only `m2` will be imported. The Rust Reference has a [listing of macro-related -attributes](../reference.html#macro--and-plugin-related-attributes). +attributes](../reference.html#macro-related-attributes). # The variable `$crate` diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 422439fadc1a1..b3cc133d22946 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -306,6 +306,14 @@ pub struct Iter<'a, T: 'a> { rx: &'a Receiver } +/// An owning iterator over messages on a receiver, this iterator will block +/// whenever `next` is called, waiting for a new message, and `None` will be +/// returned when the corresponding channel has hung up. +#[stable(feature = "receiver_into_iter", since = "1.1.0")] +pub struct IntoIter { + rx: Receiver +} + /// The sending-half of Rust's asynchronous channel type. This half can only be /// owned by one task, but it can be cloned to send to other tasks. #[stable(feature = "rust1", since = "1.0.0")] @@ -899,6 +907,29 @@ impl<'a, T> Iterator for Iter<'a, T> { fn next(&mut self) -> Option { self.rx.recv().ok() } } +#[stable(feature = "receiver_into_iter", since = "1.1.0")] +impl<'a, T> IntoIterator for &'a Receiver { + type Item = T; + type IntoIter = Iter<'a, T>; + + fn into_iter(self) -> Iter<'a, T> { self.iter() } +} + +impl Iterator for IntoIter { + type Item = T; + fn next(&mut self) -> Option { self.rx.recv().ok() } +} + +#[stable(feature = "receiver_into_iter", since = "1.1.0")] +impl IntoIterator for Receiver { + type Item = T; + type IntoIter = IntoIter; + + fn into_iter(self) -> IntoIter { + IntoIter { rx: self } + } +} + #[unsafe_destructor] #[stable(feature = "rust1", since = "1.0.0")] impl Drop for Receiver { @@ -1507,6 +1538,32 @@ mod test { assert_eq!(count_rx.recv().unwrap(), 4); } + #[test] + fn test_recv_into_iter_owned() { + let mut iter = { + let (tx, rx) = channel::(); + tx.send(1).unwrap(); + tx.send(2).unwrap(); + + rx.into_iter() + }; + assert_eq!(iter.next().unwrap(), 1); + assert_eq!(iter.next().unwrap(), 2); + assert_eq!(iter.next().is_none(), true); + } + + #[test] + fn test_recv_into_iter_borrowed() { + let (tx, rx) = channel::(); + tx.send(1).unwrap(); + tx.send(2).unwrap(); + drop(tx); + let mut iter = (&rx).into_iter(); + assert_eq!(iter.next().unwrap(), 1); + assert_eq!(iter.next().unwrap(), 2); + assert_eq!(iter.next().is_none(), true); + } + #[test] fn try_recv_states() { let (tx1, rx1) = channel::(); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index dc577f603f621..68006a8979a64 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1151,8 +1151,8 @@ impl<'a> Parser<'a> { &token::CloseDelim(token::Brace), seq_sep_none(), |p| { - let lo = p.span.lo; let mut attrs = p.parse_outer_attributes(); + let lo = p.span.lo; let (name, node) = if try!(p.eat_keyword(keywords::Type)) { let TyParam {ident, bounds, default, ..} = try!(p.parse_ty_param()); @@ -3409,8 +3409,8 @@ impl<'a> Parser<'a> { } } - let lo = self.span.lo; let attrs = self.parse_outer_attributes(); + let lo = self.span.lo; Ok(Some(if self.check_keyword(keywords::Let) { check_expected_item(self, &attrs); @@ -4304,8 +4304,8 @@ impl<'a> Parser<'a> { /// Parse an impl item. pub fn parse_impl_item(&mut self) -> PResult> { - let lo = self.span.lo; let mut attrs = self.parse_outer_attributes(); + let lo = self.span.lo; let vis = try!(self.parse_visibility()); let (name, node) = if try!(self.eat_keyword(keywords::Type)) { let name = try!(self.parse_ident()); @@ -5380,9 +5380,8 @@ impl<'a> Parser<'a> { /// Parse a foreign item. fn parse_foreign_item(&mut self) -> PResult>> { - let lo = self.span.lo; - let attrs = self.parse_outer_attributes(); + let lo = self.span.lo; let visibility = try!(self.parse_visibility()); if self.check_keyword(keywords::Static) {