# make check-stage1-rpass TESTNAME=my-shiny-new-test
#
# // Having trouble figuring out which test is failing? Turn off parallel tests
-# make check-stage1-std RUST_TEST_TASKS=1
-#
-# This is hardly all there is to know of The Rust Build System's
-# mysteries. The tale continues on the wiki[1].
-#
-# [1]: https://github.com/rust-lang/rust/wiki/Note-testsuite
+# make check-stage1-std RUST_TEST_THREADS=1
#
# If you really feel like getting your hands dirty, then:
#
\fBopt\-level\fR=\fIVAL\fR
Optimize with possible levels 0\[en]3
+.SH ENVIRONMENT VARIABLES
+
+Some of these affect the output of the compiler, while others affect programs
+which link to the standard library.
+
+.TP
+\fBRUST_TEST_THREADS\fR
+The test framework Rust provides executes tests in parallel. This variable sets
+the maximum number of threads used for this purpose.
+
+.TP
+\fBRUST_TEST_NOCAPTURE\fR
+A synonym for the --nocapture flag.
+
+.TP
+\fBRUST_MIN_STACK\fR
+Sets the minimum stack size for new threads.
+
+.TP
+\fBRUST_BACKTRACE\fR
+If set, produces a backtrace in the output of a program which panics.
+
.SH "EXAMPLES"
To build an executable from a source file with a main function:
$ rustc \-o hello hello.rs
// android debug-info test uses remote debugger
// so, we test 1 task at once.
// also trying to isolate problems with adb_run_wrapper.sh ilooping
- env::set_var("RUST_TEST_TASKS","1");
+ env::set_var("RUST_TEST_THREADS","1");
}
match config.mode {
// Some older versions of LLDB seem to have problems with multiple
// instances running in parallel, so only run one test task at a
// time.
- env::set_var("RUST_TEST_TASKS", "1");
+ env::set_var("RUST_TEST_THREADS", "1");
}
_ => { /* proceed */ }
}
true
});
- for key in vec!["RUST_TEST_NOCAPTURE", "RUST_TEST_TASKS"] {
+ for key in vec!["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] {
match env::var(key) {
Ok(val) =>
if exec_env.iter().find(|&&(ref x, _)| *x == key.to_string()).is_none() {
* [Strings](strings.md)
* [Arrays, Vectors, and Slices](arrays-vectors-and-slices.md)
* [Standard Input](standard-input.md)
- * [Guessing Game](guessing-game.md)
* [II: Intermediate Rust](intermediate.md)
* [Crates and Modules](crates-and-modules.md)
* [Testing](testing.md)
When this occurs, we must use Rust's destructors to provide safety and guarantee
the release of these resources (especially in the case of panic).
+For more about destructors, see the [Drop trait](../std/ops/trait.Drop.html).
+
# Callbacks from C code to Rust functions
Some external libraries require the usage of callbacks to report back their
+++ /dev/null
-% Guessing Game
-
-Okay! We've got the basics of Rust down. Let's write a bigger program.
-
-For our first project, we'll implement a classic beginner programming problem:
-the guessing game. Here's how it works: Our program will generate a random
-integer between one and a hundred. It will then prompt us to enter a guess.
-Upon entering our guess, it will tell us if we're too low or too high. Once we
-guess correctly, it will congratulate us. Sound good?
-
-## Set up
-
-Let's set up a new project. Go to your projects directory. Remember how we
-had to create our directory structure and a `Cargo.toml` for `hello_world`? Cargo
-has a command that does that for us. Let's give it a shot:
-
-```{bash}
-$ cd ~/projects
-$ cargo new guessing_game --bin
-$ cd guessing_game
-```
-
-We pass the name of our project to `cargo new`, and then the `--bin` flag,
-since we're making a binary, rather than a library.
-
-Check out the generated `Cargo.toml`:
-
-```toml
-[package]
-
-name = "guessing_game"
-version = "0.0.1"
-authors = ["Your Name <you@example.com>"]
-```
-
-Cargo gets this information from your environment. If it's not correct, go ahead
-and fix that.
-
-Finally, Cargo generated a "Hello, world!" for us. Check out `src/main.rs`:
-
-```{rust}
-fn main() {
- println!("Hello, world!")
-}
-```
-
-Let's try compiling what Cargo gave us:
-
-```{bash}
-$ cargo build
- Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
-```
-
-Excellent! Open up your `src/main.rs` again. We'll be writing all of
-our code in this file. We'll talk about multiple-file projects later on in the
-guide.
-
-Before we move on, let me show you one more Cargo command: `run`. `cargo run`
-is kind of like `cargo build`, but it also then runs the produced executable.
-Try it out:
-
-```bash
-$ cargo run
- Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
- Running `target/guessing_game`
-Hello, world!
-```
-
-Great! The `run` command comes in handy when you need to rapidly iterate on a project.
-Our game is just such a project, we need to quickly test each iteration before moving on to the next one.
-
-## Processing a Guess
-
-Let's get to it! The first thing we need to do for our guessing game is
-allow our player to input a guess. Put this in your `src/main.rs`:
-
-```{rust,no_run}
-use std::old_io;
-
-fn main() {
- println!("Guess the number!");
-
- println!("Please input your guess.");
-
- let input = old_io::stdin().read_line()
- .ok()
- .expect("Failed to read line");
-
- println!("You guessed: {}", input);
-}
-```
-
-You've seen this code before, when we talked about standard input. We
-import the `std::old_io` module with `use`, and then our `main` function contains
-our program's logic. We print a little message announcing the game, ask the
-user to input a guess, get their input, and then print it out.
-
-Because we talked about this in the section on standard I/O, I won't go into
-more details here. If you need a refresher, go re-read that section.
-
-## Generating a secret number
-
-Next, we need to generate a secret number. To do that, we need to use Rust's
-random number generation, which we haven't talked about yet. Rust includes a
-bunch of interesting functions in its standard library. If you need a bit of
-code, it's possible that it's already been written for you! In this case,
-we do know that Rust has random number generation, but we don't know how to
-use it.
-
-Enter the docs. Rust has a page specifically to document the standard library.
-You can find that page [here](../std/index.html). There's a lot of information on
-that page, but the best part is the search bar. Right up at the top, there's
-a box that you can enter in a search term. The search is pretty primitive
-right now, but is getting better all the time. If you type "random" in that
-box, the page will update to [this one](../std/index.html?search=random). The very
-first result is a link to [`std::rand::random`](../std/rand/fn.random.html). If we
-click on that result, we'll be taken to its documentation page.
-
-This page shows us a few things: the type signature of the function, some
-explanatory text, and then an example. Let's try to modify our code to add in the
-`random` function and see what happens:
-
-```{rust,ignore}
-use std::old_io;
-use std::rand;
-
-fn main() {
- println!("Guess the number!");
-
- let secret_number = (rand::random() % 100) + 1; // secret_number: i32
-
- println!("The secret number is: {}", secret_number);
-
- println!("Please input your guess.");
-
- let input = old_io::stdin().read_line()
- .ok()
- .expect("Failed to read line");
-
-
- println!("You guessed: {}", input);
-}
-```
-
-The first thing we changed was to `use std::rand`, as the docs
-explained. We then added in a `let` expression to create a variable binding
-named `secret_number`, and we printed out its result.
-
-Also, you may wonder why we are using `%` on the result of `rand::random()`.
-This operator is called *modulo*, and it returns the remainder of a division.
-By taking the modulo of the result of `rand::random()`, we're limiting the
-values to be between 0 and 99. Then, we add one to the result, making it from 1
-to 100. Using modulo can give you a very, very small bias in the result, but
-for this example, it is not important.
-
-Let's try to compile this using `cargo build`:
-
-```bash
-$ cargo build
- Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
-src/main.rs:7:26: 7:34 error: the type of this value must be known in this context
-src/main.rs:7 let secret_number = (rand::random() % 100) + 1;
- ^~~~~~~~
-error: aborting due to previous error
-```
-
-It didn't work! Rust says "the type of this value must be known in this
-context." What's up with that? Well, as it turns out, `rand::random()` can
-generate many kinds of random values, not just integers. And in this case, Rust
-isn't sure what kind of value `random()` should generate. So we have to help
-it. With number literals, we can just add an `i32` onto the end to tell Rust they're
-integers, but that does not work with functions. There's a different syntax,
-and it looks like this:
-
-```{rust,ignore}
-rand::random::<i32>();
-```
-
-This says "please give me a random `i32` value." We can change our code to use
-this hint:
-
-```{rust,no_run}
-use std::old_io;
-use std::rand;
-
-fn main() {
- println!("Guess the number!");
-
- let secret_number = (rand::random::<i32>() % 100) + 1;
-
- println!("The secret number is: {}", secret_number);
-
- println!("Please input your guess.");
-
- let input = old_io::stdin().read_line()
- .ok()
- .expect("Failed to read line");
-
-
- println!("You guessed: {}", input);
-}
-```
-
-Try running our new program a few times:
-
-```bash
-$ cargo run
- Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
- Running `target/guessing_game`
-Guess the number!
-The secret number is: 7
-Please input your guess.
-4
-You guessed: 4
-$ ./target/guessing_game
-Guess the number!
-The secret number is: 83
-Please input your guess.
-5
-You guessed: 5
-$ ./target/guessing_game
-Guess the number!
-The secret number is: -29
-Please input your guess.
-42
-You guessed: 42
-```
-
-Wait. Negative 29? We wanted a number between one and a hundred! We have two
-options here: we can either ask `random()` to generate an unsigned integer, which
-can only be positive, or we can use the `abs()` function. Let's go with the
-unsigned integer approach. If we want a random positive number, we should ask for
-a random positive number. Our code looks like this now:
-
-```{rust,no_run}
-use std::old_io;
-use std::rand;
-
-fn main() {
- println!("Guess the number!");
-
- let secret_number = (rand::random::<u32>() % 100) + 1;
-
- println!("The secret number is: {}", secret_number);
-
- println!("Please input your guess.");
-
- let input = old_io::stdin().read_line()
- .ok()
- .expect("Failed to read line");
-
-
- println!("You guessed: {}", input);
-}
-```
-
-And trying it out:
-
-```bash
-$ cargo run
- Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
- Running `target/guessing_game`
-Guess the number!
-The secret number is: 57
-Please input your guess.
-3
-You guessed: 3
-```
-
-Great! Next up: let's compare our guess to the secret guess.
-
-## Comparing guesses
-
-If you remember, earlier in the guide, we made a `cmp` function that compared
-two numbers. Let's add that in, along with a `match` statement to compare our
-guess to the secret number:
-
-```{rust,ignore}
-use std::old_io;
-use std::rand;
-use std::cmp::Ordering;
-
-fn main() {
- println!("Guess the number!");
-
- let secret_number = (rand::random::<u32>() % 100) + 1;
-
- println!("The secret number is: {}", secret_number);
-
- println!("Please input your guess.");
-
- let input = old_io::stdin().read_line()
- .ok()
- .expect("Failed to read line");
-
-
- println!("You guessed: {}", input);
-
- match cmp(input, secret_number) {
- Ordering::Less => println!("Too small!"),
- Ordering::Greater => println!("Too big!"),
- Ordering::Equal => println!("You win!"),
- }
-}
-
-fn cmp(a: i32, b: i32) -> Ordering {
- if a < b { Ordering::Less }
- else if a > b { Ordering::Greater }
- else { Ordering::Equal }
-}
-```
-
-If we try to compile, we'll get some errors:
-
-```bash
-$ cargo build
- Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
-src/main.rs:20:15: 20:20 error: mismatched types: expected `i32` but found `collections::string::String` (expected i32 but found struct collections::string::String)
-src/main.rs:20 match cmp(input, secret_number) {
- ^~~~~
-src/main.rs:20:22: 20:35 error: mismatched types: expected `i32` but found `u32` (expected i32 but found u32)
-src/main.rs:20 match cmp(input, secret_number) {
- ^~~~~~~~~~~~~
-error: aborting due to 2 previous errors
-```
-
-This often happens when writing Rust programs, and is one of Rust's greatest
-strengths. You try out some code, see if it compiles, and Rust tells you that
-you've done something wrong. In this case, our `cmp` function works on integers,
-but we've given it unsigned integers. In this case, the fix is easy, because
-we wrote the `cmp` function! Let's change it to take `u32`s:
-
-```{rust,ignore}
-use std::old_io;
-use std::rand;
-use std::cmp::Ordering;
-
-fn main() {
- println!("Guess the number!");
-
- let secret_number = (rand::random::<u32>() % 100) + 1;
-
- println!("The secret number is: {}", secret_number);
-
- println!("Please input your guess.");
-
- let input = old_io::stdin().read_line()
- .ok()
- .expect("Failed to read line");
-
-
- println!("You guessed: {}", input);
-
- match cmp(input, secret_number) {
- Ordering::Less => println!("Too small!"),
- Ordering::Greater => println!("Too big!"),
- Ordering::Equal => println!("You win!"),
- }
-}
-
-fn cmp(a: u32, b: u32) -> Ordering {
- if a < b { Ordering::Less }
- else if a > b { Ordering::Greater }
- else { Ordering::Equal }
-}
-```
-
-And try compiling again:
-
-```bash
-$ cargo build
- Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
-src/main.rs:20:15: 20:20 error: mismatched types: expected `u32` but found `collections::string::String` (expected u32 but found struct collections::string::String)
-src/main.rs:20 match cmp(input, secret_number) {
- ^~~~~
-error: aborting due to previous error
-```
-
-This error is similar to the last one: we expected to get a `u32`, but we got
-a `String` instead! That's because our `input` variable is coming from the
-standard input, and you can guess anything. Try it:
-
-```bash
-$ ./target/guessing_game
-Guess the number!
-The secret number is: 73
-Please input your guess.
-hello
-You guessed: hello
-```
-
-Oops! Also, you'll note that we just ran our program even though it didn't compile.
-This works because the older version we did successfully compile was still lying
-around. Gotta be careful!
-
-Anyway, we have a `String`, but we need a `u32`. What to do? Well, there's
-a function for that:
-
-```{rust,ignore}
-let input = old_io::stdin().read_line()
- .ok()
- .expect("Failed to read line");
-let input_num: Result<u32, _> = input.parse();
-```
-
-The `parse` function takes in a `&str` value and converts it into something.
-We tell it what kind of something with a type hint. Remember our type hint with
-`random()`? It looked like this:
-
-```{rust,ignore}
-rand::random::<u32>();
-```
-
-There's an alternate way of providing a hint too, and that's declaring the type
-in a `let`:
-
-```{rust,ignore}
-let x: u32 = rand::random();
-```
-
-In this case, we say `x` is a `u32` explicitly, so Rust is able to properly
-tell `random()` what to generate. In a similar fashion, both of these work:
-
-```{rust,ignore}
-let input_num_option = "5".parse::<u32>().ok(); // input_num: Option<u32>
-let input_num_result: Result<u32, _> = "5".parse(); // input_num: Result<u32, <u32 as FromStr>::Err>
-```
-
-Above, we're converting the `Result` returned by `parse` to an `Option` by using
-the `ok` method as well. Anyway, with us now converting our input to a number,
-our code looks like this:
-
-```{rust,ignore}
-use std::old_io;
-use std::rand;
-use std::cmp::Ordering;
-
-fn main() {
- println!("Guess the number!");
-
- let secret_number = (rand::random::<u32>() % 100) + 1;
-
- println!("The secret number is: {}", secret_number);
-
- println!("Please input your guess.");
-
- let input = old_io::stdin().read_line()
- .ok()
- .expect("Failed to read line");
- let input_num: Result<u32, _> = input.parse();
-
- println!("You guessed: {:?}", input_num);
-
- match cmp(input_num, secret_number) {
- Ordering::Less => println!("Too small!"),
- Ordering::Greater => println!("Too big!"),
- Ordering::Equal => println!("You win!"),
- }
-}
-
-fn cmp(a: u32, b: u32) -> Ordering {
- if a < b { Ordering::Less }
- else if a > b { Ordering::Greater }
- else { Ordering::Equal }
-}
-```
-
-Let's try it out!
-
-```bash
-$ cargo build
- Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
-src/main.rs:21:15: 21:24 error: mismatched types: expected `u32`, found `core::result::Result<u32, core::num::ParseIntError>` (expected u32, found enum `core::result::Result`) [E0308]
-src/main.rs:21 match cmp(input_num, secret_number) {
- ^~~~~~~~~
-error: aborting due to previous error
-```
-
-Oh yeah! Our `input_num` has the type `Result<u32, <some error>>`, rather than `u32`. We
-need to unwrap the Result. If you remember from before, `match` is a great way
-to do that. Try this code:
-
-```{rust,no_run}
-use std::old_io;
-use std::rand;
-use std::cmp::Ordering;
-
-fn main() {
- println!("Guess the number!");
-
- let secret_number = (rand::random::<u32>() % 100) + 1;
-
- println!("The secret number is: {}", secret_number);
-
- println!("Please input your guess.");
-
- let input = old_io::stdin().read_line()
- .ok()
- .expect("Failed to read line");
- let input_num: Result<u32, _> = input.parse();
-
- let num = match input_num {
- Ok(n) => n,
- Err(_) => {
- println!("Please input a number!");
- return;
- }
- };
-
-
- println!("You guessed: {}", num);
-
- match cmp(num, secret_number) {
- Ordering::Less => println!("Too small!"),
- Ordering::Greater => println!("Too big!"),
- Ordering::Equal => println!("You win!"),
- }
-}
-
-fn cmp(a: u32, b: u32) -> Ordering {
- if a < b { Ordering::Less }
- else if a > b { Ordering::Greater }
- else { Ordering::Equal }
-}
-```
-
-We use a `match` to either give us the `u32` inside of the `Result`, or else
-print an error message and return. Let's give this a shot:
-
-```bash
-$ cargo run
- Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
- Running `target/guessing_game`
-Guess the number!
-The secret number is: 17
-Please input your guess.
-5
-Please input a number!
-```
-
-Uh, what? But we did!
-
-... actually, we didn't. See, when you get a line of input from `stdin()`,
-you get all the input. Including the `\n` character from you pressing Enter.
-Therefore, `parse()` sees the string `"5\n"` and says "nope, that's not a
-number; there's non-number stuff in there!" Luckily for us, `&str`s have an easy
-method we can use defined on them: `trim()`. One small modification, and our
-code looks like this:
-
-```{rust,no_run}
-use std::old_io;
-use std::rand;
-use std::cmp::Ordering;
-
-fn main() {
- println!("Guess the number!");
-
- let secret_number = (rand::random::<u32>() % 100) + 1;
-
- println!("The secret number is: {}", secret_number);
-
- println!("Please input your guess.");
-
- let input = old_io::stdin().read_line()
- .ok()
- .expect("Failed to read line");
- let input_num: Result<u32, _> = input.trim().parse();
-
- let num = match input_num {
- Ok(num) => num,
- Err(_) => {
- println!("Please input a number!");
- return;
- }
- };
-
-
- println!("You guessed: {}", num);
-
- match cmp(num, secret_number) {
- Ordering::Less => println!("Too small!"),
- Ordering::Greater => println!("Too big!"),
- Ordering::Equal => println!("You win!"),
- }
-}
-
-fn cmp(a: u32, b: u32) -> Ordering {
- if a < b { Ordering::Less }
- else if a > b { Ordering::Greater }
- else { Ordering::Equal }
-}
-```
-
-Let's try it!
-
-```bash
-$ cargo run
- Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
- Running `target/guessing_game`
-Guess the number!
-The secret number is: 58
-Please input your guess.
- 76
-You guessed: 76
-Too big!
-```
-
-Nice! You can see I even added spaces before my guess, and it still figured
-out that I guessed 76. Run the program a few times, and verify that guessing
-the number works, as well as guessing a number too small.
-
-The Rust compiler helped us out quite a bit there! This technique is called
-"leaning on the compiler", and it's often useful when working on some code.
-Let the error messages help guide you towards the correct types.
-
-Now we've got most of the game working, but we can only make one guess. Let's
-change that by adding loops!
-
-## Looping
-
-As we already discussed, the `loop` keyword gives us an infinite loop.
-Let's add that in:
-
-```{rust,no_run}
-use std::old_io;
-use std::rand;
-use std::cmp::Ordering;
-
-fn main() {
- println!("Guess the number!");
-
- let secret_number = (rand::random::<u32>() % 100) + 1;
-
- println!("The secret number is: {}", secret_number);
-
- loop {
-
- println!("Please input your guess.");
-
- let input = old_io::stdin().read_line()
- .ok()
- .expect("Failed to read line");
- let input_num: Result<u32, _> = input.trim().parse();
-
- let num = match input_num {
- Ok(num) => num,
- Err(_) => {
- println!("Please input a number!");
- return;
- }
- };
-
-
- println!("You guessed: {}", num);
-
- match cmp(num, secret_number) {
- Ordering::Less => println!("Too small!"),
- Ordering::Greater => println!("Too big!"),
- Ordering::Equal => println!("You win!"),
- }
- }
-}
-
-fn cmp(a: u32, b: u32) -> Ordering {
- if a < b { Ordering::Less }
- else if a > b { Ordering::Greater }
- else { Ordering::Equal }
-}
-```
-
-And try it out. But wait, didn't we just add an infinite loop? Yup. Remember
-that `return`? If we give a non-number answer, we'll `return` and quit. Observe:
-
-```bash
-$ cargo run
- Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
- Running `target/guessing_game`
-Guess the number!
-The secret number is: 59
-Please input your guess.
-45
-You guessed: 45
-Too small!
-Please input your guess.
-60
-You guessed: 60
-Too big!
-Please input your guess.
-59
-You guessed: 59
-You win!
-Please input your guess.
-quit
-Please input a number!
-```
-
-Ha! `quit` actually quits. As does any other non-number input. Well, this is
-suboptimal to say the least. First, let's actually quit when you win the game:
-
-```{rust,no_run}
-use std::old_io;
-use std::rand;
-use std::cmp::Ordering;
-
-fn main() {
- println!("Guess the number!");
-
- let secret_number = (rand::random::<u32>() % 100) + 1;
-
- println!("The secret number is: {}", secret_number);
-
- loop {
-
- println!("Please input your guess.");
-
- let input = old_io::stdin().read_line()
- .ok()
- .expect("Failed to read line");
- let input_num: Result<u32, _> = input.trim().parse();
-
- let num = match input_num {
- Ok(num) => num,
- Err(_) => {
- println!("Please input a number!");
- return;
- }
- };
-
-
- println!("You guessed: {}", num);
-
- match cmp(num, secret_number) {
- Ordering::Less => println!("Too small!"),
- Ordering::Greater => println!("Too big!"),
- Ordering::Equal => {
- println!("You win!");
- return;
- },
- }
- }
-}
-
-fn cmp(a: u32, b: u32) -> Ordering {
- if a < b { Ordering::Less }
- else if a > b { Ordering::Greater }
- else { Ordering::Equal }
-}
-```
-
-By adding the `return` line after the `You win!`, we'll exit the program when
-we win. We have just one more tweak to make: when someone inputs a non-number,
-we don't want to quit, we just want to ignore it. Change that `return` to
-`continue`:
-
-
-```{rust,no_run}
-use std::old_io;
-use std::rand;
-use std::cmp::Ordering;
-
-fn main() {
- println!("Guess the number!");
-
- let secret_number = (rand::random::<u32>() % 100) + 1;
-
- println!("The secret number is: {}", secret_number);
-
- loop {
-
- println!("Please input your guess.");
-
- let input = old_io::stdin().read_line()
- .ok()
- .expect("Failed to read line");
- let input_num: Result<u32, _> = input.trim().parse();
-
- let num = match input_num {
- Ok(num) => num,
- Err(_) => {
- println!("Please input a number!");
- continue;
- }
- };
-
-
- println!("You guessed: {}", num);
-
- match cmp(num, secret_number) {
- Ordering::Less => println!("Too small!"),
- Ordering::Greater => println!("Too big!"),
- Ordering::Equal => {
- println!("You win!");
- return;
- },
- }
- }
-}
-
-fn cmp(a: u32, b: u32) -> Ordering {
- if a < b { Ordering::Less }
- else if a > b { Ordering::Greater }
- else { Ordering::Equal }
-}
-```
-
-Now we should be good! Let's try:
-
-```bash
-$ cargo run
- Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
- Running `target/guessing_game`
-Guess the number!
-The secret number is: 61
-Please input your guess.
-10
-You guessed: 10
-Too small!
-Please input your guess.
-99
-You guessed: 99
-Too big!
-Please input your guess.
-foo
-Please input a number!
-Please input your guess.
-61
-You guessed: 61
-You win!
-```
-
-Awesome! With one tiny last tweak, we have finished the guessing game. Can you
-think of what it is? That's right, we don't want to print out the secret number.
-It was good for testing, but it kind of ruins the game. Here's our final source:
-
-```{rust,no_run}
-use std::old_io;
-use std::rand;
-use std::cmp::Ordering;
-
-fn main() {
- println!("Guess the number!");
-
- let secret_number = (rand::random::<u32>() % 100) + 1;
-
- loop {
-
- println!("Please input your guess.");
-
- let input = old_io::stdin().read_line()
- .ok()
- .expect("Failed to read line");
- let input_num: Result<u32, _> = input.trim().parse();
-
- let num = match input_num {
- Ok(num) => num,
- Err(_) => {
- println!("Please input a number!");
- continue;
- }
- };
-
-
- println!("You guessed: {}", num);
-
- match cmp(num, secret_number) {
- Ordering::Less => println!("Too small!"),
- Ordering::Greater => println!("Too big!"),
- Ordering::Equal => {
- println!("You win!");
- return;
- },
- }
- }
-}
-
-fn cmp(a: u32, b: u32) -> Ordering {
- if a < b { Ordering::Less }
- else if a > b { Ordering::Greater }
- else { Ordering::Equal }
-}
-```
-
-## Complete!
-
-At this point, you have successfully built the Guessing Game! Congratulations!
-
-You've now learned the basic syntax of Rust. All of this is relatively close to
-various other programming languages you have used in the past. These
-fundamental syntactical and semantic elements will form the foundation for the
-rest of your Rust education.
-
-Now that you're an expert at the basics, it's time to learn about some of
-Rust's more unique features.
In this case, Rust knows that `x` is being *borrowed* by the `add_one()`
function, and since it's only reading the value, allows it.
-We can borrow `x` multiple times, as long as it's not simultaneous:
+We can borrow `x` as read-only multiple times, even simultaneously:
```{rust}
-fn add_one(x: &i32) -> i32 {
- *x + 1
+fn add(x: &i32, y: &i32) -> i32 {
+ *x + *y
}
fn main() {
let x = Box::new(5);
- println!("{}", add_one(&*x));
- println!("{}", add_one(&*x));
- println!("{}", add_one(&*x));
+ println!("{}", add(&x, &x));
+ println!("{}", add(&x, &x));
}
```
-Or as long as it's not a mutable borrow. This will error:
+We can mutably borrow `x` multiple times, but only if x itself is mutable, and
+it may not be *simultaneously* borrowed:
```{rust,ignore}
-fn add_one(x: &mut i32) -> i32 {
- *x + 1
+fn increment(x: &mut i32) {
+ *x += 1;
}
fn main() {
- let x = Box::new(5);
+ // If variable x is not "mut", this will not compile
+ let mut x = Box::new(5);
- println!("{}", add_one(&*x)); // error: cannot borrow immutable dereference
- // of `&`-pointer as mutable
+ increment(&mut x);
+ increment(&mut x);
+ println!("{}", x);
}
```
-Notice we changed the signature of `add_one()` to request a mutable reference.
+Notice the signature of `increment()` requests a mutable reference.
## Best practices
- are plain-old-data, that is, they don't move ownership, again unlike
`Box`, hence the Rust compiler cannot protect against bugs like
use-after-free;
-- are considered sendable (if their contents is considered sendable),
- so the compiler offers no assistance with ensuring their use is
- thread-safe; for example, one can concurrently access a `*mut i32`
- from two threads without synchronization.
- lack any form of lifetimes, unlike `&`, and so the compiler cannot
reason about dangling pointers; and
- have no guarantees about aliasing or mutability other than mutation
/// Saturating integer addition. Computes `self + other`, saturating at
/// the numeric bounds instead of overflowing.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::num::Int;
+ ///
+ /// assert_eq!(5u16.saturating_add(65534), 65535);
+ /// assert_eq!((-5i16).saturating_add(-32767), -32768);
+ /// assert_eq!(100u32.saturating_add(4294967294), 4294967295);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
fn saturating_add(self, other: Self) -> Self {
/// Saturating integer subtraction. Computes `self - other`, saturating at
/// the numeric bounds instead of overflowing.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::num::Int;
+ ///
+ /// assert_eq!(5u16.saturating_sub(65534), 0);
+ /// assert_eq!(5i16.saturating_sub(-32767), 32767);
+ /// assert_eq!(100u32.saturating_sub(4294967294), 0);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
fn saturating_sub(self, other: Self) -> Self {
pub fn tr_span(&self, span: Span) -> Span {
let imported_filemaps = &self.cdata.codemap_import_info[..];
+ let span = if span.lo > span.hi {
+ // Currently macro expansion sometimes produces invalid Span values
+ // where lo > hi. In order not to crash the compiler when trying to
+ // translate these values, let's transform them into something we
+ // can handle (and which will produce useful debug locations at
+ // least some of the time).
+ // This workaround is only necessary as long as macro expansion is
+ // not fixed. FIXME(#23480)
+ codemap::mk_sp(span.lo, span.lo)
+ } else {
+ span
+ };
+
let filemap_index = {
// Optimize for the case that most spans within a translated item
// originate from the same filemap.
let last_filemap_index = self.last_filemap_index.get();
if span.lo >= imported_filemaps[last_filemap_index].original_start_pos &&
+ span.lo <= imported_filemaps[last_filemap_index].original_end_pos &&
+ span.hi >= imported_filemaps[last_filemap_index].original_start_pos &&
span.hi <= imported_filemaps[last_filemap_index].original_end_pos {
last_filemap_index
} else {
let path = tmpdir.join(&leaf);
match fs::create_dir(&path) {
Ok(_) => return Ok(TempDir { path: Some(path) }),
- Err(ref e) if e.kind() == ErrorKind::PathAlreadyExists => {}
+ Err(ref e) if e.kind() == ErrorKind::AlreadyExists => {}
Err(e) => return Err(e)
}
}
- Err(Error::new(ErrorKind::PathAlreadyExists,
+ Err(Error::new(ErrorKind::AlreadyExists,
"too many temporary directories already exist",
None))
}
/// Takes a path to a source file and cleans the path to it. This canonicalizes
/// things like ".." to components which preserve the "top down" hierarchy of a
-/// static HTML tree.
+/// static HTML tree. Each component in the cleaned path will be passed as an
+/// argument to `f`. The very last component of the path (ie the file name) will
+/// be passed to `f` if `keep_filename` is true, and ignored otherwise.
// FIXME (#9639): The closure should deal with &[u8] instead of &str
// FIXME (#9639): This is too conservative, rejecting non-UTF-8 paths
-fn clean_srcpath<F>(src_root: &Path, p: &Path, mut f: F) where
+fn clean_srcpath<F>(src_root: &Path, p: &Path, keep_filename: bool, mut f: F) where
F: FnMut(&str),
{
// make it relative, if possible
let p = p.relative_from(src_root).unwrap_or(p);
- for c in p.iter().map(|x| x.to_str().unwrap()) {
+ let mut iter = p.iter().map(|x| x.to_str().unwrap()).peekable();
+ while let Some(c) = iter.next() {
+ if !keep_filename && iter.peek().is_none() {
+ break;
+ }
+
if ".." == c {
f("up");
} else {
// Create the intermediate directories
let mut cur = self.dst.clone();
let mut root_path = String::from_str("../../");
- clean_srcpath(&self.cx.src_root, &p, |component| {
+ clean_srcpath(&self.cx.src_root, &p, false, |component| {
cur.push(component);
mkdir(&cur).unwrap();
root_path.push_str("../");
if ast_util::is_local(self.item.def_id) {
let mut path = Vec::new();
clean_srcpath(&cx.src_root, Path::new(&self.item.source.filename),
- |component| {
+ true, |component| {
path.push(component.to_string());
});
let href = if self.item.source.loline == self.item.source.hiline {
#![feature(test)]
#![feature(unicode)]
#![feature(str_words)]
-#![feature(io)]
#![feature(file_path)]
#![feature(path_ext)]
#![feature(path_relative_from)]
#![feature(collections)]
#![feature(core)]
#![feature(int_uint)]
-#![feature(io)]
#![feature(old_path)]
#![feature(rustc_private)]
#![feature(staged_api)]
/// will yield instances of `io::Result<DirEntry>`. Through a `DirEntry`
/// information like the entry's path and possibly other metadata can be
/// learned.
+///
+/// # Failure
+///
+/// This `io::Result` will be an `Err` if there's some sort of intermittent
+/// IO error during iteration.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct ReadDir(fs_imp::ReadDir);
let from = from.as_path();
let to = to.as_path();
if !from.is_file() {
- return Err(Error::new(ErrorKind::MismatchedFileTypeForOperation,
+ return Err(Error::new(ErrorKind::InvalidInput,
"the source path is not an existing file",
None))
}
let dir = &tmpdir.join("mkdir_error_twice");
check!(fs::create_dir(dir));
let e = fs::create_dir(dir).err().unwrap();
- assert_eq!(e.kind(), ErrorKind::PathAlreadyExists);
+ assert_eq!(e.kind(), ErrorKind::AlreadyExists);
}
#[test]
let path = tmpdir.join(&leaf);
match fs::create_dir(&path) {
Ok(_) => return Ok(TempDir { path: Some(path) }),
- Err(ref e) if e.kind() == ErrorKind::PathAlreadyExists => {}
+ Err(ref e) if e.kind() == ErrorKind::AlreadyExists => {}
Err(e) => return Err(e)
}
}
- Err(Error::new(ErrorKind::PathAlreadyExists,
+ Err(Error::new(ErrorKind::AlreadyExists,
"too many temporary directories already exist",
None))
}
}
/// A list specifying general categories of I/O error.
+///
+/// This list is intended to grow over time and it is not recommended to
+/// exhaustively match against it.
#[derive(Copy, PartialEq, Eq, Clone, Debug)]
-#[unstable(feature = "io",
- reason = "the interaction between OS error codes and how they map to \
- these names (as well as the names themselves) has not \
- been thoroughly thought out")]
+#[stable(feature = "rust1", since = "1.0.0")]
pub enum ErrorKind {
- /// The file was not found.
- FileNotFound,
- /// The file permissions disallowed access to this file.
+ /// An entity was not found, often a file.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ NotFound,
+ /// The operation lacked the necessary privileges to complete.
+ #[stable(feature = "rust1", since = "1.0.0")]
PermissionDenied,
/// The connection was refused by the remote server.
+ #[stable(feature = "rust1", since = "1.0.0")]
ConnectionRefused,
/// The connection was reset by the remote server.
+ #[stable(feature = "rust1", since = "1.0.0")]
ConnectionReset,
/// The connection was aborted (terminated) by the remote server.
+ #[stable(feature = "rust1", since = "1.0.0")]
ConnectionAborted,
/// The network operation failed because it was not connected yet.
+ #[stable(feature = "rust1", since = "1.0.0")]
NotConnected,
+ /// A socket address could not be bound because the address is already in
+ /// use elsewhere.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ AddrInUse,
+ /// A nonexistent interface was requested or the requested address was not
+ /// local.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ AddrNotAvailable,
/// The operation failed because a pipe was closed.
+ #[stable(feature = "rust1", since = "1.0.0")]
BrokenPipe,
- /// A file already existed with that name.
- PathAlreadyExists,
- /// No file exists at that location.
- PathDoesntExist,
- /// The path did not specify the type of file that this operation required.
- /// For example, attempting to copy a directory with the `fs::copy()`
- /// operation will fail with this error.
- MismatchedFileTypeForOperation,
- /// The operation temporarily failed (for example, because a signal was
- /// received), and retrying may succeed.
- ResourceUnavailable,
- /// A parameter was incorrect in a way that caused an I/O error not part of
- /// this list.
+ /// An entity already exists, often a file.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ AlreadyExists,
+ /// The operation needs to block to complete, but the blocking operation was
+ /// requested to not occur.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ WouldBlock,
+ /// A parameter was incorrect.
+ #[stable(feature = "rust1", since = "1.0.0")]
InvalidInput,
/// The I/O operation's timeout expired, causing it to be canceled.
+ #[stable(feature = "rust1", since = "1.0.0")]
TimedOut,
/// An error returned when an operation could not be completed because a
/// call to `write` returned `Ok(0)`.
/// This typically means that an operation could only succeed if it wrote a
/// particular number of bytes but only a smaller number of bytes could be
/// written.
+ #[stable(feature = "rust1", since = "1.0.0")]
WriteZero,
- /// This operation was interrupted
+ /// This operation was interrupted.
+ ///
+ /// Interrupted operations can typically be retried.
+ #[stable(feature = "rust1", since = "1.0.0")]
Interrupted,
/// Any I/O error not part of this list.
+ #[stable(feature = "rust1", since = "1.0.0")]
Other,
+
+ /// Any I/O error not part of this list.
+ #[unstable(feature = "std_misc",
+ reason = "better expressed through extensible enums that this \
+ enum cannot be exhaustively matched against")]
+ #[doc(hidden)]
+ __Nonexhaustive,
}
impl Error {
Error { repr: Repr::Os(code) }
}
+ /// Returns the OS error that this error represents (if any).
+ ///
+ /// If this `Error` was constructed via `last_os_error` then this function
+ /// will return `Some`, otherwise it will return `None`.
+ #[unstable(feature = "io", reason = "function was just added and the return \
+ type may become an abstract OS error")]
+ pub fn raw_os_error(&self) -> Option<i32> {
+ match self.repr {
+ Repr::Os(i) => Some(i),
+ Repr::Custom(..) => None,
+ }
+ }
+
/// Return the corresponding `ErrorKind` for this error.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn kind(&self) -> ErrorKind {
read_until(self, byte, buf)
}
- /// Read all bytes until a newline byte (the 0xA byte) is reached.
+ /// Read all bytes until a newline byte (the 0xA byte) is reached, and
+ /// append them to the provided buffer.
///
/// This function will continue to read (and buffer) bytes from the
/// underlying stream until the newline delimiter (the 0xA byte) or EOF is
pub use self::addr::{SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
pub use self::tcp::{TcpStream, TcpListener};
pub use self::udp::UdpSocket;
+pub use self::parser::AddrParseError;
mod ip;
mod addr;
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl FromStr for Ipv4Addr {
- type Err = ParseError;
- fn from_str(s: &str) -> Result<Ipv4Addr, ParseError> {
+ type Err = AddrParseError;
+ fn from_str(s: &str) -> Result<Ipv4Addr, AddrParseError> {
match Parser::new(s).read_till_eof(|p| p.read_ipv4_addr()) {
Some(s) => Ok(s),
- None => Err(ParseError)
+ None => Err(AddrParseError(()))
}
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl FromStr for Ipv6Addr {
- type Err = ParseError;
- fn from_str(s: &str) -> Result<Ipv6Addr, ParseError> {
+ type Err = AddrParseError;
+ fn from_str(s: &str) -> Result<Ipv6Addr, AddrParseError> {
match Parser::new(s).read_till_eof(|p| p.read_ipv6_addr()) {
Some(s) => Ok(s),
- None => Err(ParseError)
+ None => Err(AddrParseError(()))
}
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl FromStr for SocketAddr {
- type Err = ParseError;
- fn from_str(s: &str) -> Result<SocketAddr, ParseError> {
+ type Err = AddrParseError;
+ fn from_str(s: &str) -> Result<SocketAddr, AddrParseError> {
match Parser::new(s).read_till_eof(|p| p.read_socket_addr()) {
Some(s) => Ok(s),
- None => Err(ParseError),
+ None => Err(AddrParseError(())),
}
}
}
-#[derive(Debug, Clone, PartialEq, Copy)]
-pub struct ParseError;
+/// An error returned when parsing an IP address or a socket address.
+#[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Debug, Clone, PartialEq)]
+pub struct AddrParseError(());
match TcpListener::bind("1.1.1.1:9999") {
Ok(..) => panic!(),
Err(e) =>
- // EADDRNOTAVAIL is mapped to ConnectionRefused
- assert_eq!(e.kind(), ErrorKind::ConnectionRefused),
+ assert_eq!(e.kind(), ErrorKind::AddrNotAvailable),
}
}
fn connect_error() {
match TcpStream::connect("0.0.0.0:1") {
Ok(..) => panic!(),
- Err(e) => assert!((e.kind() == ErrorKind::ConnectionRefused)
- || (e.kind() == ErrorKind::InvalidInput)),
+ Err(e) => assert!(e.kind() == ErrorKind::ConnectionRefused ||
+ e.kind() == ErrorKind::InvalidInput ||
+ e.kind() == ErrorKind::AddrInUse ||
+ e.kind() == ErrorKind::AddrNotAvailable,
+ "bad error: {} {:?}", e, e.kind()),
}
}
Ok(..) => panic!(),
Err(e) => {
assert!(e.kind() == ErrorKind::ConnectionRefused ||
- e.kind() == ErrorKind::Other,
+ e.kind() == ErrorKind::Other ||
+ e.kind() == ErrorKind::AddrInUse,
"unknown error: {} {:?}", e, e.kind());
}
}
/// Constructs a floating point number by multiplying `x` by 2 raised to the
/// power of `exp`
#[inline]
- fn ldexp(x: f32, exp: int) -> f32 {
- unsafe { cmath::ldexpf(x, exp as c_int) }
+ fn ldexp(self, exp: isize) -> f32 {
+ unsafe { cmath::ldexpf(self, exp as c_int) }
}
/// Breaks the number into a normalized fraction and a base-2 exponent,
let f1: f32 = FromStrRadix::from_str_radix("1p-123", 16).unwrap();
let f2: f32 = FromStrRadix::from_str_radix("1p-111", 16).unwrap();
let f3: f32 = FromStrRadix::from_str_radix("1.Cp-12", 16).unwrap();
- assert_eq!(Float::ldexp(1f32, -123), f1);
- assert_eq!(Float::ldexp(1f32, -111), f2);
+ assert_eq!(1f32.ldexp(-123), f1);
+ assert_eq!(1f32.ldexp(-111), f2);
assert_eq!(Float::ldexp(1.75f32, -12), f3);
assert_eq!(Float::ldexp(0f32, -123), 0f32);
fn to_radians(self) -> f64 { num::Float::to_radians(self) }
#[inline]
- fn ldexp(x: f64, exp: int) -> f64 {
- unsafe { cmath::ldexp(x, exp as c_int) }
+ fn ldexp(self, exp: isize) -> f64 {
+ unsafe { cmath::ldexp(self, exp as c_int) }
}
/// Breaks the number into a normalized fraction and a base-2 exponent,
let f1: f64 = FromStrRadix::from_str_radix("1p-123", 16).unwrap();
let f2: f64 = FromStrRadix::from_str_radix("1p-111", 16).unwrap();
let f3: f64 = FromStrRadix::from_str_radix("1.Cp-12", 16).unwrap();
- assert_eq!(Float::ldexp(1f64, -123), f1);
- assert_eq!(Float::ldexp(1f64, -111), f2);
+ assert_eq!(1f64.ldexp(-123), f1);
+ assert_eq!(1f64.ldexp(-111), f2);
assert_eq!(Float::ldexp(1.75f64, -12), f3);
assert_eq!(Float::ldexp(0f64, -123), 0f64);
/// ```
#[unstable(feature = "std_misc",
reason = "pending integer conventions")]
- fn ldexp(x: Self, exp: isize) -> Self;
+ fn ldexp(self, exp: isize) -> Self;
/// Breaks the number into a normalized fraction and a base-2 exponent,
/// satisfying:
///
#[test]
fn test_process_output_fail_to_start() {
match Command::new("/no-binary-by-this-name-should-exist").output() {
- Err(e) => assert_eq!(e.kind(), ErrorKind::FileNotFound),
+ Err(e) => assert_eq!(e.kind(), ErrorKind::NotFound),
Ok(..) => panic!()
}
}
use usize;
// Reexport some of our utilities which are expected by other crates.
-pub use self::util::{default_sched_threads, min_stack, running_on_valgrind};
+pub use self::util::{min_stack, running_on_valgrind};
pub use self::unwind::{begin_unwind, begin_unwind_fmt};
// Reexport some functionality from liballoc.
return amt;
}
-/// Get's the number of scheduler threads requested by the environment
-/// either `RUST_THREADS` or `num_cpus`.
-#[allow(deprecated)]
-pub fn default_sched_threads() -> uint {
- use os;
- match env::var("RUST_THREADS") {
- Ok(nstr) => {
- let opt_n: Option<uint> = nstr.parse().ok();
- match opt_n {
- Some(n) if n > 0 => n,
- _ => panic!("`RUST_THREADS` is `{}`, should be a positive integer", nstr)
- }
- }
- Err(..) => {
- if limit_thread_creation_due_to_osx_and_valgrind() {
- 1
- } else {
- os::num_cpus()
- }
- }
- }
-}
-
// Indicates whether we should perform expensive sanity checks, including rtassert!
//
// FIXME: Once the runtime matures remove the `true` below to turn off rtassert,
libc::EPIPE => ErrorKind::BrokenPipe,
libc::ENOTCONN => ErrorKind::NotConnected,
libc::ECONNABORTED => ErrorKind::ConnectionAborted,
- libc::EADDRNOTAVAIL => ErrorKind::ConnectionRefused,
- libc::EADDRINUSE => ErrorKind::ConnectionRefused,
- libc::ENOENT => ErrorKind::FileNotFound,
- libc::EISDIR => ErrorKind::InvalidInput,
+ libc::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
+ libc::EADDRINUSE => ErrorKind::AddrInUse,
+ libc::ENOENT => ErrorKind::NotFound,
libc::EINTR => ErrorKind::Interrupted,
libc::EINVAL => ErrorKind::InvalidInput,
- libc::ENOTTY => ErrorKind::MismatchedFileTypeForOperation,
libc::ETIMEDOUT => ErrorKind::TimedOut,
- libc::ECANCELED => ErrorKind::TimedOut,
- libc::consts::os::posix88::EEXIST => ErrorKind::PathAlreadyExists,
+ libc::consts::os::posix88::EEXIST => ErrorKind::AlreadyExists,
// These two constants can have the same value on some systems,
// but different values on others, so we can't use a match
// clause
x if x == libc::EAGAIN || x == libc::EWOULDBLOCK =>
- ErrorKind::ResourceUnavailable,
+ ErrorKind::WouldBlock,
_ => ErrorKind::Other,
}
pub fn decode_error_kind(errno: i32) -> ErrorKind {
match errno as libc::c_int {
libc::ERROR_ACCESS_DENIED => ErrorKind::PermissionDenied,
- libc::ERROR_ALREADY_EXISTS => ErrorKind::PathAlreadyExists,
+ libc::ERROR_ALREADY_EXISTS => ErrorKind::AlreadyExists,
libc::ERROR_BROKEN_PIPE => ErrorKind::BrokenPipe,
- libc::ERROR_FILE_NOT_FOUND => ErrorKind::FileNotFound,
- libc::ERROR_INVALID_FUNCTION => ErrorKind::InvalidInput,
- libc::ERROR_INVALID_HANDLE => ErrorKind::MismatchedFileTypeForOperation,
- libc::ERROR_INVALID_NAME => ErrorKind::InvalidInput,
- libc::ERROR_NOTHING_TO_TERMINATE => ErrorKind::InvalidInput,
+ libc::ERROR_FILE_NOT_FOUND => ErrorKind::NotFound,
libc::ERROR_NO_DATA => ErrorKind::BrokenPipe,
libc::ERROR_OPERATION_ABORTED => ErrorKind::TimedOut,
libc::WSAEACCES => ErrorKind::PermissionDenied,
- libc::WSAEADDRINUSE => ErrorKind::ConnectionRefused,
- libc::WSAEADDRNOTAVAIL => ErrorKind::ConnectionRefused,
+ libc::WSAEADDRINUSE => ErrorKind::AddrInUse,
+ libc::WSAEADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
libc::WSAECONNABORTED => ErrorKind::ConnectionAborted,
libc::WSAECONNREFUSED => ErrorKind::ConnectionRefused,
libc::WSAECONNRESET => ErrorKind::ConnectionReset,
libc::WSAEINVAL => ErrorKind::InvalidInput,
libc::WSAENOTCONN => ErrorKind::NotConnected,
- libc::WSAEWOULDBLOCK => ErrorKind::ResourceUnavailable,
+ libc::WSAEWOULDBLOCK => ErrorKind::WouldBlock,
_ => ErrorKind::Other,
}
impl_to_source! { ast::Arg, arg_to_string }
impl_to_source! { Generics, generics_to_string }
impl_to_source! { P<ast::Item>, item_to_string }
+ impl_to_source! { P<ast::ImplItem>, impl_item_to_string }
+ impl_to_source! { P<ast::TraitItem>, trait_item_to_string }
impl_to_source! { P<ast::Stmt>, stmt_to_string }
impl_to_source! { P<ast::Expr>, expr_to_string }
impl_to_source! { P<ast::Pat>, pat_to_string }
impl_to_tokens! { ast::Ident }
impl_to_tokens! { P<ast::Item> }
+ impl_to_tokens! { P<ast::ImplItem> }
+ impl_to_tokens! { P<ast::TraitItem> }
impl_to_tokens! { P<ast::Pat> }
impl_to_tokens! { ast::Arm }
impl_to_tokens_lifetime! { &'a [P<ast::Item>] }
$to_string(|s| s.print_item(i))
}
+pub fn impl_item_to_string(i: &ast::ImplItem) -> String {
+ $to_string(|s| s.print_impl_item(i))
+}
+
+pub fn trait_item_to_string(i: &ast::TraitItem) -> String {
+ $to_string(|s| s.print_trait_item(i))
+}
+
pub fn generics_to_string(generics: &ast::Generics) -> String {
$to_string(|s| s.print_generics(generics))
}
#![feature(std_misc)]
#![feature(libc)]
#![feature(set_stdio)]
+#![feature(os)]
extern crate getopts;
extern crate serialize;
only those tests that match are run.
By default, all tests are run in parallel. This can be altered with the
-RUST_TEST_TASKS environment variable when running tests (set it to 1).
+RUST_TEST_THRADS environment variable when running tests (set it to 1).
All tests have their standard output and standard error captured by default.
This can be overridden with the --nocapture flag or the RUST_TEST_NOCAPTURE=1
Ok(())
}
+#[allow(deprecated)]
fn get_concurrency() -> uint {
- use std::rt;
- match env::var("RUST_TEST_TASKS") {
+ match env::var("RUST_TEST_THREADS") {
Ok(s) => {
let opt_n: Option<uint> = s.parse().ok();
match opt_n {
Some(n) if n > 0 => n,
- _ => panic!("RUST_TEST_TASKS is `{}`, should be a positive integer.", s)
+ _ => panic!("RUST_TEST_THREADS is `{}`, should be a positive integer.", s)
}
}
Err(..) => {
- rt::default_sched_threads()
+ if std::rt::util::limit_thread_creation_due_to_osx_and_valgrind() {
+ 1
+ } else {
+ std::os::num_cpus()
+ }
}
}
}
}
/// An iterator over the lowercase mapping of a given character, returned from
-/// the `lowercase` method on characters.
+/// the [`to_lowercase` method](../primitive.char.html#method.to_lowercase) on
+/// characters.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct ToLowercase(Option<char>);
}
/// An iterator over the uppercase mapping of a given character, returned from
-/// the `uppercase` method on characters.
+/// the [`to_uppercase` method](../primitive.char.html#method.to_uppercase) on
+/// characters.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct ToUppercase(Option<char>);
--- /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.
+
+#![crate_type = "rlib"]
+// no-prefer-dynamic
+
+// compile-flags: -g
+
+#[macro_use]
+mod crate_with_invalid_spans_macros;
+
+pub fn exported_generic<T>(x: T, y: u32) -> (T, u32) {
+ // Using the add1 macro will produce an invalid span, because the `y` passed
+ // to the macro will have a span from this file, but the rest of the code
+ // generated from the macro will have spans from the macro-defining file.
+ // The AST node for the (1 + y) expression generated by the macro will then
+ // take it's `lo` span bound from the `1` literal in the macro-defining file
+ // and it's `hi` bound from `y` in this file, which should be lower than the
+ // `lo` and even lower than the lower bound of the FileMap it is supposedly
+ // contained in because the FileMap for this file was allocated earlier than
+ // the FileMap of the macro-defining file.
+ return (x, add1!(y));
+}
--- /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.
+
+macro_rules! add1 {
+ ($e:expr) => ({
+ let a = 1 + $e;
+ let b = $e + 1;
+ a + b - 1
+ })
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// This checks that RUST_TEST_TASKS not being 1, 2, ... is detected
+// This checks that RUST_TEST_THREADS not being 1, 2, ... is detected
// properly.
// error-pattern:should be a positive integer
// compile-flags: --test
-// exec-env:RUST_TEST_TASKS=foo
+// exec-env:RUST_TEST_THREADS=foo
// ignore-pretty: does not work well with `--test`
#[test]
--- /dev/null
+-include ../tools.mk
+all:
+ $(HOST_RPATH_ENV) $(RUSTDOC) -w html -o $(TMPDIR)/doc foo.rs
+ $(HTMLDOCCK) $(TMPDIR)/doc foo.rs
+ $(HTMLDOCCK) $(TMPDIR)/doc qux/mod.rs
--- /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.
+
+#![crate_name = "foo"]
+
+//! Dox
+// @has src/foo/foo.rs.html
+// @has foo/index.html '//a/@href' '../src/foo/foo.rs.html'
+
+pub mod qux;
+
+// @has foo/bar/index.html '//a/@href' '../../src/foo/foo.rs.html'
+pub mod bar {
+
+ /// Dox
+ // @has foo/bar/baz/index.html '//a/@href' '../../../src/foo/foo.rs.html'
+ pub mod baz {
+ /// Dox
+ // @has foo/bar/baz/fn.baz.html '//a/@href' '../../../src/foo/foo.rs.html'
+ pub fn baz() { }
+ }
+
+ /// Dox
+ // @has foo/bar/trait.Foobar.html '//a/@href' '../../src/foo/foo.rs.html'
+ pub trait Foobar { fn dummy(&self) { } }
+
+ // @has foo/bar/struct.Foo.html '//a/@href' '../../src/foo/foo.rs.html'
+ pub struct Foo { x: i32, y: u32 }
+
+ // @has foo/bar/fn.prawns.html '//a/@href' '../../src/foo/foo.rs.html'
+ pub fn prawns((a, b): (i32, u32), Foo { x, y }: Foo) { }
+}
+
+/// Dox
+// @has foo/fn.modfn.html '//a/@href' '../src/foo/foo.rs.html'
+pub fn modfn() { }
--- /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.
+
+//! Dox
+// @has src/foo/qux/mod.rs.html
+// @has foo/qux/index.html '//a/@href' '../../src/foo/qux/mod.rs.html'
+
+// @has foo/qux/bar/index.html '//a/@href' '../../../src/foo/qux/mod.rs.html'
+pub mod bar {
+
+ /// Dox
+ // @has foo/qux/bar/baz/index.html '//a/@href' '../../../../src/foo/qux/mod.rs.html'
+ pub mod baz {
+ /// Dox
+ // @has foo/qux/bar/baz/fn.baz.html '//a/@href' '../../../../src/foo/qux/mod.rs.html'
+ pub fn baz() { }
+ }
+
+ /// Dox
+ // @has foo/qux/bar/trait.Foobar.html '//a/@href' '../../../src/foo/qux/mod.rs.html'
+ pub trait Foobar { fn dummy(&self) { } }
+
+ // @has foo/qux/bar/struct.Foo.html '//a/@href' '../../../src/foo/qux/mod.rs.html'
+ pub struct Foo { x: i32, y: u32 }
+
+ // @has foo/qux/bar/fn.prawns.html '//a/@href' '../../../src/foo/qux/mod.rs.html'
+ pub fn prawns((a, b): (i32, u32), Foo { x, y }: Foo) { }
+}
+
+/// Dox
+// @has foo/qux/fn.modfn.html '//a/@href' '../../src/foo/qux/mod.rs.html'
+pub fn modfn() { }
--- /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.
+
+// aux-build:crate_with_invalid_spans.rs
+
+extern crate crate_with_invalid_spans;
+
+fn main() {
+ // The AST of `exported_generic` stored in crate_with_invalid_spans's
+ // metadata should contain an invalid span where span.lo > span.hi.
+ // Let's make sure the compiler doesn't crash when encountering this.
+ let _ = crate_with_invalid_spans::exported_generic(32u32, 7u32);
+}
// ignore-pretty
// compile-flags:--test
-// exec-env:RUST_TEST_TASKS=1
+// exec-env:RUST_TEST_THREADS=1
// Tests for the connect_timeout() function on a TcpStream. This runs with only
// one test task to ensure that errors are timeouts, not file descriptor