esac
}
+# Prints the absolute path of a directory to stdout
+abs_path() {
+ local _path="$1"
+ # Unset CDPATH because it causes havok: it makes the destination unpredictable
+ # and triggers 'cd' to print the path to stdout. Route `cd`'s output to /dev/null
+ # for good measure.
+ (unset CDPATH && cd "$_path" > /dev/null && pwd)
+}
+
msg "looking for configure programs"
need_cmd cmp
need_cmd mkdir
DEFAULT_BUILD="${CFG_CPUTYPE}-${CFG_OSTYPE}"
-CFG_SRC_DIR="$(cd $(dirname $0) && pwd)/"
+CFG_SRC_DIR="$(abs_path $(dirname $0))/"
CFG_BUILD_DIR="$(pwd)/"
CFG_SELF="$0"
CFG_CONFIGURE_ARGS="$@"
CFG_DISABLE_UNSTABLE_FEATURES=1
endif
ifeq ($(CFG_RELEASE_CHANNEL),beta)
-CFG_RELEASE=$(CFG_RELEASE_NUM)-beta$(CFG_PRERELEASE_VERSION)
-CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)-beta$(CFG_PRERELEASE_VERSION)
+CFG_RELEASE=$(CFG_RELEASE_NUM)-beta
+# When building beta distributables just reuse the same "beta" name
+# so when we upload we'll always override the previous beta. This
+# doesn't actually impact the version reported by rustc - it's just
+# for file naming.
+CFG_PACKAGE_VERS=beta
CFG_DISABLE_UNSTABLE_FEATURES=1
endif
ifeq ($(CFG_RELEASE_CHANNEL),nightly)
PRETTY_DEPS_pretty-rfail = $(RFAIL_TESTS)
PRETTY_DEPS_pretty-bench = $(BENCH_TESTS)
PRETTY_DEPS_pretty-pretty = $(PRETTY_TESTS)
-# The stage- and host-specific dependencies are for e.g. macro_crate_test which pulls in
-# external crates.
-PRETTY_DEPS$(1)_H_$(3)_pretty-rpass =
-PRETTY_DEPS$(1)_H_$(3)_pretty-rpass-full = $$(HLIB$(1)_H_$(3))/stamp.syntax $$(HLIB$(1)_H_$(3))/stamp.rustc
-PRETTY_DEPS$(1)_H_$(3)_pretty-rfail =
-PRETTY_DEPS$(1)_H_$(3)_pretty-bench =
-PRETTY_DEPS$(1)_H_$(3)_pretty-pretty =
PRETTY_DIRNAME_pretty-rpass = run-pass
PRETTY_DIRNAME_pretty-rpass-valgrind = run-pass-valgrind
PRETTY_DIRNAME_pretty-rpass-full = run-pass-fulldeps
PRETTY_DIRNAME_pretty-bench = bench
PRETTY_DIRNAME_pretty-pretty = pretty
+define DEF_PRETTY_FULLDEPS
+PRETTY_DEPS$(1)_T_$(2)_H_$(3)_pretty-rpass-full = $$(CSREQ$(1)_T_$(3)_H_$(3))
+endef
+
+$(foreach host,$(CFG_HOST), \
+ $(foreach target,$(CFG_TARGET), \
+ $(foreach stage,$(STAGES), \
+ $(eval $(call DEF_PRETTY_FULLDEPS,$(stage),$(target),$(host))))))
+
define DEF_RUN_PRETTY_TEST
PRETTY_ARGS$(1)-T-$(2)-H-$(3)-$(4) := \
$$(call TEST_OK_FILE,$(1),$(2),$(3),$(4)): \
$$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \
$$(PRETTY_DEPS_$(4)) \
- $$(PRETTY_DEPS$(1)_H_$(3)_$(4))
+ $$(PRETTY_DEPS$(1)_T_$(2)_H_$(3)_$(4))
@$$(call E, run pretty-rpass [$(2)]: $$<)
$$(Q)touch $$@.start_time
$$(Q)$$(call CFG_RUN_CTEST_$(2),$(1),$$<,$(3)) \
// is the ending point, and * represents ANSI color codes.
for line in proc_res.stderr.lines() {
let mut was_expected = false;
+ let mut prev = 0;
for (i, ee) in expected_errors.iter().enumerate() {
if !found_flags[i] {
debug!("prefix={} ee.kind={} ee.msg={} line={}",
ee.kind,
ee.msg,
line);
+ // Suggestions have no line number in their output, so take on the line number of
+ // the previous expected error
+ if ee.kind == "suggestion" {
+ assert!(expected_errors[prev].kind == "help",
+ "SUGGESTIONs must be preceded by a HELP");
+ if line.contains(&ee.msg) {
+ found_flags[i] = true;
+ was_expected = true;
+ break;
+ }
+ }
if (prefix_matches(line, &prefixes[i]) || continuation(line)) &&
line.contains(&ee.kind) &&
line.contains(&ee.msg) {
break;
}
}
+ prev = i;
}
// ignore this msg which gets printed at the end
fn aux_output_dir_name(config: &Config, testfile: &Path) -> PathBuf {
let f = output_base_name(config, testfile);
let mut fname = f.file_name().unwrap().to_os_string();
- fname.push("libaux");
+ fname.push(&format!(".{}.libaux", config.mode));
f.with_file_name(&fname)
}
# Notation
-Rust's grammar is defined over Unicode codepoints, each conventionally denoted
+Rust's grammar is defined over Unicode code points, each conventionally denoted
`U+XXXX`, for 4 or more hexadecimal digits `X`. _Most_ of Rust's grammar is
confined to the ASCII range of Unicode, and is described in this document by a
dialect of Extended Backus-Naur Form (EBNF), specifically a dialect of EBNF
- Square brackets are used to group rules.
- `LITERAL` is a single printable ASCII character, or an escaped hexadecimal
ASCII code of the form `\xQQ`, in single quotes, denoting the corresponding
- Unicode codepoint `U+00QQ`.
+ Unicode code point `U+00QQ`.
- `IDENTIFIER` is a nonempty string of ASCII letters and underscores.
- The `repeat` forms apply to the adjacent `element`, and are as follows:
- `?` means zero or one repetition
## Unicode productions
-A few productions in Rust's grammar permit Unicode codepoints outside the ASCII
+A few productions in Rust's grammar permit Unicode code points outside the ASCII
range. We define these productions in terms of character properties specified
-in the Unicode standard, rather than in terms of ASCII-range codepoints. The
+in the Unicode standard, rather than in terms of ASCII-range code points. The
section [Special Unicode Productions](#special-unicode-productions) lists these
productions.
## Input format
-Rust input is interpreted as a sequence of Unicode codepoints encoded in UTF-8.
+Rust input is interpreted as a sequence of Unicode code points encoded in UTF-8.
Most Rust grammar rules are defined in terms of printable ASCII-range
-codepoints, but a small number are defined in terms of Unicode properties or
-explicit codepoint lists. [^inputformat]
+code points, but a small number are defined in terms of Unicode properties or
+explicit code point lists. [^inputformat]
[^inputformat]: Substitute definitions for the special Unicode productions are
provided to the grammar verifier, restricted to ASCII range, when verifying the
sequence (`/**`), are interpreted as a special syntax for `doc`
[attributes](#attributes). That is, they are equivalent to writing
`#[doc="..."]` around the body of the comment (this includes the comment
-characters themselves, ie `/// Foo` turns into `#[doc="/// Foo"]`).
+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.
| 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
literals. An escape starts with a `U+005C` (`\`) and continues with one of the
following forms:
-* An _8-bit codepoint escape_ escape starts with `U+0078` (`x`) and is
- followed by exactly two _hex digits_. It denotes the Unicode codepoint
+* An _8-bit code point escape_ starts with `U+0078` (`x`) and is
+ followed by exactly two _hex digits_. It denotes the Unicode code point
equal to the provided hex value.
-* A _24-bit codepoint escape_ starts with `U+0075` (`u`) and is followed
+* A _24-bit code point escape_ starts with `U+0075` (`u`) and is followed
by up to six _hex digits_ surrounded by braces `U+007B` (`{`) and `U+007D`
- (`}`). It denotes the Unicode codepoint equal to the provided hex value.
+ (`}`). It denotes the Unicode code point equal to the provided hex value.
* A _whitespace escape_ is one of the characters `U+006E` (`n`), `U+0072`
- (`r`), or `U+0074` (`t`), denoting the unicode values `U+000A` (LF),
+ (`r`), or `U+0074` (`t`), denoting the Unicode values `U+000A` (LF),
`U+000D` (CR) or `U+0009` (HT) respectively.
* The _backslash escape_ is the character `U+005C` (`\`) which must be
escaped in order to denote *itself*.
literals. An escape starts with a `U+005C` (`\`) and continues with one of the
following forms:
-* An _byte escape_ escape starts with `U+0078` (`x`) and is
+* A _byte escape_ escape starts with `U+0078` (`x`) and is
followed by exactly two _hex digits_. It denotes the byte
equal to the provided hex value.
* A _whitespace escape_ is one of the characters `U+006E` (`n`), `U+0072`
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 parens, 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 parens 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
angle-bracket-enclosed, comma-separated list following the function name.
```{.ignore}
-fn iter<T>(seq: &[T], f: |T|) {
- for elt in seq.iter() { f(elt); }
+fn iter<T, F>(seq: &[T], f: F) where T: Copy, F: Fn(T) {
+ for elt in seq { f(*elt); }
}
-fn map<T, U>(seq: &[T], f: |T| -> U) -> Vec<U> {
+fn map<T, U, F>(seq: &[T], f: F) -> Vec<U> 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::<u32>() == 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<T>(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
[noalias]: http://llvm.org/docs/LangRef.html#noalias
-##### Behaviour not considered unsafe
+##### Behavior not considered unsafe
-This is a list of behaviour not considered *unsafe* in Rust terms, but that may
+This is a list of behavior not considered *unsafe* in Rust terms, but that may
be undesired.
* Deadlocks
several different type constraints.
For example, the following defines the type `Point` as a synonym for the type
-`(u8, u8)`, the type of pairs of unsigned 8 bit integers.:
+`(u8, u8)`, the type of pairs of unsigned 8 bit integers:
```
type Point = (u8, u8);
}
```
-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.
### Crate-only attributes
-- `crate_name` - specify the this crate's crate name.
+- `crate_name` - specify the crate's crate name.
- `crate_type` - see [linkage](#linkage).
- `feature` - see [compiler features](#compiler-features).
- `no_builtins` - disable optimizing certain code patterns to invocations of
`"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
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
(["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,
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.
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
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
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}
}
```
+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}
UTF-32 string.
A value of type `str` is a Unicode string, represented as an array of 8-bit
-unsigned bytes holding a sequence of UTF-8 codepoints. Since `str` is of
+unsigned bytes holding a sequence of UTF-8 code points. Since `str` is of
unknown size, it is not a _first-class_ type, but can only be instantiated
through a pointer type, such as `&str` or `String`.
```
-### 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<T>`, where `T`
implements trait `R`, casting `E` to the corresponding pointer type `&R` or
-`Box<R>` results in a value of the _object type_ `R`. This result is
+`Box<R>` 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 {
}
```
-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
* [Learn Rust](learn-rust.md)
* [Effective Rust](effective-rust.md)
* [The Stack and the Heap](the-stack-and-the-heap.md)
- * [Debug and Display](debug-and-display.md)
* [Testing](testing.md)
+ * [Conditional Compilation](conditional-compilation.md)
* [Documentation](documentation.md)
* [Iterators](iterators.md)
* [Concurrency](concurrency.md)
* [`const` and `static`](const-and-static.md)
* [Tuple Structs](tuple-structs.md)
* [Attributes](attributes.md)
- * [Conditional Compilation](conditional-compilation.md)
* [`type` aliases](type-aliases.md)
* [Casting between types](casting-between-types.md)
* [Associated Types](associated-types.md)
% Attributes
-Coming Soon!
+Declarations can be annotated with ‘attributes’ in Rust. They look like this:
+
+```rust
+#[test]
+# fn foo() {}
+```
+
+or like this:
+
+```rust
+# mod foo {
+#![test]
+# }
+```
+
+The difference between the two is the `!`, which changes what the attribute
+applies to:
+
+```rust,ignore
+#[foo]
+struct Foo;
+
+mod bar {
+ #![bar]
+}
+```
+
+The `#[foo]` attribute applies to the next item, which is the `struct`
+declaration. The `#![bar]` attribute applies to the item enclosing it, which is
+the `mod` declaration. Otherwise, they’re the same. Both change the meaning of
+the item they’re attached to somehow.
+
+For example, consider a function like this:
+
+```rust
+#[test]
+fn check() {
+ assert_eq!(2, 1 + 1);
+}
+```
+
+It is marked with `#[test]`. This means it’s special: when you run
+[tests][tests], this function will execute. When you compile as usual, it won’t
+even be included. This function is now a test function.
+
+[tests]: testing.html
+
+Attributes may also have additional data:
+
+```rust
+#[inline(always)]
+fn super_fast_fn() {
+# }
+```
+
+Or even keys and values:
+
+```rust
+#[cfg(target_os = "macos")]
+mod macos_only {
+# }
+```
+
+Rust attributes are used for a number of different things. There is a full list
+of attributes [in the reference][reference]. Currently, you are not allowed to
+create your own attributes, the Rust compiler defines them.
+
+[reference]: reference.html#attributes
% Conditional Compilation
-Coming Soon!
+Rust has a special attribute, `#[cfg]`, which allows you to compile code
+based on a flag passed to the compiler. It has two forms:
+
+```rust
+#[cfg(foo)]
+# fn foo() {}
+
+#[cfg(bar = "baz")]
+# fn bar() {}
+```
+
+They also have some helpers:
+
+```rust
+#[cfg(any(unix, windows))]
+# fn foo() {}
+
+#[cfg(all(unix, target_pointer_width = "32"))]
+# fn bar() {}
+
+#[cfg(not(foo))]
+# fn not_foo() {}
+```
+
+These can nest arbitrarily:
+
+```rust
+#[cfg(any(not(unix), all(target_os="macos", target_arch = "powerpc")))]
+# fn foo() {}
+```
+
+As for how to enable or disable these switches, if you’re using Cargo,
+they get set in the [`[features]` section][features] of your `Cargo.toml`:
+
+[features]: http://doc.crates.io/manifest.html#the-[features]-section
+
+```toml
+[features]
+# no features by default
+default = []
+
+# The “secure-password” feature depends on the bcrypt package.
+secure-password = ["bcrypt"]
+```
+
+When you do this, Cargo passes along a flag to `rustc`:
+
+```text
+--cfg feature="${feature_name}"
+```
+
+The sum of these `cfg` flags will determine which ones get activated, and
+therefore, which code gets compiled. Let’s take this code:
+
+```rust
+#[cfg(feature = "foo")]
+mod foo {
+}
+```
+
+If we compile it with `cargo build --features "foo"`, it will send the `--cfg
+feature="foo"` flag to `rustc`, and the output will have the `mod foo` in it.
+If we compile it with a regular `cargo build`, no extra flags get passed on,
+and so, no `foo` module will exist.
+
+# cfg_attr
+
+You can also set another attribute based on a `cfg` variable with `cfg_attr`:
+
+```rust
+#[cfg_attr(a, b)]
+# fn foo() {}
+```
+
+Will be the same as `#[b]` if `a` is set by `cfg` attribute, and nothing otherwise.
+
+# cfg!
+
+The `cfg!` [syntax extension][compilerplugins] lets you use these kinds of flags
+elsewhere in your code, too:
+
+```rust
+if cfg!(target_os = "macos") || cfg!(target_os = "ios") {
+ println!("Think Different!");
+}
+```
+
+[compilerplugins]: compiler-plugins.html
+
+These will be replaced by a `true` or `false` at compile-time, depending on the
+configuration settings.
+++ /dev/null
-% Debug and Display
-
-Coming soon!
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 {
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.
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`
% `type` Aliases
-Coming soon
+The `type` keyword lets you declare an alias of another type:
+
+```rust
+type Name = String;
+```
+
+You can then use this type as if it were a real type:
+
+```rust
+type Name = String;
+
+let x: Name = "Hello".to_string();
+```
+
+Note, however, that this is an _alias_, not a new type entirely. In other
+words, because Rust is strongly typed, you’d expect a comparison between two
+different types to fail:
+
+```rust,ignore
+let x: i32 = 5;
+let y: i64 = 5;
+
+if x == y {
+ // ...
+}
+```
+
+this gives
+
+```text
+error: mismatched types:
+ expected `i32`,
+ found `i64`
+(expected i32,
+ found i64) [E0308]
+ if x == y {
+ ^
+```
+
+But, if we had an alias:
+
+```rust
+type Num = i32;
+
+let x: i32 = 5;
+let y: Num = 5;
+
+if x == y {
+ // ...
+}
+```
+
+This compiles without error. Values of a `Num` type are the same as a value of
+type `i32`, in every way.
+
+You can also use type aliases with generics:
+
+```rust
+use std::result;
+
+enum ConcreteError {
+ Foo,
+ Bar,
+}
+
+type Result<T> = result::Result<T, ConcreteError>;
+```
+
+This creates a specialized version of the `Result` type, which always has a
+`ConcreteError` for the `E` part of `Result<T, E>`. This is commonly used
+in the standard library to create custom errors for each subsection. For
+example, [io::Result][ioresult].
+
+[ioresult]: ../std/io/type.Result.html
% Universal Function Call Syntax
-Coming soon
+Sometimes, functions can have the same names. Consider this code:
+
+```rust
+trait Foo {
+ fn f(&self);
+}
+
+trait Bar {
+ fn f(&self);
+}
+
+struct Baz;
+
+impl Foo for Baz {
+ fn f(&self) { println!("Baz’s impl of Foo"); }
+}
+
+impl Bar for Baz {
+ fn f(&self) { println!("Baz’s impl of Bar"); }
+}
+
+let b = Baz;
+```
+
+If we were to try to call `b.f()`, we’d get an error:
+
+```text
+error: multiple applicable methods in scope [E0034]
+b.f();
+ ^~~
+note: candidate #1 is defined in an impl of the trait `main::Foo` for the type
+`main::Baz`
+ fn f(&self) { println!("Baz’s impl of Foo"); }
+ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+note: candidate #2 is defined in an impl of the trait `main::Bar` for the type
+`main::Baz`
+ fn f(&self) { println!("Baz’s impl of Bar"); }
+ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+```
+
+We need a way to disambiguate which method we need. This feature is called
+‘universal function call syntax’, and it looks like this:
+
+```rust
+# trait Foo {
+# fn f(&self);
+# }
+# trait Bar {
+# fn f(&self);
+# }
+# struct Baz;
+# impl Foo for Baz {
+# fn f(&self) { println!("Baz’s impl of Foo"); }
+# }
+# impl Bar for Baz {
+# fn f(&self) { println!("Baz’s impl of Bar"); }
+# }
+# let b = Baz;
+Foo::f(&b);
+Bar::f(&b);
+```
+
+Let’s break it down.
+
+```rust,ignore
+Foo::
+Bar::
+```
+
+These halves of the invocation are the types of the two traits: `Foo` and
+`Bar`. This is what ends up actually doing the disambiguation between the two:
+Rust calls the one from the trait name you use.
+
+```rust,ignore
+f(&b)
+```
+
+When we call a method like `b.f()` using [method syntax][methodsyntax], Rust
+will automatically borrow `b` if `f()` takes `&self`. In this case, Rust will
+not, and so we need to pass an explicit `&b`.
+
+[methodsyntax]: method-syntax.html
+
+# Angle-bracket Form
+
+The form of UFCS we just talked about:
+
+```rust,ignore
+Type::method(args);
+```
+
+Is a short-hand. There’s an expanded form of this that’s needed in some
+situations:
+
+```rust,ignore
+<Type as Trait>::method(args);
+```
+
+The `<>::` syntax is a means of providing a type hint. The type goes inside
+the `<>`s. In this case, the type is `Type as Trait`, indicating that we want
+`Trait`’s version of `method` to be called here. The `as Trait` part is
+optional if it’s not ambiguous. Same with the angle brackets, hence the
+shorter form.
+
+Here’s an example of using the longer form.
+
+```rust
+trait Foo {
+ fn clone(&self);
+}
+
+#[derive(Clone)]
+struct Bar;
+
+impl Foo for Bar {
+ fn clone(&self) {
+ println!("Making a clone of Bar");
+
+ <Bar as Clone>::clone(self);
+ }
+}
+```
+
+This will call the `Clone` trait’s `clone()` method, rather than `Foo`’s.
% Unsized Types
-Coming Soon!
+Most types have a particular size, in bytes, that is knowable at compile time.
+For example, an `i32` is thirty-two bits big, or four bytes. However, there are
+some types which are useful to express, but do not have a defined size. These are
+called ‘unsized’ or ‘dynamically sized’ types. One example is `[T]`. This type
+represents a certain number of `T` in sequence. But we don’t know how many
+there are, so the size is not known.
+
+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.
+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
+ data.
+
+So why bother? Well, because `[T]` can only be used behind a pointer, if we
+didn’t have language support for unsized types, it would be impossible to write
+this:
+
+```rust,ignore
+impl Foo for str {
+```
+
+or
+
+```rust,ignore
+impl<T> Foo for [T] {
+```
+
+Instead, you would have to write:
+
+```rust,ignore
+impl Foo for &str {
+```
+
+Meaning, this implementation would only work for [references][ref], and not
+other types of pointers. With this `impl`, all pointers, including (at some
+point, there are some bugs to fix first) user-defined custom smart pointers,
+can use this `impl`.
+
+# ?Sized
+
+If you want to write a function that accepts a dynamically sized type, you
+can use the special bound, `?Sized`:
+
+```rust
+struct Foo<T: ?Sized> {
+ f: T,
+}
+```
+
+This `?`, read as “T may be `Sized`”, means that this bound is special: it
+lets us match more kinds, not less. It’s almost like every `T` implicitly has
+`T: Sized`, and the `?` undoes this default.
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Default + Sync + Send> Default for Arc<T> {
+impl<T: Default> Default for Arc<T> {
#[stable(feature = "rust1", since = "1.0.0")]
fn default() -> Arc<T> { Arc::new(Default::default()) }
}
/// `TraitObject` is guaranteed to match layouts, but it is not the
/// type of trait objects (e.g. the fields are not directly accessible
/// on a `&SomeTrait`) nor does it control that layout (changing the
-/// definition will not change the layout of a `&SometTrait`). It is
+/// definition will not change the layout of a `&SomeTrait`). It is
/// only designed to be used by unsafe code that needs to manipulate
/// the low-level details.
///
into a variable called `op_string` while simultaneously requiring the inner
String to be moved into a variable called `s`.
+```
let x = Some("s".to_string());
match x {
op_string @ Some(s) => ...
None => ...
}
+```
See also Error 303.
"##,
referenced in the pattern guard code. Doing so however would prevent the name
from being available in the body of the match arm. Consider the following:
+```
match Some("hi".to_string()) {
Some(s) if s.len() == 0 => // use s.
...
}
+```
The variable `s` has type String, and its use in the guard is as a variable of
type String. The guard code effectively executes in a separate scope to the body
innocuous, the problem is most clear when considering functions that take their
argument by value.
+```
match Some("hi".to_string()) {
Some(s) if { drop(s); false } => (),
Some(s) => // use s.
...
}
+```
The value would be dropped in the guard then become unavailable not only in the
body of that arm but also in all subsequent arms! The solution is to bind by
You can build a free-standing crate by adding `#![no_std]` to the crate
attributes:
+```
#![feature(no_std)]
#![no_std]
+```
See also https://doc.rust-lang.org/book/no-stdlib.html
"##,
If you want to match against a `static`, consider using a guard instead:
+```
static FORTY_TWO: i32 = 42;
match Some(42) {
Some(x) if x == FORTY_TWO => ...
...
}
+```
"##,
E0161: r##"
match was succesful. If the match is irrefutable (when it cannot fail to match),
use a regular `let`-binding instead. For instance:
+```
struct Irrefutable(i32);
let irr = Irrefutable(0);
// Try this instead:
let Irrefutable(x) = irr;
foo(x);
+```
"##,
E0165: r##"
match was succesful. If the match is irrefutable (when it cannot fail to match),
use a regular `let`-binding inside a `loop` instead. For instance:
+```
struct Irrefutable(i32);
let irr = Irrefutable(0);
let Irrefutable(x) = irr;
...
}
+```
"##,
E0170: r##"
Enum variants are qualified by default. For example, given this type:
+```
enum Method {
GET,
POST
}
+```
you would match it using:
+```
match m {
Method::GET => ...
Method::POST => ...
}
+```
If you don't qualify the names, the code will bind new variables named "GET" and
"POST" instead. This behavior is likely not what you want, so rustc warns when
Qualified names are good practice, and most code works well with them. But if
you prefer them unqualified, you can import the variants into scope:
+```
use Method::*;
enum Method { GET, POST }
+```
"##,
E0267: r##"
This error indicates that the given recursion limit could not be parsed. Ensure
that the value provided is a positive integer between quotes, like so:
+```
#![recursion_limit="1000"]
+```
"##,
E0297: r##"
loop variable, consider using a `match` or `if let` inside the loop body. For
instance:
+```
// This fails because `None` is not covered.
for Some(x) in xs {
...
...
}
}
+```
"##,
E0301: r##"
exhaustive. For instance, the following would not match any arm if mutable
borrows were allowed:
+```
match Some(()) {
None => { },
option if option.take().is_none() => { /* impossible, option is `Some` */ },
Some(_) => { } // When the previous match failed, the option became `None`.
}
+```
"##,
E0302: r##"
exhaustive. For instance, the following would not match any arm if assignments
were allowed:
+```
match Some(()) {
None => { },
option if { option = None; false } { },
Some(_) => { } // When the previous match failed, the option became `None`.
}
+```
"##,
E0303: r##"
Updates to the borrow checker in a future version of Rust may remove this
restriction, but for now patterns must be rewritten without sub-bindings.
-// Before.
-match Some("hi".to_string()) {
- ref op_string_ref @ Some(ref s) => ...
+```
+// Code like this...
+match Some(5) {
+ ref op_num @ Some(num) => ...
None => ...
}
}
None => ...
}
+```
The `op_string_ref` binding has type &Option<&String> in both cases.
obligation.repr(self.tcx()));
self.infcx.probe(|snapshot| {
- let (skol_obligation_trait_ref, skol_map) =
- self.infcx().skolemize_late_bound_regions(&obligation.predicate, snapshot);
- match self.match_impl(impl_def_id, obligation, snapshot,
- &skol_map, skol_obligation_trait_ref.trait_ref.clone()) {
- Ok(substs) => {
+ match self.match_impl(impl_def_id, obligation, snapshot) {
+ Ok((substs, skol_map)) => {
let vtable_impl = self.vtable_impl(impl_def_id,
substs,
obligation.cause.clone(),
let all_impls = self.all_impls(def_id);
for &impl_def_id in &all_impls {
self.infcx.probe(|snapshot| {
- let (skol_obligation_trait_pred, skol_map) =
- self.infcx().skolemize_late_bound_regions(&obligation.predicate, snapshot);
- match self.match_impl(impl_def_id, obligation, snapshot,
- &skol_map, skol_obligation_trait_pred.trait_ref.clone()) {
+ match self.match_impl(impl_def_id, obligation, snapshot) {
Ok(_) => {
candidates.vec.push(ImplCandidate(impl_def_id));
}
// First, create the substitutions by matching the impl again,
// this time not in a probe.
self.infcx.commit_if_ok(|snapshot| {
- let (skol_obligation_trait_ref, skol_map) =
- self.infcx().skolemize_late_bound_regions(&obligation.predicate, snapshot);
- let substs =
+ let (substs, skol_map) =
self.rematch_impl(impl_def_id, obligation,
- snapshot, &skol_map, skol_obligation_trait_ref.trait_ref);
+ snapshot);
debug!("confirm_impl_candidate substs={}", substs.repr(self.tcx()));
Ok(self.vtable_impl(impl_def_id, substs, obligation.cause.clone(),
obligation.recursion_depth + 1, skol_map, snapshot))
fn rematch_impl(&mut self,
impl_def_id: ast::DefId,
obligation: &TraitObligation<'tcx>,
- snapshot: &infer::CombinedSnapshot,
- skol_map: &infer::SkolemizationMap,
- skol_obligation_trait_ref: Rc<ty::TraitRef<'tcx>>)
- -> Normalized<'tcx, Substs<'tcx>>
+ snapshot: &infer::CombinedSnapshot)
+ -> (Normalized<'tcx, Substs<'tcx>>, infer::SkolemizationMap)
{
- match self.match_impl(impl_def_id, obligation, snapshot,
- skol_map, skol_obligation_trait_ref) {
- Ok(substs) => substs,
+ match self.match_impl(impl_def_id, obligation, snapshot) {
+ Ok((substs, skol_map)) => (substs, skol_map),
Err(()) => {
self.tcx().sess.bug(
&format!("Impl {} was matchable against {} but now is not",
fn match_impl(&mut self,
impl_def_id: ast::DefId,
obligation: &TraitObligation<'tcx>,
- snapshot: &infer::CombinedSnapshot,
- skol_map: &infer::SkolemizationMap,
- skol_obligation_trait_ref: Rc<ty::TraitRef<'tcx>>)
- -> Result<Normalized<'tcx, Substs<'tcx>>, ()>
+ snapshot: &infer::CombinedSnapshot)
+ -> Result<(Normalized<'tcx, Substs<'tcx>>,
+ infer::SkolemizationMap), ()>
{
let impl_trait_ref = ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap();
return Err(());
}
+ let (skol_obligation, skol_map) = self.infcx().skolemize_late_bound_regions(
+ &obligation.predicate,
+ snapshot);
+ let skol_obligation_trait_ref = skol_obligation.trait_ref;
+
let impl_substs = util::fresh_type_vars_for_impl(self.infcx,
obligation.cause.span,
impl_def_id);
return Err(());
}
- if let Err(e) = self.infcx.leak_check(skol_map, snapshot) {
+ if let Err(e) = self.infcx.leak_check(&skol_map, snapshot) {
debug!("match_impl: failed leak check due to `{}`",
ty::type_err_to_str(self.tcx(), &e));
return Err(());
}
debug!("match_impl: success impl_substs={}", impl_substs.repr(self.tcx()));
- Ok(Normalized {
+ Ok((Normalized {
value: impl_substs,
obligations: impl_trait_ref.obligations
- })
+ }, skol_map))
}
fn fast_reject_trait_refs(&mut self,
uses it like a function name",
path_name));
- let msg = format!("Did you mean to write: \
+ let msg = format!("did you mean to write: \
`{} {{ /* fields */ }}`?",
path_name);
if self.emit_errors {
uses it like a function name",
path_name));
- let msg = format!("Did you mean to write: \
+ let msg = format!("did you mean to write: \
`{} {{ /* fields */ }}`?",
path_name);
if self.emit_errors {
use std::rc::Rc;
use std::slice;
use syntax::{abi, ast, ast_util};
-use syntax::codemap::Span;
+use syntax::codemap::{Span, Pos};
use syntax::parse::token;
use syntax::print::pprust;
span_err!(this.tcx().sess, ty.span, E0178,
"expected a path on the left-hand side of `+`, not `{}`",
pprust::ty_to_string(ty));
- match ty.node {
- ast::TyRptr(None, ref mut_ty) => {
- fileline_help!(this.tcx().sess, ty.span,
- "perhaps you meant `&{}({} +{})`? (per RFC 438)",
- ppaux::mutability_to_string(mut_ty.mutbl),
- pprust::ty_to_string(&*mut_ty.ty),
- pprust::bounds_to_string(bounds));
+ let hi = bounds.iter().map(|x| match *x {
+ ast::TraitTyParamBound(ref tr, _) => tr.span.hi,
+ ast::RegionTyParamBound(ref r) => r.span.hi,
+ }).max_by(|x| x.to_usize());
+ let full_span = hi.map(|hi| Span {
+ lo: ty.span.lo,
+ hi: hi,
+ expn_id: ty.span.expn_id,
+ });
+ match (&ty.node, full_span) {
+ (&ast::TyRptr(None, ref mut_ty), Some(full_span)) => {
+ this.tcx().sess
+ .span_suggestion(full_span, "try adding parentheses (per RFC 438):",
+ format!("&{}({} +{})",
+ ppaux::mutability_to_string(mut_ty.mutbl),
+ pprust::ty_to_string(&*mut_ty.ty),
+ pprust::bounds_to_string(bounds)));
}
- ast::TyRptr(Some(ref lt), ref mut_ty) => {
- fileline_help!(this.tcx().sess, ty.span,
- "perhaps you meant `&{} {}({} +{})`? (per RFC 438)",
- pprust::lifetime_to_string(lt),
- ppaux::mutability_to_string(mut_ty.mutbl),
- pprust::ty_to_string(&*mut_ty.ty),
- pprust::bounds_to_string(bounds));
+ (&ast::TyRptr(Some(ref lt), ref mut_ty), Some(full_span)) => {
+ this.tcx().sess
+ .span_suggestion(full_span, "try adding parentheses (per RFC 438):",
+ format!("&{} {}({} +{})",
+ pprust::lifetime_to_string(lt),
+ ppaux::mutability_to_string(mut_ty.mutbl),
+ pprust::ty_to_string(&*mut_ty.ty),
+ pprust::bounds_to_string(bounds)));
}
_ => {
ast::MutImmutable => ""
};
if ty::type_is_trait(t_1) {
- span_help!(fcx.tcx().sess, t_span, "did you mean `&{}{}`?", mtstr, tstr);
+ match fcx.tcx().sess.codemap().span_to_snippet(t_span) {
+ Ok(s) => {
+ fcx.tcx().sess.span_suggestion(t_span,
+ "try casting to a reference instead:",
+ format!("&{}{}", mtstr, s));
+ },
+ Err(_) =>
+ span_help!(fcx.tcx().sess, t_span,
+ "did you mean `&{}{}`?", mtstr, tstr),
+ }
} else {
span_help!(fcx.tcx().sess, span,
"consider using an implicit coercion to `&{}{}` instead",
}
}
ty::ty_uniq(..) => {
- span_help!(fcx.tcx().sess, t_span, "did you mean `Box<{}>`?", tstr);
+ match fcx.tcx().sess.codemap().span_to_snippet(t_span) {
+ Ok(s) => {
+ fcx.tcx().sess.span_suggestion(t_span,
+ "try casting to a `Box` instead:",
+ format!("Box<{}>", s));
+ },
+ Err(_) =>
+ span_help!(fcx.tcx().sess, t_span, "did you mean `Box<{}>`?", tstr),
+ }
}
_ => {
span_help!(fcx.tcx().sess, e_span,
try!(write!(fmt, "<span class='out-of-band'>"));
try!(write!(fmt,
r##"<span id='render-detail'>
- <a id="collapse-all" href="#">[-]</a> <a id="expand-all" href="#">[+]</a>
+ <a id="toggle-all-docs" href="#" title="collapse all docs">[-]</a>
</span>"##));
// Write `src` tag
match self.href(self.cx) {
Some(l) => {
try!(write!(fmt, "<a id='src-{}' class='srclink' \
- href='{}'>[src]</a>",
- self.item.def_id.node, l));
+ href='{}' title='{}'>[src]</a>",
+ self.item.def_id.node, l, "goto source code"));
}
None => {}
}
window.location = $('.srclink').attr('href');
}
- $("#expand-all").on("click", function() {
- $(".docblock").show();
- $(".toggle-label").hide();
- $(".toggle-wrapper").removeClass("collapsed");
- $(".collapse-toggle").children(".inner").html("-");
- });
-
- $("#collapse-all").on("click", function() {
- $(".docblock").hide();
- $(".toggle-label").show();
- $(".toggle-wrapper").addClass("collapsed");
- $(".collapse-toggle").children(".inner").html("+");
+ $("#toggle-all-docs").on("click", function() {
+ var toggle = $("#toggle-all-docs");
+ if (toggle.html() == "[-]") {
+ toggle.html("[+]");
+ toggle.attr("title", "expand all docs");
+ $(".docblock").hide();
+ $(".toggle-label").show();
+ $(".toggle-wrapper").addClass("collapsed");
+ $(".collapse-toggle").children(".inner").html("+");
+ } else {
+ toggle.html("[-]");
+ toggle.attr("title", "collapse all docs");
+ $(".docblock").show();
+ $(".toggle-label").hide();
+ $(".toggle-wrapper").removeClass("collapsed");
+ $(".collapse-toggle").children(".inner").html("-");
+ }
});
$(document).on("click", ".collapse-toggle", function() {
///
/// This handle implements the `Read` trait, but beware that concurrent reads
/// of `Stdin` must be executed with care.
+///
+/// Created by the function `io::stdin()`.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Stdin {
inner: Arc<Mutex<BufReader<StdinRaw>>>,
/// Each handle shares a global buffer of data to be written to the standard
/// output stream. Access is also synchronized via a lock and explicit control
/// over locking is available via the `lock` method.
+///
+/// Created by the function `io::stdout()`.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Stdout {
// FIXME: this should be LineWriter or BufWriter depending on the state of
rx: &'a Receiver<T>
}
+/// 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<T> {
+ rx: Receiver<T>
+}
+
/// 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")]
fn next(&mut self) -> Option<T> { self.rx.recv().ok() }
}
+#[stable(feature = "receiver_into_iter", since = "1.1.0")]
+impl<'a, T> IntoIterator for &'a Receiver<T> {
+ type Item = T;
+ type IntoIter = Iter<'a, T>;
+
+ fn into_iter(self) -> Iter<'a, T> { self.iter() }
+}
+
+impl<T> Iterator for IntoIter<T> {
+ type Item = T;
+ fn next(&mut self) -> Option<T> { self.rx.recv().ok() }
+}
+
+#[stable(feature = "receiver_into_iter", since = "1.1.0")]
+impl <T> IntoIterator for Receiver<T> {
+ type Item = T;
+ type IntoIter = IntoIter<T>;
+
+ fn into_iter(self) -> IntoIter<T> {
+ IntoIter { rx: self }
+ }
+}
+
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Drop for Receiver<T> {
assert_eq!(count_rx.recv().unwrap(), 4);
}
+ #[test]
+ fn test_recv_into_iter_owned() {
+ let mut iter = {
+ let (tx, rx) = channel::<i32>();
+ 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::<i32>();
+ 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::<i32>();
/// dropped (falls out of scope), the lock will be unlocked.
///
/// The data protected by the mutex can be access through this guard via its
-/// Deref and DerefMut implementations
+/// `Deref` and `DerefMut` implementations
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct MutexGuard<'a, T: 'a> {
pub fn span_help(&self, sp: Span, m: &str) {
self.sess.span_diagnostic.span_help(sp, m)
}
+ pub fn span_suggestion(&self, sp: Span, m: &str, n: String) {
+ self.sess.span_diagnostic.span_suggestion(sp, m, n)
+ }
pub fn fileline_help(&self, sp: Span, m: &str) {
self.sess.span_diagnostic.fileline_help(sp, m)
}
&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());
}
let lo = self.span.lo;
+ let box_hi = self.span.hi;
try!(self.bump());
self.span_err(span,
&format!("expected expression, found `{}`",
this_token_to_string));
- let box_span = mk_sp(lo, self.last_span.hi);
- self.span_help(box_span,
- "perhaps you meant `box() (foo)` instead?");
+ let box_span = mk_sp(lo, box_hi);
+ self.span_suggestion(box_span,
+ "try using `box()` instead:",
+ "box()".to_string());
self.abort_if_errors();
}
let subexpression = try!(self.parse_prefix_expr());
}
}
- 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);
/// Parse an impl item.
pub fn parse_impl_item(&mut self) -> PResult<P<ImplItem>> {
- 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());
/// Parse a foreign item.
fn parse_foreign_item(&mut self) -> PResult<Option<P<ForeignItem>>> {
- 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) {
-Subproject commit ebc6b04c29591108d3f28e724b4b9b74cd1232e6
+Subproject commit e54d4823d26cdb3f98e5a1b17e1c257cd329aa61
// aux-build:rlib_crate_test.rs
// ignore-stage1
// ignore-tidy-linelength
-// ignore-android
// ignore-cross-compile gives a different error message
#![feature(plugin)]
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ &1 as Copy;
+ //~^ ERROR cast to unsized type
+ //~| HELP try casting to a reference instead:
+ //~| SUGGESTION &1 as &Copy;
+ Box::new(1) as Copy;
+ //~^ ERROR cast to unsized type
+ //~| HELP try casting to a `Box` instead:
+ //~| SUGGESTION Box::new(1) as Box<Copy>;
+}
// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
let _bar = Box::new(1_usize) as std::fmt::Debug;
//~^ ERROR cast to unsized type: `Box<usize>` as `core::fmt::Debug`
- //~^^ HELP did you mean `Box<core::fmt::Debug>`?
+ //~^^ HELP try casting to a `Box` instead
let _baz = 1_usize as std::fmt::Debug;
//~^ ERROR cast to unsized type: `usize` as `core::fmt::Debug`
fn main() {
let _m = Monster(); //~ ERROR `Monster` is a structure name, but
- //~^ HELP Did you mean to write: `Monster { /* fields */ }`?
+ //~^ HELP did you mean to write: `Monster { /* fields */ }`?
}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ let _: &Copy + 'static;
+ //~^ ERROR expected a path
+ //~| HELP try adding parentheses
+ //~| SUGGESTION let _: &(Copy + 'static);
+ let _: &'static Copy + 'static;
+ //~^ ERROR expected a path
+ //~| HELP try adding parentheses
+ //~| SUGGESTION let _: &'static (Copy + 'static);
+}
// compile-flags: -Z parse-only
fn main() {
- box(1 + 1) //~ HELP perhaps you meant `box() (foo)` instead?
+ box (1 + 1)
+ //~^ HELP try using `box()` instead:
+ //~| SUGGESTION box() (1 + 1)
; //~ ERROR expected expression, found `;`
}
# on some platforms, but LLVM just prints a warning so that's fine for
# now.
$(1): simd.rs
- $$(RUSTC) --target=$(1) --emit=llvm-ir,asm simd.rs -C target-feature='+neon,+sse2'
+ $$(RUSTC) --target=$(1) --emit=llvm-ir,asm simd.rs \
+ -C target-feature='+neon,+sse2' -C extra-filename=-$(1)
endef
$(foreach targetxxx,$(TARGETS),$(eval $(call MK_TARGETS,$(targetxxx))))
// Test that the CompilerCalls interface to the compiler works.
-// ignore-android
+// ignore-cross-compile
#![feature(rustc_private, path)]
#![feature(core)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android
+// ignore-cross-compile
#![feature(rustc_private)]
// except according to those terms.
// no-prefer-dynamic
-// ignore-android
+// ignore-cross-compile
#![feature(rustc_private)]
// except according to those terms.
// ignore-pretty
-// ignore-android
+// ignore-cross-compile
#![feature(quote, rustc_private)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android
+// ignore-cross-compile
// ignore-pretty: does not work well with `--test`
#![feature(quote, rustc_private)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// ignore-cross-compile
// ignore-pretty
// ignore-test
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android
+// ignore-cross-compile
// ignore-pretty: does not work well with `--test`
#![feature(quote, rustc_private)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android
+// ignore-cross-compile
// ignore-pretty: does not work well with `--test`
#![feature(quote, rustc_private)]
// This test can't be a unit test in std,
// because it needs TempDir, which is in extra
-// ignore-android
+// ignore-cross-compile
#![feature(rustc_private, path_ext)]
write!(w, "{}", "hello");
writeln!(w, "{}", "line");
writeln!(w, "{foo}", foo="bar");
+ w.write_char('☃');
+ w.write_str("str");
}
- t!(buf, "34helloline\nbar\n");
+ t!(buf, "34helloline\nbar\n☃str");
}
// Just make sure that the macros are defined, there's not really a lot that we
// except according to those terms.
// aux-build:rustdoc-default-impl.rs
-// ignore-android
+// ignore-cross-compile
extern crate rustdoc_default_impl as foo;
// except according to those terms.
// aux-build:rustdoc-extern-default-method.rs
-// ignore-android
+// ignore-cross-compile
extern crate rustdoc_extern_default_method as ext;
// except according to those terms.
// aux-build:rustdoc-extern-method.rs
-// ignore-android
+// ignore-cross-compile
#![feature(unboxed_closures)]
// except according to those terms.
// aux-build:rustdoc-ffi.rs
-// ignore-android
+// ignore-cross-compile
extern crate rustdoc_ffi as lib;
// except according to those terms.
// aux-build:inline-default-methods.rs
-// ignore-android
+// ignore-cross-compile
extern crate inline_default_methods;
// except according to those terms.
// aux-build:issue-13698.rs
-// ignore-android
+// ignore-cross-compile
extern crate issue_13698;
// except according to those terms.
// aux-build:issue-15318.rs
-// ignore-android
+// ignore-cross-compile
extern crate issue_15318;
// except according to those terms.
// aux-build:issue-15318.rs
-// ignore-android
+// ignore-cross-compile
#![feature(no_std)]
#![no_std]
// except according to those terms.
// aux-build:issue-17476.rs
-// ignore-android
+// ignore-cross-compile
extern crate issue_17476;
// except according to those terms.
// aux-build:issue-19190-3.rs
-// ignore-android
+// ignore-cross-compile
extern crate issue_19190_3;
// except according to those terms.
// aux-build:issue-20646.rs
-// ignore-android
+// ignore-cross-compile
#![feature(associated_types)]
// except according to those terms.
// aux-build:issue-20727.rs
-// ignore-android
+// ignore-cross-compile
extern crate issue_20727;
// except according to those terms.
// aux-build:issue-20727.rs
-// ignore-android
+// ignore-cross-compile
extern crate issue_20727;
// except according to those terms.
// aux-build:issue-20727.rs
-// ignore-android
+// ignore-cross-compile
extern crate issue_20727;
// except according to those terms.
// aux-build:issue-20727.rs
-// ignore-android
+// ignore-cross-compile
extern crate issue_20727;
// except according to those terms.
// aux-build:issue-21092.rs
-// ignore-android
+// ignore-cross-compile
extern crate issue_21092;
// except according to those terms.
// aux-build:issue-21801.rs
-// ignore-android
+// ignore-cross-compile
extern crate issue_21801;
// except according to those terms.
// aux-build:issue-22025.rs
-// ignore-android
+// ignore-cross-compile
extern crate issue_22025;
// aux-build:issue-23207-1.rs
// aux-build:issue-23207-2.rs
-// ignore-android
+// ignore-cross-compile
extern crate issue_23207_2;