diff options
| author | bors <bors@rust-lang.org> | 2015-01-02 21:56:13 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2015-01-02 21:56:13 +0000 |
| commit | c89417130f042c58adc60012e7cddc4ef70b70b9 (patch) | |
| tree | 344f3d621e187b41d23ef01f621ff68ebe810a03 | |
| parent | 4b40bc85cbc1d072179c92ce01655db0272aa598 (diff) | |
| parent | 340f3fd7a909b30509a63916df06f2b885d113f7 (diff) | |
| download | rust-c89417130f042c58adc60012e7cddc4ef70b70b9.tar.gz rust-c89417130f042c58adc60012e7cddc4ef70b70b9.zip | |
auto merge of #20436 : alexcrichton/rust/rollup, r=alexcrichton
488 files changed, 6697 insertions, 4791 deletions
diff --git a/.travis.yml b/.travis.yml index 26199005298..03e38f4e0c1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,7 @@ # RVM/bundler/ruby and whatnot. Right now 'rust' as a language actually # downloads a rust/cargo snapshot, which we don't really want for building rust. language: c +sudo: false # The test suite is in general way too stressful for travis, especially in # terms of time limit and reliability. In the past we've tried to scale things diff --git a/mk/dist.mk b/mk/dist.mk index a8b331c6cc2..6986746a117 100644 --- a/mk/dist.mk +++ b/mk/dist.mk @@ -212,7 +212,7 @@ distcheck-osx: dist-osx # Unix binary installer tarballs ###################################################################### -NON_INSTALLED_PREFIXES=COPYRIGHT,LICENSE-APACHE,LICENSE-MIT,README.md,doc +NON_INSTALLED_PREFIXES=COPYRIGHT,LICENSE-APACHE,LICENSE-MIT,README.md,version define DEF_INSTALLER @@ -236,6 +236,8 @@ dist-install-dir-$(1): prepare-base-dir-$(1) docs compiler-docs $$(Q)$$(PREPARE_MAN_CMD) $$(S)LICENSE-APACHE $$(PREPARE_DEST_DIR)/share/doc/rust $$(Q)$$(PREPARE_MAN_CMD) $$(S)LICENSE-MIT $$(PREPARE_DEST_DIR)/share/doc/rust $$(Q)$$(PREPARE_MAN_CMD) $$(S)README.md $$(PREPARE_DEST_DIR)/share/doc/rust +# This tiny morsel of metadata is used by rust-packaging + $$(Q)echo "$(CFG_VERSION)" > $$(PREPARE_DEST_DIR)/version dist/$$(PKG_NAME)-$(1).tar.gz: dist-install-dir-$(1) @$(call E, build: $$@) diff --git a/mk/install.mk b/mk/install.mk index f36ca4db7ca..a8dfdffb59d 100644 --- a/mk/install.mk +++ b/mk/install.mk @@ -28,7 +28,11 @@ endif # Remove tmp files because it's a decent amount of disk space $(Q)rm -R tmp/dist +ifeq ($(CFG_DISABLE_DOCS),) +prepare_install: dist/$(PKG_NAME)-$(CFG_BUILD).tar.gz dist/$(DOC_PKG_NAME)-$(CFG_BUILD).tar.gz | tmp/empty_dir +else prepare_install: dist/$(PKG_NAME)-$(CFG_BUILD).tar.gz | tmp/empty_dir +endif uninstall: ifeq (root user, $(USER) $(patsubst %,user,$(SUDO_USER))) diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index bdbfbfd7c89..ad1264828cb 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -22,8 +22,8 @@ extern crate regex; use std::os; use std::io; use std::io::fs; -use std::str::FromStr; -use std::thunk::{Thunk}; +use std::str::{FromStr, from_str}; +use std::thunk::Thunk; use getopts::{optopt, optflag, reqopt}; use common::Config; use common::{Pretty, DebugInfoGdb, DebugInfoLldb, Codegen}; diff --git a/src/doc/guide-ffi.md b/src/doc/guide-ffi.md index 3a87271ede7..b8808eaf57d 100644 --- a/src/doc/guide-ffi.md +++ b/src/doc/guide-ffi.md @@ -450,6 +450,8 @@ them. ~~~no_run extern crate libc; + +use std::c_str::ToCStr; use std::ptr; #[link(name = "readline")] diff --git a/src/doc/guide-tasks.md b/src/doc/guide-tasks.md index 29c98e22ee9..8eb13187e58 100644 --- a/src/doc/guide-tasks.md +++ b/src/doc/guide-tasks.md @@ -206,6 +206,7 @@ getting the result later. The basic example below illustrates this. ```{rust,ignore} +# #![allow(deprecated)] use std::sync::Future; # fn main() { @@ -233,6 +234,7 @@ Here is another example showing how futures allow you to background computations. The workload will be distributed on the available cores. ```{rust,ignore} +# #![allow(deprecated)] # use std::num::Float; # use std::sync::Future; fn partial_sum(start: uint) -> f64 { diff --git a/src/doc/guide.md b/src/doc/guide.md index f4ec787a794..55465651cfb 100644 --- a/src/doc/guide.md +++ b/src/doc/guide.md @@ -26,7 +26,7 @@ in the `$`s, they just indicate the start of each command): curl -L https://static.rust-lang.org/rustup.sh | sudo sh ``` -If you're concerned about the [potential insecurity](http://curlpipesh.tumblr.com/) of using `curl | sudo sh`, +If you're concerned about the [potential insecurity](http://curlpipesh.tumblr.com/) of using `curl | sudo sh`, please keep reading and see our disclaimer below. And feel free to use a two-step version of the installation and examine our installation script: ```bash @@ -1106,13 +1106,21 @@ enum Ordering { ``` An `Ordering` can only be _one_ of `Less`, `Equal`, or `Greater` at any given -time. Here's an example: +time. + +Because `Ordering` is provided by the standard library, we can use the `use` +keyword to use it in our code. We'll learn more about `use` later, but it's +used to bring names into scope. + +Here's an example of how to use `Ordering`: ```{rust} +use std::cmp::Ordering; + fn cmp(a: int, b: int) -> Ordering { - if a < b { Less } - else if a > b { Greater } - else { Equal } + if a < b { Ordering::Less } + else if a > b { Ordering::Greater } + else { Ordering::Equal } } fn main() { @@ -1121,28 +1129,35 @@ fn main() { let ordering = cmp(x, y); // ordering: Ordering - if ordering == Less { + if ordering == Ordering::Less { println!("less"); - } else if ordering == Greater { + } else if ordering == Ordering::Greater { println!("greater"); - } else if ordering == Equal { + } else if ordering == Ordering::Equal { println!("equal"); } } ``` -`cmp` is a function that compares two things, and returns an `Ordering`. We -return either `Less`, `Greater`, or `Equal`, depending on if the two values -are greater, less, or equal. +There's a symbol here we haven't seen before: the double colon (`::`). +This is used to indicate a namesapce. In this case, `Ordering` lives in +the `cmp` submodule of the `std` module. We'll talk more about modules +later in the guide. For now, all you need to know is that you can `use` +things from the standard library if you need them. -The `ordering` variable has the type `Ordering`, and so contains one of the -three values. We can then do a bunch of `if`/`else` comparisons to check -which one it is. +Okay, let's talk about the actual code in the example. `cmp` is a function that +compares two things, and returns an `Ordering`. We return either +`Ordering::Less`, `Ordering::Greater`, or `Ordering::Equal`, depending on if +the two values are greater, less, or equal. Note that each variant of the +`enum` is namespaced under the `enum` itself: it's `Ordering::Greater` not +`Greater`. -However, repeated `if`/`else` comparisons get quite tedious. Rust has a feature -that not only makes them nicer to read, but also makes sure that you never -miss a case. Before we get to that, though, let's talk about another kind of -enum: one with values. +The `ordering` variable has the type `Ordering`, and so contains one of the +three values. We can then do a bunch of `if`/`else` comparisons to check which +one it is. However, repeated `if`/`else` comparisons get quite tedious. Rust +has a feature that not only makes them nicer to read, but also makes sure that +you never miss a case. Before we get to that, though, let's talk about another +kind of enum: one with values. This enum has two variants, one of which has a value: @@ -1175,18 +1190,19 @@ enum StringResult { ErrorReason(String), } ``` -Where a `StringResult` is either a `StringOK`, with the result of a computation, or an -`ErrorReason` with a `String` explaining what caused the computation to fail. These kinds of -`enum`s are actually very useful and are even part of the standard library. +Where a `StringResult` is either a `StringResult::StringOK`, with the result of +a computation, or an `StringResult::ErrorReason` with a `String` explaining +what caused the computation to fail. These kinds of `enum`s are actually very +useful and are even part of the standard library. -Enum variants are namespaced under the enum names. For example, here is an example of using -our `StringResult`: +Here is an example of using our `StringResult`: ```rust -# enum StringResult { -# StringOK(String), -# ErrorReason(String), -# } +enum StringResult { + StringOK(String), + ErrorReason(String), +} + fn respond(greeting: &str) -> StringResult { if greeting == "Hello" { StringResult::StringOK("Good morning!".to_string()) @@ -1196,10 +1212,7 @@ fn respond(greeting: &str) -> StringResult { } ``` -Notice that we need both the enum name and the variant name: `StringResult::StringOK`, but -we didn't need to with `Ordering` – we just said `Greater` rather than `Ordering::Greater`. -There's a reason: the Rust prelude imports the variants of `Ordering` as well as the enum -itself. We can use the `use` keyword to do something similar with `StringResult`: +That's a lot of typing! We can use the `use` keyword to make it shorter: ```rust use StringResult::StringOK; @@ -1221,12 +1234,11 @@ fn respond(greeting: &str) -> StringResult { } ``` -We'll learn more about `use` later, but it's used to bring names into scope. `use` declarations -must come before anything else, which looks a little strange in this example, since we `use` -the variants before we define them. Anyway, in the body of `respond`, we can just say `StringOK` -now, rather than the full `StringResult::StringOK`. Importing variants can be convenient, but can -also cause name conflicts, so do this with caution. It's considered good style to rarely import -variants for this reason. +`use` declarations must come before anything else, which looks a little strange in this example, +since we `use` the variants before we define them. Anyway, in the body of `respond`, we can just +say `StringOK` now, rather than the full `StringResult::StringOK`. Importing variants can be +convenient, but can also cause name conflicts, so do this with caution. It's considered good style +to rarely import variants for this reason. As you can see, `enum`s with values are quite a powerful tool for data representation, and can be even more useful when they're generic across types. Before we get to generics, @@ -1280,10 +1292,12 @@ for every possible value of `x`, and so our program will compile successfully. section on enums? ```{rust} +use std::cmp::Ordering; + fn cmp(a: int, b: int) -> Ordering { - if a < b { Less } - else if a > b { Greater } - else { Equal } + if a < b { Ordering::Less } + else if a > b { Ordering::Greater } + else { Ordering::Equal } } fn main() { @@ -1292,11 +1306,11 @@ fn main() { let ordering = cmp(x, y); - if ordering == Less { + if ordering == Ordering::Less { println!("less"); - } else if ordering == Greater { + } else if ordering == Ordering::Greater { println!("greater"); - } else if ordering == Equal { + } else if ordering == Ordering::Equal { println!("equal"); } } @@ -1305,10 +1319,12 @@ fn main() { We can re-write this as a `match`: ```{rust} +use std::cmp::Ordering; + fn cmp(a: int, b: int) -> Ordering { - if a < b { Less } - else if a > b { Greater } - else { Equal } + if a < b { Ordering::Less } + else if a > b { Ordering::Greater } + else { Ordering::Equal } } fn main() { @@ -1316,9 +1332,9 @@ fn main() { let y = 10i; match cmp(x, y) { - Less => println!("less"), - Greater => println!("greater"), - Equal => println!("equal"), + Ordering::Less => println!("less"), + Ordering::Greater => println!("greater"), + Ordering::Equal => println!("equal"), } } ``` @@ -1365,10 +1381,12 @@ side of a `let` binding or directly where an expression is used. We could also implement the previous line like this: ```{rust} +use std::cmp::Ordering; + fn cmp(a: int, b: int) -> Ordering { - if a < b { Less } - else if a > b { Greater } - else { Equal } + if a < b { Ordering::Less } + else if a > b { Ordering::Greater } + else { Ordering::Equal } } fn main() { @@ -1376,9 +1394,9 @@ fn main() { let y = 10i; println!("{}", match cmp(x, y) { - Less => "less", - Greater => "greater", - Equal => "equal", + Ordering::Less => "less", + Ordering::Greater => "greater", + Ordering::Equal => "equal", }); } ``` @@ -2139,6 +2157,7 @@ guess to the secret number: ```{rust,ignore} use std::io; use std::rand; +use std::cmp::Ordering; fn main() { println!("Guess the number!"); @@ -2157,16 +2176,16 @@ fn main() { println!("You guessed: {}", input); match cmp(input, secret_number) { - Less => println!("Too small!"), - Greater => println!("Too big!"), - Equal => println!("You win!"), + Ordering::Less => println!("Too small!"), + Ordering::Greater => println!("Too big!"), + Ordering::Equal => println!("You win!"), } } fn cmp(a: int, b: int) -> Ordering { - if a < b { Less } - else if a > b { Greater } - else { Equal } + if a < b { Ordering::Less } + else if a > b { Ordering::Greater } + else { Ordering::Equal } } ``` @@ -2193,6 +2212,7 @@ we wrote the `cmp` function! Let's change it to take `uint`s: ```{rust,ignore} use std::io; use std::rand; +use std::cmp::Ordering; fn main() { println!("Guess the number!"); @@ -2211,16 +2231,16 @@ fn main() { println!("You guessed: {}", input); match cmp(input, secret_number) { - Less => println!("Too small!"), - Greater => println!("Too big!"), - Equal => println!("You win!"), + Ordering::Less => println!("Too small!"), + Ordering::Greater => println!("Too big!"), + Ordering::Equal => println!("You win!"), } } fn cmp(a: uint, b: uint) -> Ordering { - if a < b { Less } - else if a > b { Greater } - else { Equal } + if a < b { Ordering::Less } + else if a > b { Ordering::Greater } + else { Ordering::Equal } } ``` @@ -2290,6 +2310,7 @@ Anyway, with us now converting our input to a number, our code looks like this: ```{rust,ignore} use std::io; use std::rand; +use std::cmp::Ordering; fn main() { println!("Guess the number!"); @@ -2308,16 +2329,16 @@ fn main() { println!("You guessed: {}", input_num); match cmp(input_num, secret_number) { - Less => println!("Too small!"), - Greater => println!("Too big!"), - Equal => println!("You win!"), + Ordering::Less => println!("Too small!"), + Ordering::Greater => println!("Too big!"), + Ordering::Equal => println!("You win!"), } } fn cmp(a: uint, b: uint) -> Ordering { - if a < b { Less } - else if a > b { Greater } - else { Equal } + if a < b { Ordering::Less } + else if a > b { Ordering::Greater } + else { Ordering::Equal } } ``` @@ -2339,6 +2360,7 @@ to do that. Try this code: ```{rust,no_run} use std::io; use std::rand; +use std::cmp::Ordering; fn main() { println!("Guess the number!"); @@ -2366,16 +2388,16 @@ fn main() { println!("You guessed: {}", num); match cmp(num, secret_number) { - Less => println!("Too small!"), - Greater => println!("Too big!"), - Equal => println!("You win!"), + Ordering::Less => println!("Too small!"), + Ordering::Greater => println!("Too big!"), + Ordering::Equal => println!("You win!"), } } fn cmp(a: uint, b: uint) -> Ordering { - if a < b { Less } - else if a > b { Greater } - else { Equal } + if a < b { Ordering::Less } + else if a > b { Ordering::Greater } + else { Ordering::Equal } } ``` @@ -2405,6 +2427,7 @@ code looks like this: ```{rust,no_run} use std::io; use std::rand; +use std::cmp::Ordering; fn main() { println!("Guess the number!"); @@ -2432,16 +2455,16 @@ fn main() { println!("You guessed: {}", num); match cmp(num, secret_number) { - Less => println!("Too small!"), - Greater => println!("Too big!"), - Equal => println!("You win!"), + Ordering::Less => println!("Too small!"), + Ordering::Greater => println!("Too big!"), + Ordering::Equal => println!("You win!"), } } fn cmp(a: uint, b: uint) -> Ordering { - if a < b { Less } - else if a > b { Greater } - else { Equal } + if a < b { Ordering::Less } + else if a > b { Ordering::Greater } + else { Ordering::Equal } } ``` @@ -2478,6 +2501,7 @@ Let's add that in: ```{rust,no_run} use std::io; use std::rand; +use std::cmp::Ordering; fn main() { println!("Guess the number!"); @@ -2507,17 +2531,17 @@ fn main() { println!("You guessed: {}", num); match cmp(num, secret_number) { - Less => println!("Too small!"), - Greater => println!("Too big!"), - Equal => println!("You win!"), + Ordering::Less => println!("Too small!"), + Ordering::Greater => println!("Too big!"), + Ordering::Equal => println!("You win!"), } } } fn cmp(a: uint, b: uint) -> Ordering { - if a < b { Less } - else if a > b { Greater } - else { Equal } + if a < b { Ordering::Less } + else if a > b { Ordering::Greater } + else { Ordering::Equal } } ``` @@ -2553,6 +2577,7 @@ suboptimal to say the least. First, let's actually quit when you win the game: ```{rust,no_run} use std::io; use std::rand; +use std::cmp::Ordering; fn main() { println!("Guess the number!"); @@ -2582,9 +2607,9 @@ fn main() { println!("You guessed: {}", num); match cmp(num, secret_number) { - Less => println!("Too small!"), - Greater => println!("Too big!"), - Equal => { + Ordering::Less => println!("Too small!"), + Ordering::Greater => println!("Too big!"), + Ordering::Equal => { println!("You win!"); return; }, @@ -2593,9 +2618,9 @@ fn main() { } fn cmp(a: uint, b: uint) -> Ordering { - if a < b { Less } - else if a > b { Greater } - else { Equal } + if a < b { Ordering::Less } + else if a > b { Ordering::Greater } + else { Ordering::Equal } } ``` @@ -2608,6 +2633,7 @@ we don't want to quit, we just want to ignore it. Change that `return` to ```{rust,no_run} use std::io; use std::rand; +use std::cmp::Ordering; fn main() { println!("Guess the number!"); @@ -2637,9 +2663,9 @@ fn main() { println!("You guessed: {}", num); match cmp(num, secret_number) { - Less => println!("Too small!"), - Greater => println!("Too big!"), - Equal => { + Ordering::Less => println!("Too small!"), + Ordering::Greater => println!("Too big!"), + Ordering::Equal => { println!("You win!"); return; }, @@ -2648,9 +2674,9 @@ fn main() { } fn cmp(a: uint, b: uint) -> Ordering { - if a < b { Less } - else if a > b { Greater } - else { Equal } + if a < b { Ordering::Less } + else if a > b { Ordering::Greater } + else { Ordering::Equal } } ``` @@ -2686,6 +2712,7 @@ It was good for testing, but it kind of ruins the game. Here's our final source: ```{rust,no_run} use std::io; use std::rand; +use std::cmp::Ordering; fn main() { println!("Guess the number!"); @@ -2713,9 +2740,9 @@ fn main() { println!("You guessed: {}", num); match cmp(num, secret_number) { - Less => println!("Too small!"), - Greater => println!("Too big!"), - Equal => { + Ordering::Less => println!("Too small!"), + Ordering::Greater => println!("Too big!"), + Ordering::Equal => { println!("You win!"); return; }, @@ -2724,9 +2751,9 @@ fn main() { } fn cmp(a: uint, b: uint) -> Ordering { - if a < b { Less } - else if a > b { Greater } - else { Equal } + if a < b { Ordering::Less } + else if a > b { Ordering::Greater } + else { Ordering::Equal } } ``` @@ -4154,7 +4181,7 @@ We've made a struct that represents a circle. We then write an `impl` block, and inside it, define a method, `area`. Methods take a special first parameter, `&self`. There are three variants: `self`, `&self`, and `&mut self`. You can think of this first parameter as being the `x` in `x.foo()`. The three -variants correspond to the three kinds of thing `x` could be: `self` if it's +variants correspond to the three kinds of things `x` could be: `self` if it's just a value on the stack, `&self` if it's a reference, and `&mut self` if it's a mutable reference. We should default to using `&self`, as it's the most common. @@ -4742,13 +4769,13 @@ enum OptionalFloat64 { } ``` -This is really unfortunate. Luckily, Rust has a feature that gives us a better -way: generics. Generics are called **parametric polymorphism** in type theory, -which means that they are types or functions that have multiple forms ("poly" -is multiple, "morph" is form) over a given parameter ("parametric"). +Such repetition is unfortunate. Luckily, Rust has a feature that gives us a +better way: **generics**. Generics are called **parametric polymorphism** in +type theory, which means that they are types or functions that have multiple +forms over a given parameter ("parametric"). -Anyway, enough with type theory declarations, let's check out the generic form -of `OptionalInt`. It is actually provided by Rust itself, and looks like this: +Let's see how generics help us escape `OptionalInt`. `Option` is already +provided in Rust's standard library and looks like this: ```rust enum Option<T> { @@ -4757,25 +4784,27 @@ enum Option<T> { } ``` -The `<T>` part, which you've seen a few times before, indicates that this is -a generic data type. Inside the declaration of our enum, wherever we see a `T`, -we substitute that type for the same type used in the generic. Here's an -example of using `Option<T>`, with some extra type annotations: +The `<T>` part, which you've seen a few times before, indicates that this is a +generic data type. `T` is called a **type parameter**. When we create instances +of `Option`, we need to provide a concrete type in place of the type +parameter. For example, if we wanted something like our `OptionalInt`, we would +need to instantiate an `Option<int>`. Inside the declaration of our enum, +wherever we see a `T`, we replace it with the type specified (or inferred by the +the compiler). ```{rust} let x: Option<int> = Some(5i); ``` -In the type declaration, we say `Option<int>`. Note how similar this looks to -`Option<T>`. So, in this particular `Option`, `T` has the value of `int`. On -the right-hand side of the binding, we do make a `Some(T)`, where `T` is `5i`. -Since that's an `int`, the two sides match, and Rust is happy. If they didn't -match, we'd get an error: +In this particular `Option`, `T` has the value of `int`. On the right-hand side +of the binding, we do make a `Some(T)`, where `T` is `5i`. Since that's an +`int`, the two sides match, and Rust is happy. If they didn't match, we'd get an +error: ```{rust,ignore} let x: Option<f64> = Some(5i); -// error: mismatched types: expected `core::option::Option<f64>` -// but found `core::option::Option<int>` (expected f64 but found int) +// error: mismatched types: expected `core::option::Option<f64>`, +// found `core::option::Option<int>` (expected f64, found int) ``` That doesn't mean we can't make `Option<T>`s that hold an `f64`! They just have to @@ -4786,8 +4815,6 @@ let x: Option<int> = Some(5i); let y: Option<f64> = Some(5.0f64); ``` -This is just fine. One definition, multiple uses. - Generics don't have to only be generic over one type. Consider Rust's built-in `Result<T, E>` type: @@ -4808,20 +4835,20 @@ enum Result<H, N> { } ``` -if we wanted to. Convention says that the first generic parameter should be -`T`, for 'type,' and that we use `E` for 'error'. Rust doesn't care, however. +Convention says that the first generic parameter should be `T`, for "type," and +that we use `E` for "error." -The `Result<T, E>` type is intended to -be used to return the result of a computation, and to have the ability to -return an error if it didn't work out. Here's an example: +The `Result<T, E>` type is intended to be used to return the result of a +computation and to have the ability to return an error if it didn't work +out. Here's an example: ```{rust} let x: Result<f64, String> = Ok(2.3f64); let y: Result<f64, String> = Err("There was an error.".to_string()); ``` -This particular Result will return an `f64` if there's a success, and a -`String` if there's a failure. Let's write a function that uses `Result<T, E>`: +This particular `Result` will return an `f64` upon success and a `String` if +there's a failure. Let's write a function that uses `Result<T, E>`: ```{rust} fn inverse(x: f64) -> Result<f64, String> { @@ -4831,17 +4858,18 @@ fn inverse(x: f64) -> Result<f64, String> { } ``` -We don't want to take the inverse of zero, so we check to make sure that we -weren't passed zero. If we were, then we return an `Err`, with a message. If -it's okay, we return an `Ok`, with the answer. +We want to indicate that `inverse(0.0f64)` is undefined or is an erroneous usage +of the function, so we check to make sure that we weren't passed zero. If we +were, we return an `Err` with a message. If it's okay, we return an `Ok` with +the answer. Why does this matter? Well, remember how `match` does exhaustive matches? Here's how this function gets used: ```{rust} # fn inverse(x: f64) -> Result<f64, String> { -# if x == 0.0f64 { return Err("x cannot be zero!".to_string()); } -# Ok(1.0f64 / x) +# if x == 0.0f64 { return Err("x cannot be zero!".to_string()); } +# Ok(1.0f64 / x) # } let x = inverse(25.0f64); @@ -4862,8 +4890,8 @@ println!("{}", x + 2.0f64); // error: binary operation `+` cannot be applied ``` This function is great, but there's one other problem: it only works for 64 bit -floating point values. What if we wanted to handle 32 bit floating point as -well? We'd have to write this: +floating point values. If we wanted to handle 32 bit floating point values we'd +have to write this: ```{rust} fn inverse32(x: f32) -> Result<f32, String> { @@ -4873,9 +4901,9 @@ fn inverse32(x: f32) -> Result<f32, String> { } ``` -Bummer. What we need is a **generic function**. Luckily, we can write one! -However, it won't _quite_ work yet. Before we get into that, let's talk syntax. -A generic version of `inverse` would look something like this: +What we need is a **generic function**. We can do that with Rust! However, it +won't _quite_ work yet. We need to talk about syntax. A first attempt at a +generic version of `inverse` might look something like this: ```{rust,ignore} fn inverse<T>(x: T) -> Result<T, String> { @@ -4885,24 +4913,34 @@ fn inverse<T>(x: T) -> Result<T, String> { } ``` -Just like how we had `Option<T>`, we use a similar syntax for `inverse<T>`. -We can then use `T` inside the rest of the signature: `x` has type `T`, and half -of the `Result` has type `T`. However, if we try to compile that example, we'll get -an error: +Just like how we had `Option<T>`, we use a similar syntax for `inverse<T>`. We +can then use `T` inside the rest of the signature: `x` has type `T`, and half of +the `Result` has type `T`. However, if we try to compile that example, we'll get +some errors: ```text error: binary operation `==` cannot be applied to type `T` + if x == 0.0 { return Err("x cannot be zero!".to_string()); } + ^~~~~~~~ +error: mismatched types: expected `_`, found `T` (expected floating-point variable, found type parameter) + Ok(1.0 / x) + ^ +error: mismatched types: expected `core::result::Result<T, collections::string::String>`, found `core::result::Result<_, _>` (expected type parameter, found floating-point variable) + Ok(1.0 / x) + ^~~~~~~~~~~ ``` -Because `T` can be _any_ type, it may be a type that doesn't implement `==`, -and therefore, the first line would be wrong. What do we do? +The problem is that `T` is unconstrained: it can be _any_ type. It could be a +`String`, and the expression `1.0 / x` has no meaning if `x` is a `String`. It +may be a type that doesn't implement `==`, and the first line would be +wrong. What do we do? -To fix this example, we need to learn about another Rust feature: traits. +To fix this example, we need to learn about another Rust feature: **traits**. # Traits -Do you remember the `impl` keyword, used to call a function with method -syntax? +Our discussion of **traits** begins with the `impl` keyword. We used it before +to specify methods. ```{rust} struct Circle { @@ -4918,8 +4956,8 @@ impl Circle { } ``` -Traits are similar, except that we define a trait with just the method -signature, then implement the trait for that struct. Like this: +We define a trait in terms of its methods. We then `impl` a trait `for` a type +(or many types). ```{rust} struct Circle { @@ -4939,19 +4977,18 @@ impl HasArea for Circle { } ``` -As you can see, the `trait` block looks very similar to the `impl` block, -but we don't define a body, just a type signature. When we `impl` a trait, -we use `impl Trait for Item`, rather than just `impl Item`. +The `trait` block defines only type signatures. When we `impl` a trait, we use +`impl Trait for Item`, rather than just `impl Item`. -So what's the big deal? Remember the error we were getting with our generic -`inverse` function? +The first of the three errors we got with our generic `inverse` function was +this: ```text error: binary operation `==` cannot be applied to type `T` ``` -We can use traits to constrain our generics. Consider this function, which -does not compile, and gives us a similar error: +We can use traits to constrain generic type parameters. Consider this function, +which does not compile, and gives us a similar error: ```{rust,ignore} fn print_area<T>(shape: T) { @@ -4966,8 +5003,9 @@ error: type `T` does not implement any method in scope named `area` ``` Because `T` can be any type, we can't be sure that it implements the `area` -method. But we can add a **trait constraint** to our generic `T`, ensuring -that it does: +method. But we can add a **trait constraint** to our generic `T`, ensuring that +we can only compile the function if it's called with types which `impl` the +`HasArea` trait: ```{rust} # trait HasArea { @@ -4978,9 +5016,9 @@ fn print_area<T: HasArea>(shape: T) { } ``` -The syntax `<T: HasArea>` means `any type that implements the HasArea trait`. -Because traits define function type signatures, we can be sure that any type -which implements `HasArea` will have an `.area()` method. +The syntax `<T: HasArea>` means "any type that implements the HasArea trait." +Because traits define method signatures, we can be sure that any type which +implements `HasArea` will have an `area` method. Here's an extended example of how this works: @@ -5078,55 +5116,22 @@ impl HasArea for int { It is considered poor style to implement methods on such primitive types, even though it is possible. -This may seem like the Wild West, but there are two other restrictions around -implementing traits that prevent this from getting out of hand. First, traits -must be `use`d in any scope where you wish to use the trait's method. So for -example, this does not work: - -```{rust,ignore} -mod shapes { - use std::f64::consts; - - trait HasArea { - fn area(&self) -> f64; - } - - struct Circle { - x: f64, - y: f64, - radius: f64, - } - - impl HasArea for Circle { - fn area(&self) -> f64 { - consts::PI * (self.radius * self.radius) - } - } -} - -fn main() { - let c = shapes::Circle { - x: 0.0f64, - y: 0.0f64, - radius: 1.0f64, - }; +## Scoped Method Resolution and Orphan `impl`s - println!("{}", c.area()); -} -``` +There are two restrictions for implementing traits that prevent this from +getting out of hand. -Now that we've moved the structs and traits into their own module, we get an -error: +1. **Scope-based Method Resolution**: Traits must be `use`d in any scope where + you wish to use the trait's methods +2. **No Orphan `impl`s**: Either the trait or the type you're writing the `impl` + for must be inside your crate. -```text -error: type `shapes::Circle` does not implement any method in scope named `area` -``` - -If we add a `use` line right above `main` and make the right things public, -everything is fine: +If we organize our crate differently by using modules, we'll need to ensure both +of the conditions are satisfied. Don't worry, you can lean on the compiler since +it won't let you get away with violating them. ```{rust} -use shapes::HasArea; +use shapes::HasArea; // satisfies #1 mod shapes { use std::f64::consts; @@ -5148,8 +5153,8 @@ mod shapes { } } - fn main() { + // use shapes::HasArea; // This would satisfy #1, too let c = shapes::Circle { x: 0.0f64, y: 0.0f64, @@ -5160,18 +5165,25 @@ fn main() { } ``` -This means that even if someone does something bad like add methods to `int`, -it won't affect you, unless you `use` that trait. +Requiring us to `use` traits whose methods we want means that even if someone +does something bad like add methods to `int`, it won't affect us, unless you +`use` that trait. -There's one more restriction on implementing traits. Either the trait or the -type you're writing the `impl` for must be inside your crate. So, we could -implement the `HasArea` type for `int`, because `HasArea` is in our crate. But -if we tried to implement `Float`, a trait provided by Rust, for `int`, we could -not, because both the trait and the type aren't in our crate. +The second condition allows us to `impl` built-in `trait`s for types we define, +or allows us to `impl` our own `trait`s for built-in types, but restricts us +from mixing and matching third party or built-in `impl`s with third party or +built-in types. -One last thing about traits: generic functions with a trait bound use -**monomorphization** ("mono": one, "morph": form), so they are statically -dispatched. What's that mean? Well, let's take a look at `print_area` again: +We could `impl` the `HasArea` trait for `int`, because `HasArea` is in our +crate. But if we tried to implement `Float`, a standard library `trait`, for +`int`, we could not, because neither the `trait` nor the `type` are in our +crate. + +## Monomorphization + +One last thing about generics and traits: the compiler performs +**monomorphization** on generic functions so they are statically dispatched. To +see what that means, let's take a look at `print_area` again: ```{rust,ignore} fn print_area<T: HasArea>(shape: T) { @@ -5188,10 +5200,11 @@ fn main() { } ``` -When we use this trait with `Circle` and `Square`, Rust ends up generating -two different functions with the concrete type, and replacing the call sites with -calls to the concrete implementations. In other words, you get something like -this: +Because we have called `print_area` with two different types in place of its +type paramater `T`, Rust will generate two versions of the function with the +appropriate concrete types, replacing the call sites with calls to the concrete +implementations. In other words, the compiler will actually compile something +more like this: ```{rust,ignore} fn __print_area_circle(shape: Circle) { @@ -5212,12 +5225,14 @@ fn main() { } ``` -The names don't actually change to this, it's just for illustration. But -as you can see, there's no overhead of deciding which version to call here, -hence 'statically dispatched'. The downside is that we have two copies of -the same function, so our binary is a little bit larger. +These names are for illustration; the compiler will generate its own cryptic +names for internal uses. The point is that there is no runtime overhead of +deciding which version to call. The function to be called is determined +statically, at compile time. Thus, generic functions are **statically +dispatched**. The downside is that we have two similar functions, so our binary +is larger. -# Threads +# Threads Concurrency and parallelism are topics that are of increasing interest to a broad subsection of software developers. Modern computers are often multi-core, @@ -5312,6 +5327,7 @@ example, if you wish to compute some value in the background, `Future` is a useful thing to use: ```{rust} +# #![allow(deprecated)] use std::sync::Future; let mut delayed_value = Future::spawn(move || { diff --git a/src/doc/reference.md b/src/doc/reference.md index f3ad19bbd2a..a8abb595034 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -1480,9 +1480,9 @@ data are being stored, or single-address and mutability properties are required. ``` use std::sync::atomic; -// Note that INIT_ATOMIC_UINT is a *const*, but it may be used to initialize a +// Note that ATOMIC_UINT_INIT is a *const*, but it may be used to initialize a // static. This static can be modified, so it is not placed in read-only memory. -static COUNTER: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT; +static COUNTER: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT; // This table is a candidate to be placed in read-only memory. static TABLE: &'static [uint] = &[1, 2, 3, /* ... */]; @@ -2561,6 +2561,9 @@ The currently implemented features of the reference compiler are: if the system linker is not used then specifying custom flags doesn't have much meaning. +* `link_llvm_intrinsics` – Allows linking to LLVM intrinsics via + `#[link_name="llvm.*"]`. + * `linkage` - Allows use of the `linkage` attribute, which is not portable. * `log_syntax` - Allows use of the `log_syntax` macro attribute, which is a @@ -4149,11 +4152,11 @@ Unwinding the stack of a thread is done by the thread itself, on its own control stack. If a value with a destructor is freed during unwinding, the code for the destructor is run, also on the thread's control stack. Running the destructor code causes a temporary transition to a *running* state, and allows the -destructor code to cause any subsequent state transitions. The original thread +destructor code to cause any subsequent state transitions. The original thread of unwinding and panicking thereby may suspend temporarily, and may involve (recursive) unwinding of the stack of a failed destructor. Nonetheless, the outermost unwinding activity will continue until the stack is unwound and the -thread transitions to the *dead* state. There is no way to "recover" from thread +thread transitions to the *dead* state. There is no way to "recover" from thread panics. Once a thread has temporarily suspended its unwinding in the *panicking* state, a panic occurring from within this destructor results in *hard* panic. A hard panic currently results in the process aborting. diff --git a/src/etc/licenseck.py b/src/etc/licenseck.py index 7669df36b04..9ac0acc38a7 100644 --- a/src/etc/licenseck.py +++ b/src/etc/licenseck.py @@ -38,8 +38,8 @@ exceptions = [ "rt/isaac/randport.cpp", # public domain "rt/isaac/rand.h", # public domain "rt/isaac/standard.h", # public domain - "libstd/comm/mpsc_queue.rs", # BSD - "libstd/comm/spsc_queue.rs", # BSD + "libstd/sync/mpsc/mpsc_queue.rs", # BSD + "libstd/sync/mpsc/spsc_queue.rs", # BSD "test/bench/shootout-binarytrees.rs", # BSD "test/bench/shootout-chameneos-redux.rs", # BSD "test/bench/shootout-fannkuch-redux.rs", # BSD diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 820a3838978..59106aa9777 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -247,7 +247,9 @@ impl<T> BorrowFrom<Arc<T>> for T { } #[experimental = "Deref is experimental."] -impl<T> Deref<T> for Arc<T> { +impl<T> Deref for Arc<T> { + type Target = T; + #[inline] fn deref(&self) -> &T { &self.inner().data @@ -593,7 +595,7 @@ impl<T: Default + Sync + Send> Default for Arc<T> { #[allow(experimental)] mod tests { use std::clone::Clone; - use std::comm::channel; + use std::sync::mpsc::channel; use std::mem::drop; use std::ops::Drop; use std::option::Option; @@ -630,11 +632,11 @@ mod tests { let (tx, rx) = channel(); task::spawn(move || { - let arc_v: Arc<Vec<int>> = rx.recv(); + let arc_v: Arc<Vec<int>> = rx.recv().unwrap(); assert_eq!((*arc_v)[3], 4); }); - tx.send(arc_v.clone()); + tx.send(arc_v.clone()).unwrap(); assert_eq!((*arc_v)[2], 3); assert_eq!((*arc_v)[4], 5); diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 74f0599e486..e836b08459b 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -10,6 +10,8 @@ //! A unique pointer type. +#![stable] + use core::any::{Any, AnyRefExt}; use core::clone::Clone; use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering}; @@ -44,7 +46,7 @@ pub static HEAP: () = (); /// A type that represents a uniquely-owned value. #[lang = "owned_box"] -#[unstable = "custom allocators will add an additional type parameter (with default)"] +#[stable] pub struct Box<T>(Unique<T>); #[stable] @@ -111,20 +113,20 @@ impl<S: hash::Writer, Sized? T: Hash<S>> Hash<S> for Box<T> { } } - /// Extension methods for an owning `Any` trait object. #[unstable = "post-DST and coherence changes, this will not be a trait but \ rather a direct `impl` on `Box<Any>`"] pub trait BoxAny { /// Returns the boxed value if it is of type `T`, or /// `Err(Self)` if it isn't. - #[unstable = "naming conventions around accessing innards may change"] + #[stable] fn downcast<T: 'static>(self) -> Result<Box<T>, Self>; } -#[stable] impl BoxAny for Box<Any> { #[inline] + #[unstable = "method may be renamed with respect to other downcasting \ + methods"] fn downcast<T: 'static>(self) -> Result<Box<T>, Box<Any>> { if self.is::<T>() { unsafe { @@ -147,17 +149,19 @@ impl<Sized? T: fmt::Show> fmt::Show for Box<T> { } } -impl fmt::Show for Box<Any+'static> { +impl fmt::Show for Box<Any> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Box<Any>") } } -impl<Sized? T> Deref<T> for Box<T> { +impl<Sized? T> Deref for Box<T> { + type Target = T; + fn deref(&self) -> &T { &**self } } -impl<Sized? T> DerefMut<T> for Box<T> { +impl<Sized? T> DerefMut for Box<T> { fn deref_mut(&mut self) -> &mut T { &mut **self } } @@ -210,7 +214,7 @@ mod test { #[test] fn deref() { - fn homura<T: Deref<i32>>(_: T) { } + fn homura<T: Deref<Target=i32>>(_: T) { } homura(box 765i32); } } diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 61b5d43d1cb..aab513ddeb7 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -64,7 +64,9 @@ html_root_url = "http://doc.rust-lang.org/nightly/")] #![no_std] -#![feature(lang_items, phase, unsafe_destructor, default_type_params)] +#![allow(unknown_features)] +#![feature(lang_items, phase, unsafe_destructor, default_type_params, old_orphan_check)] +#![feature(associated_types)] #[phase(plugin, link)] extern crate core; diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index bd250938836..c57231fc434 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -355,7 +355,9 @@ impl<T> BorrowFrom<Rc<T>> for T { } #[experimental = "Deref is experimental."] -impl<T> Deref<T> for Rc<T> { +impl<T> Deref for Rc<T> { + type Target = T; + #[inline(always)] fn deref(&self) -> &T { &self.inner().value diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index 64e10e69a2e..f748c8ad1eb 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -26,6 +26,7 @@ //! [dir_graph]: http://en.wikipedia.org/wiki/Directed_graph //! //! ``` +//! use std::cmp::Ordering; //! use std::collections::BinaryHeap; //! use std::uint; //! @@ -151,6 +152,7 @@ use core::prelude::*; use core::default::Default; +use core::iter::FromIterator; use core::mem::{zeroed, replace, swap}; use core::ptr; diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index d8dfc02c97a..6ea624df034 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -82,17 +82,20 @@ use core::prelude::*; +use core::cmp::Ordering; use core::cmp; use core::default::Default; use core::fmt; -use core::iter::{Cloned, Chain, Enumerate, Repeat, Skip, Take, repeat}; -use core::iter; +use core::hash; +use core::iter::RandomAccessIterator; +use core::iter::{Chain, Enumerate, Repeat, Skip, Take, repeat, Cloned}; +use core::iter::{mod, FromIterator}; use core::num::Int; +use core::ops::Index; use core::slice; use core::{u8, u32, uint}; use bitv_set; //so meta -use core::hash; use Vec; type Blocks<'a> = Cloned<slice::Iter<'a, u32>>; @@ -2507,7 +2510,7 @@ mod tests { #[cfg(test)] mod bitv_bench { - use std::prelude::*; + use std::prelude::v1::*; use std::rand; use std::rand::Rng; use std::u32; @@ -3002,7 +3005,7 @@ mod bitv_set_test { #[cfg(test)] mod bitv_set_bench { - use std::prelude::*; + use std::prelude::v1::*; use std::rand; use std::rand::Rng; use std::u32; diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 87b40aa1cee..da98c19e888 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -19,21 +19,23 @@ pub use self::Entry::*; use core::prelude::*; -use self::StackOp::*; -use super::node::{mod, Node, Found, GoDown}; -use super::node::{Traversal, MutTraversal, MoveTraversal}; -use super::node::TraversalItem::{mod, Elem, Edge}; -use super::node::ForceResult::{Leaf, Internal}; use core::borrow::BorrowFrom; -use std::hash::{Writer, Hash}; +use core::cmp::Ordering; use core::default::Default; -use core::{iter, fmt, mem}; use core::fmt::Show; -use core::iter::Map; +use core::hash::{Writer, Hash}; +use core::iter::{Map, FromIterator}; +use core::ops::{Index, IndexMut}; +use core::{iter, fmt, mem}; use ring_buf::RingBuf; use self::Continuation::{Continue, Finished}; +use self::StackOp::*; +use super::node::ForceResult::{Leaf, Internal}; +use super::node::TraversalItem::{mod, Elem, Edge}; +use super::node::{Traversal, MutTraversal, MoveTraversal}; +use super::node::{mod, Node, Found, GoDown}; // FIXME(conventions): implement bounded iterators @@ -501,6 +503,7 @@ mod stack { use core::prelude::*; use core::kinds::marker; use core::mem; + use core::ops::{Deref, DerefMut}; use super::BTreeMap; use super::super::node::{mod, Node, Fit, Split, Internal, Leaf}; use super::super::node::handle; @@ -515,13 +518,15 @@ mod stack { marker: marker::InvariantLifetime<'id> } - impl<'id, T> Deref<T> for IdRef<'id, T> { + impl<'id, T> Deref for IdRef<'id, T> { + type Target = T; + fn deref(&self) -> &T { &*self.inner } } - impl<'id, T> DerefMut<T> for IdRef<'id, T> { + impl<'id, T> DerefMut for IdRef<'id, T> { fn deref_mut(&mut self) -> &mut T { &mut *self.inner } diff --git a/src/libcollections/btree/node.rs b/src/libcollections/btree/node.rs index 3907f28092a..3dddcae11ce 100644 --- a/src/libcollections/btree/node.rs +++ b/src/libcollections/btree/node.rs @@ -18,10 +18,12 @@ pub use self::TraversalItem::*; use core::prelude::*; -use core::{slice, mem, ptr, cmp, num, raw}; -use core::iter::Zip; use core::borrow::BorrowFrom; +use core::cmp::Ordering::{Greater, Less, Equal}; +use core::iter::Zip; +use core::ops::{Deref, DerefMut}; use core::ptr::Unique; +use core::{slice, mem, ptr, cmp, num, raw}; use alloc::heap; /// Represents the result of an Insertion: either the item fit, or the node had to split @@ -455,7 +457,9 @@ impl<K: Clone, V: Clone> Clone for Node<K, V> { /// flag: &'a Cell<bool>, /// } /// -/// impl<'a> Deref<Node<uint, uint>> for Nasty<'a> { +/// impl<'a> Deref for Nasty<'a> { +/// type Target = Node<uint, uint>; +/// /// fn deref(&self) -> &Node<uint, uint> { /// if self.flag.get() { /// &*self.second @@ -511,7 +515,7 @@ impl<K: Ord, V> Node<K, V> { /// Searches for the given key in the node. If it finds an exact match, /// `Found` will be yielded with the matching index. If it doesn't find an exact match, /// `GoDown` will be yielded with the index of the subtree the key must lie in. - pub fn search<Sized? Q, NodeRef: Deref<Node<K, V>>>(node: NodeRef, key: &Q) + pub fn search<Sized? Q, NodeRef: Deref<Target=Node<K, V>>>(node: NodeRef, key: &Q) -> SearchResult<NodeRef> where Q: BorrowFrom<K> + Ord { // FIXME(Gankro): Tune when to search linear or binary based on B (and maybe K/V). // For the B configured as of this writing (B = 6), binary search was *significantly* @@ -588,7 +592,7 @@ impl <K, V> Node<K, V> { } } -impl<K, V, NodeRef: Deref<Node<K, V>>, Type, NodeType> Handle<NodeRef, Type, NodeType> { +impl<K, V, NodeRef: Deref<Target=Node<K, V>>, Type, NodeType> Handle<NodeRef, Type, NodeType> { /// Returns a reference to the node that contains the pointed-to edge or key/value pair. This /// is very different from `edge` and `edge_mut` because those return children of the node /// returned by `node`. @@ -597,7 +601,9 @@ impl<K, V, NodeRef: Deref<Node<K, V>>, Type, NodeType> Handle<NodeRef, Type, Nod } } -impl<K, V, NodeRef: DerefMut<Node<K, V>>, Type, NodeType> Handle<NodeRef, Type, NodeType> { +impl<K, V, NodeRef, Type, NodeType> Handle<NodeRef, Type, NodeType> where + NodeRef: Deref<Target=Node<K, V>> + DerefMut, +{ /// Converts a handle into one that stores the same information using a raw pointer. This can /// be useful in conjunction with `from_raw` when the type system is insufficient for /// determining the lifetimes of the nodes. @@ -653,7 +659,7 @@ impl<'a, K: 'a, V: 'a> Handle<&'a mut Node<K, V>, handle::Edge, handle::Internal } } -impl<K, V, NodeRef: Deref<Node<K, V>>> Handle<NodeRef, handle::Edge, handle::Internal> { +impl<K, V, NodeRef: Deref<Target=Node<K, V>>> Handle<NodeRef, handle::Edge, handle::Internal> { // This doesn't exist because there are no uses for it, // but is fine to add, analagous to edge_mut. // @@ -667,7 +673,7 @@ pub enum ForceResult<NodeRef, Type> { Internal(Handle<NodeRef, Type, handle::Internal>) } -impl<K, V, NodeRef: Deref<Node<K, V>>, Type> Handle<NodeRef, Type, handle::LeafOrInternal> { +impl<K, V, NodeRef: Deref<Target=Node<K, V>>, Type> Handle<NodeRef, Type, handle::LeafOrInternal> { /// Figure out whether this handle is pointing to something in a leaf node or to something in /// an internal node, clarifying the type according to the result. pub fn force(self) -> ForceResult<NodeRef, Type> { @@ -684,8 +690,9 @@ impl<K, V, NodeRef: Deref<Node<K, V>>, Type> Handle<NodeRef, Type, handle::LeafO } } } - -impl<K, V, NodeRef: DerefMut<Node<K, V>>> Handle<NodeRef, handle::Edge, handle::Leaf> { +impl<K, V, NodeRef> Handle<NodeRef, handle::Edge, handle::Leaf> where + NodeRef: Deref<Target=Node<K, V>> + DerefMut, +{ /// Tries to insert this key-value pair at the given index in this leaf node /// If the node is full, we have to split it. /// @@ -717,7 +724,9 @@ impl<K, V, NodeRef: DerefMut<Node<K, V>>> Handle<NodeRef, handle::Edge, handle:: } } -impl<K, V, NodeRef: DerefMut<Node<K, V>>> Handle<NodeRef, handle::Edge, handle::Internal> { +impl<K, V, NodeRef> Handle<NodeRef, handle::Edge, handle::Internal> where + NodeRef: Deref<Target=Node<K, V>> + DerefMut, +{ /// Returns a mutable reference to the edge pointed-to by this handle. This should not be /// confused with `node`, which references the parent node of what is returned here. pub fn edge_mut(&mut self) -> &mut Node<K, V> { @@ -800,7 +809,9 @@ impl<K, V, NodeRef: DerefMut<Node<K, V>>> Handle<NodeRef, handle::Edge, handle:: } } -impl<K, V, NodeRef: DerefMut<Node<K, V>>, NodeType> Handle<NodeRef, handle::Edge, NodeType> { +impl<K, V, NodeRef, NodeType> Handle<NodeRef, handle::Edge, NodeType> where + NodeRef: Deref<Target=Node<K, V>> + DerefMut, +{ /// Gets the handle pointing to the key/value pair just to the left of the pointed-to edge. /// This is unsafe because the handle might point to the first edge in the node, which has no /// pair to its left. @@ -862,7 +873,7 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle<&'a mut Node<K, V>, handle::KV, NodeType } } -impl<'a, K: 'a, V: 'a, NodeRef: Deref<Node<K, V>> + 'a, NodeType> Handle<NodeRef, handle::KV, +impl<'a, K: 'a, V: 'a, NodeRef: Deref<Target=Node<K, V>> + 'a, NodeType> Handle<NodeRef, handle::KV, NodeType> { // These are fine to include, but are currently unneeded. // @@ -881,8 +892,9 @@ impl<'a, K: 'a, V: 'a, NodeRef: Deref<Node<K, V>> + 'a, NodeType> Handle<NodeRef // } } -impl<'a, K: 'a, V: 'a, NodeRef: DerefMut<Node<K, V>> + 'a, NodeType> Handle<NodeRef, handle::KV, - NodeType> { +impl<'a, K: 'a, V: 'a, NodeRef, NodeType> Handle<NodeRef, handle::KV, NodeType> where + NodeRef: 'a + Deref<Target=Node<K, V>> + DerefMut, +{ /// Returns a mutable reference to the key pointed-to by this handle. This doesn't return a /// reference with a lifetime as large as `into_kv_mut`, but it also does not consume the /// handle. @@ -898,7 +910,9 @@ impl<'a, K: 'a, V: 'a, NodeRef: DerefMut<Node<K, V>> + 'a, NodeType> Handle<Node } } -impl<K, V, NodeRef: DerefMut<Node<K, V>>, NodeType> Handle<NodeRef, handle::KV, NodeType> { +impl<K, V, NodeRef, NodeType> Handle<NodeRef, handle::KV, NodeType> where + NodeRef: Deref<Target=Node<K, V>> + DerefMut, +{ /// Gets the handle pointing to the edge immediately to the left of the key/value pair pointed /// to by this handle. pub fn left_edge<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, handle::Edge, NodeType> { @@ -918,7 +932,9 @@ impl<K, V, NodeRef: DerefMut<Node<K, V>>, NodeType> Handle<NodeRef, handle::KV, } } -impl<K, V, NodeRef: DerefMut<Node<K, V>>> Handle<NodeRef, handle::KV, handle::Leaf> { +impl<K, V, NodeRef> Handle<NodeRef, handle::KV, handle::Leaf> where + NodeRef: Deref<Target=Node<K, V>> + DerefMut, +{ /// Removes the key/value pair at the handle's location. /// /// # Panics (in debug build) @@ -929,7 +945,9 @@ impl<K, V, NodeRef: DerefMut<Node<K, V>>> Handle<NodeRef, handle::KV, handle::Le } } -impl<K, V, NodeRef: DerefMut<Node<K, V>>> Handle<NodeRef, handle::KV, handle::Internal> { +impl<K, V, NodeRef> Handle<NodeRef, handle::KV, handle::Internal> where + NodeRef: Deref<Target=Node<K, V>> + DerefMut +{ /// Steal! Stealing is roughly analogous to a binary tree rotation. /// In this case, we're "rotating" right. unsafe fn steal_rightward(&mut self) { diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index f3f6727f1c0..3e8988530e6 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -13,13 +13,16 @@ use core::prelude::*; -use btree_map::{BTreeMap, Keys}; -use std::hash::Hash; use core::borrow::BorrowFrom; +use core::cmp::Ordering::{mod, Less, Greater, Equal}; use core::default::Default; -use core::fmt; -use core::iter::{Peekable, Map}; use core::fmt::Show; +use core::fmt; +use core::hash::Hash; +use core::iter::{Peekable, Map, FromIterator}; +use core::ops::{BitOr, BitAnd, BitXor, Sub}; + +use btree_map::{BTreeMap, Keys}; // FIXME(conventions): implement bounded iterators diff --git a/src/libcollections/dlist.rs b/src/libcollections/dlist.rs index 8b7b7176b80..68acbfcb3c3 100644 --- a/src/libcollections/dlist.rs +++ b/src/libcollections/dlist.rs @@ -22,12 +22,13 @@ use core::prelude::*; use alloc::boxed::Box; +use core::cmp::Ordering; use core::default::Default; use core::fmt; -use core::iter; +use core::hash::{Writer, Hash}; +use core::iter::{mod, FromIterator}; use core::mem; use core::ptr; -use std::hash::{Writer, Hash}; /// A doubly-linked list. #[stable] diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index b484fc41ff6..ea3d8659f54 100644 --- a/src/libcollections/enum_set.rs +++ b/src/libcollections/enum_set.rs @@ -16,6 +16,8 @@ use core::prelude::*; use core::fmt; use core::num::Int; +use core::iter::FromIterator; +use core::ops::{Sub, BitOr, BitAnd, BitXor}; // FIXME(contentions): implement union family of methods? (general design may be wrong here) diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index cbd8d4955b2..fac9ab8107a 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -25,6 +25,8 @@ #![feature(macro_rules, default_type_params, phase, globs)] #![feature(unsafe_destructor, slicing_syntax)] #![feature(unboxed_closures)] +#![feature(old_orphan_check)] +#![feature(associated_types)] #![no_std] #[phase(plugin, link)] extern crate core; @@ -120,7 +122,6 @@ mod prelude { pub use core::result::Result::{Ok, Err}; // in core and collections (may differ). - pub use slice::{PartialEqSliceExt, OrdSliceExt}; pub use slice::{AsSlice, SliceExt}; pub use str::{from_str, Str, StrExt}; @@ -129,7 +130,7 @@ mod prelude { pub use unicode::char::UnicodeChar; // from collections. - pub use slice::{CloneSliceExt, SliceConcatExt}; + pub use slice::SliceConcatExt; pub use str::IntoMaybeOwned; pub use string::{String, ToString}; pub use vec::Vec; diff --git a/src/libcollections/ring_buf.rs b/src/libcollections/ring_buf.rs index 12148947a19..e4c9e51a845 100644 --- a/src/libcollections/ring_buf.rs +++ b/src/libcollections/ring_buf.rs @@ -14,14 +14,16 @@ use core::prelude::*; +use core::cmp::Ordering; use core::default::Default; use core::fmt; -use core::iter; -use core::raw::Slice as RawSlice; -use core::ptr; +use core::iter::{mod, FromIterator, RandomAccessIterator}; use core::kinds::marker; use core::mem; use core::num::{Int, UnsignedInt}; +use core::ops::{Index, IndexMut}; +use core::ptr; +use core::raw::Slice as RawSlice; use std::hash::{Writer, Hash}; use std::cmp; diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 61111d96bd0..1c1b48f8cef 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -89,22 +89,26 @@ use alloc::boxed::Box; use core::borrow::{BorrowFrom, BorrowFromMut, ToOwned}; -use core::cmp; -use core::iter::{range_step, MultiplicativeIterator}; +use core::clone::Clone; +use core::cmp::Ordering::{mod, Greater, Less}; +use core::cmp::{mod, Ord, PartialEq}; +use core::iter::{Iterator, IteratorExt, IteratorCloneExt}; +use core::iter::{range, range_step, MultiplicativeIterator}; use core::kinds::Sized; use core::mem::size_of; use core::mem; -use core::ops::{FnMut,SliceMut}; -use core::prelude::{Clone, Greater, Iterator, IteratorExt, Less, None, Option}; -use core::prelude::{Ord, Ordering, PtrExt, Some, range, IteratorCloneExt, Result}; +use core::ops::{FnMut, SliceMut}; +use core::option::Option::{mod, Some, None}; +use core::ptr::PtrExt; use core::ptr; +use core::result::Result; use core::slice as core_slice; use self::Direction::*; use vec::Vec; pub use core::slice::{Chunks, AsSlice, Windows}; -pub use core::slice::{Iter, IterMut, PartialEqSliceExt}; +pub use core::slice::{Iter, IterMut}; pub use core::slice::{IntSliceExt, SplitMut, ChunksMut, Split}; pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut}; pub use core::slice::{bytes, mut_ref_slice, ref_slice}; @@ -122,7 +126,9 @@ pub type MutItems<'a, T:'a> = IterMut<'a, T>; /// Allocating extension methods for slices. #[unstable = "needs associated types, may merge with other traits"] -pub trait SliceExt<T> for Sized? { +pub trait SliceExt for Sized? { + type Item; + /// Sorts the slice, in place, using `compare` to compare /// elements. /// @@ -141,7 +147,7 @@ pub trait SliceExt<T> for Sized? { /// assert!(v == [5, 4, 3, 2, 1]); /// ``` #[stable] - fn sort_by<F>(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering; + fn sort_by<F>(&mut self, compare: F) where F: FnMut(&Self::Item, &Self::Item) -> Ordering; /// Consumes `src` and moves as many elements as it can into `self` /// from the range [start,end). @@ -165,7 +171,7 @@ pub trait SliceExt<T> for Sized? { /// assert!(a == [6i, 7, 8, 4, 5]); /// ``` #[experimental = "uncertain about this API approach"] - fn move_from(&mut self, src: Vec<T>, start: uint, end: uint) -> uint; + fn move_from(&mut self, src: Vec<Self::Item>, start: uint, end: uint) -> uint; /// Returns a subslice spanning the interval [`start`, `end`). /// @@ -174,7 +180,7 @@ pub trait SliceExt<T> for Sized? { /// /// Slicing with `start` equal to `end` yields an empty slice. #[experimental = "will be replaced by slice syntax"] - fn slice(&self, start: uint, end: uint) -> &[T]; + fn slice(&self, start: uint, end: uint) -> &[Self::Item]; /// Returns a subslice from `start` to the end of the slice. /// @@ -182,7 +188,7 @@ pub trait SliceExt<T> for Sized? { /// /// Slicing from `self.len()` yields an empty slice. #[experimental = "will be replaced by slice syntax"] - fn slice_from(&self, start: uint) -> &[T]; + fn slice_from(&self, start: uint) -> &[Self::Item]; /// Returns a subslice from the start of the slice to `end`. /// @@ -190,7 +196,7 @@ pub trait SliceExt<T> for Sized? { /// /// Slicing to `0` yields an empty slice. #[experimental = "will be replaced by slice syntax"] - fn slice_to(&self, end: uint) -> &[T]; + fn slice_to(&self, end: uint) -> &[Self::Item]; /// Divides one slice into two at an index. /// @@ -200,32 +206,32 @@ pub trait SliceExt<T> for Sized? { /// /// Panics if `mid > len`. #[stable] - fn split_at(&self, mid: uint) -> (&[T], &[T]); + fn split_at(&self, mid: uint) -> (&[Self::Item], &[Self::Item]); /// Returns an iterator over the slice #[stable] - fn iter(&self) -> Iter<T>; + fn iter(&self) -> Iter<Self::Item>; /// Returns an iterator over subslices separated by elements that match /// `pred`. The matched element is not contained in the subslices. #[stable] - fn split<F>(&self, pred: F) -> Split<T, F> - where F: FnMut(&T) -> bool; + fn split<F>(&self, pred: F) -> Split<Self::Item, F> + where F: FnMut(&Self::Item) -> bool; /// Returns an iterator over subslices separated by elements that match /// `pred`, limited to splitting at most `n` times. The matched element is /// not contained in the subslices. #[stable] - fn splitn<F>(&self, n: uint, pred: F) -> SplitN<T, F> - where F: FnMut(&T) -> bool; + fn splitn<F>(&self, n: uint, pred: F) -> SplitN<Self::Item, F> + where F: FnMut(&Self::Item) -> bool; /// Returns an iterator over subslices separated by elements that match /// `pred` limited to splitting at most `n` times. This starts at the end of /// the slice and works backwards. The matched element is not contained in /// the subslices. #[stable] - fn rsplitn<F>(&self, n: uint, pred: F) -> RSplitN<T, F> - where F: FnMut(&T) -> bool; + fn rsplitn<F>(&self, n: uint, pred: F) -> RSplitN<Self::Item, F> + where F: FnMut(&Self::Item) -> bool; /// Returns an iterator over all contiguous windows of length /// `size`. The windows overlap. If the slice is shorter than @@ -247,7 +253,7 @@ pub trait SliceExt<T> for Sized? { /// } /// ``` #[stable] - fn windows(&self, size: uint) -> Windows<T>; + fn windows(&self, size: uint) -> Windows<Self::Item>; /// Returns an iterator over `size` elements of the slice at a /// time. The chunks do not overlap. If `size` does not divide the @@ -270,41 +276,41 @@ pub trait SliceExt<T> for Sized? { /// } /// ``` #[stable] - fn chunks(&self, size: uint) -> Chunks<T>; + fn chunks(&self, size: uint) -> Chunks<Self::Item>; /// Returns the element of a slice at the given index, or `None` if the /// index is out of bounds. #[stable] - fn get(&self, index: uint) -> Option<&T>; + fn get(&self, index: uint) -> Option<&Self::Item>; /// Returns the first element of a slice, or `None` if it is empty. #[stable] - fn first(&self) -> Option<&T>; + fn first(&self) -> Option<&Self::Item>; /// Deprecated: renamed to `first`. #[deprecated = "renamed to `first`"] - fn head(&self) -> Option<&T> { self.first() } + fn head(&self) -> Option<&Self::Item> { self.first() } /// Returns all but the first element of a slice. #[experimental = "likely to be renamed"] - fn tail(&self) -> &[T]; + fn tail(&self) -> &[Self::Item]; /// Returns all but the last element of a slice. #[experimental = "likely to be renamed"] - fn init(&self) -> &[T]; + fn init(&self) -> &[Self::Item]; /// Returns the last element of a slice, or `None` if it is empty. #[stable] - fn last(&self) -> Option<&T>; + fn last(&self) -> Option<&Self::Item>; /// Returns a pointer to the element at the given index, without doing /// bounds checking. #[stable] - unsafe fn get_unchecked(&self, index: uint) -> &T; + unsafe fn get_unchecked(&self, index: uint) -> &Self::Item; /// Deprecated: renamed to `get_unchecked`. #[deprecated = "renamed to get_unchecked"] - unsafe fn unsafe_get(&self, index: uint) -> &T { + unsafe fn unsafe_get(&self, index: uint) -> &Self::Item { self.get_unchecked(index) } @@ -316,7 +322,7 @@ pub trait SliceExt<T> for Sized? { /// Modifying the slice may cause its buffer to be reallocated, which /// would also make any pointers to it invalid. #[stable] - fn as_ptr(&self) -> *const T; + fn as_ptr(&self) -> *const Self::Item; /// Binary search a sorted slice with a comparator function. /// @@ -352,7 +358,7 @@ pub trait SliceExt<T> for Sized? { /// ``` #[stable] fn binary_search_by<F>(&self, f: F) -> Result<uint, uint> where - F: FnMut(&T) -> Ordering; + F: FnMut(&Self::Item) -> Ordering; /// Return the number of elements in the slice /// @@ -379,12 +385,12 @@ pub trait SliceExt<T> for Sized? { /// Returns a mutable reference to the element at the given index, /// or `None` if the index is out of bounds #[stable] - fn get_mut(&mut self, index: uint) -> Option<&mut T>; + fn get_mut(&mut self, index: uint) -> Option<&mut Self::Item>; /// Work with `self` as a mut slice. /// Primarily intended for getting a &mut [T] from a [T; N]. #[stable] - fn as_mut_slice(&mut self) -> &mut [T]; + fn as_mut_slice(&mut self) -> &mut [Self::Item]; /// Returns a mutable subslice spanning the interval [`start`, `end`). /// @@ -393,7 +399,7 @@ pub trait SliceExt<T> for Sized? { /// /// Slicing with `start` equal to `end` yields an empty slice. #[experimental = "will be replaced by slice syntax"] - fn slice_mut(&mut self, start: uint, end: uint) -> &mut [T]; + fn slice_mut(&mut self, start: uint, end: uint) -> &mut [Self::Item]; /// Returns a mutable subslice from `start` to the end of the slice. /// @@ -401,7 +407,7 @@ pub trait SliceExt<T> for Sized? { /// /// Slicing from `self.len()` yields an empty slice. #[experimental = "will be replaced by slice syntax"] - fn slice_from_mut(&mut self, start: uint) -> &mut [T]; + fn slice_from_mut(&mut self, start: uint) -> &mut [Self::Item]; /// Returns a mutable subslice from the start of the slice to `end`. /// @@ -409,54 +415,54 @@ pub trait SliceExt<T> for Sized? { /// /// Slicing to `0` yields an empty slice. #[experimental = "will be replaced by slice syntax"] - fn slice_to_mut(&mut self, end: uint) -> &mut [T]; + fn slice_to_mut(&mut self, end: uint) -> &mut [Self::Item]; /// Returns an iterator that allows modifying each value #[stable] - fn iter_mut(&mut self) -> IterMut<T>; + fn iter_mut(&mut self) -> IterMut<Self::Item>; /// Returns a mutable pointer to the first element of a slice, or `None` if it is empty #[stable] - fn first_mut(&mut self) -> Option<&mut T>; + fn first_mut(&mut self) -> Option<&mut Self::Item>; /// Depreated: renamed to `first_mut`. #[deprecated = "renamed to first_mut"] - fn head_mut(&mut self) -> Option<&mut T> { + fn head_mut(&mut self) -> Option<&mut Self::Item> { self.first_mut() } /// Returns all but the first element of a mutable slice #[experimental = "likely to be renamed or removed"] - fn tail_mut(&mut self) -> &mut [T]; + fn tail_mut(&mut self) -> &mut [Self::Item]; /// Returns all but the last element of a mutable slice #[experimental = "likely to be renamed or removed"] - fn init_mut(&mut self) -> &mut [T]; + fn init_mut(&mut self) -> &mut [Self::Item]; /// Returns a mutable pointer to the last item in the slice. #[stable] - fn last_mut(&mut self) -> Option<&mut T>; + fn last_mut(&mut self) -> Option<&mut Self::Item>; /// Returns an iterator over mutable subslices separated by elements that /// match `pred`. The matched element is not contained in the subslices. #[stable] - fn split_mut<F>(&mut self, pred: F) -> SplitMut<T, F> - where F: FnMut(&T) -> bool; + fn split_mut<F>(&mut self, pred: F) -> SplitMut<Self::Item, F> + where F: FnMut(&Self::Item) -> bool; /// Returns an iterator over subslices separated by elements that match /// `pred`, limited to splitting at most `n` times. The matched element is /// not contained in the subslices. #[stable] - fn splitn_mut<F>(&mut self, n: uint, pred: F) -> SplitNMut<T, F> - where F: FnMut(&T) -> bool; + fn splitn_mut<F>(&mut self, n: uint, pred: F) -> SplitNMut<Self::Item, F> + where F: FnMut(&Self::Item) -> bool; /// Returns an iterator over subslices separated by elements that match /// `pred` limited to splitting at most `n` times. This starts at the end of /// the slice and works backwards. The matched element is not contained in /// the subslices. #[stable] - fn rsplitn_mut<F>(&mut self, n: uint, pred: F) -> RSplitNMut<T, F> - where F: FnMut(&T) -> bool; + fn rsplitn_mut<F>(&mut self, n: uint, pred: F) -> RSplitNMut<Self::Item, F> + where F: FnMut(&Self::Item) -> bool; /// Returns an iterator over `chunk_size` elements of the slice at a time. /// The chunks are mutable and do not overlap. If `chunk_size` does @@ -467,7 +473,7 @@ pub trait SliceExt<T> for Sized? { /// /// Panics if `chunk_size` is 0. #[stable] - fn chunks_mut(&mut self, chunk_size: uint) -> ChunksMut<T>; + fn chunks_mut(&mut self, chunk_size: uint) -> ChunksMut<Self::Item>; /// Swaps two elements in a slice. /// @@ -525,7 +531,7 @@ pub trait SliceExt<T> for Sized? { /// } /// ``` #[stable] - fn split_at_mut(&mut self, mid: uint) -> (&mut [T], &mut [T]); + fn split_at_mut(&mut self, mid: uint) -> (&mut [Self::Item], &mut [Self::Item]); /// Reverse the order of elements in a slice, in place. /// @@ -541,11 +547,11 @@ pub trait SliceExt<T> for Sized? { /// Returns an unsafe mutable pointer to the element in index #[stable] - unsafe fn get_unchecked_mut(&mut self, index: uint) -> &mut T; + unsafe fn get_unchecked_mut(&mut self, index: uint) -> &mut Self::Item; /// Deprecated: renamed to `get_unchecked_mut`. #[deprecated = "renamed to get_unchecked_mut"] - unsafe fn unchecked_mut(&mut self, index: uint) -> &mut T { + unsafe fn unchecked_mut(&mut self, index: uint) -> &mut Self::Item { self.get_unchecked_mut(index) } @@ -558,11 +564,179 @@ pub trait SliceExt<T> for Sized? { /// would also make any pointers to it invalid. #[inline] #[stable] - fn as_mut_ptr(&mut self) -> *mut T; + fn as_mut_ptr(&mut self) -> *mut Self::Item; + + /// Copies `self` into a new `Vec`. + #[stable] + fn to_vec(&self) -> Vec<Self::Item> where Self::Item: Clone; + + /// Deprecated: use `iter().cloned().partition(f)` instead. + #[deprecated = "use iter().cloned().partition(f) instead"] + fn partitioned<F>(&self, f: F) -> (Vec<Self::Item>, Vec<Self::Item>) where + Self::Item: Clone, + F: FnMut(&Self::Item) -> bool; + + /// Creates an iterator that yields every possible permutation of the + /// vector in succession. + /// + /// # Examples + /// + /// ```rust + /// let v = [1i, 2, 3]; + /// let mut perms = v.permutations(); + /// + /// for p in perms { + /// println!("{}", p); + /// } + /// ``` + /// + /// Iterating through permutations one by one. + /// + /// ```rust + /// let v = [1i, 2, 3]; + /// let mut perms = v.permutations(); + /// + /// assert_eq!(Some(vec![1i, 2, 3]), perms.next()); + /// assert_eq!(Some(vec![1i, 3, 2]), perms.next()); + /// assert_eq!(Some(vec![3i, 1, 2]), perms.next()); + /// ``` + #[unstable] + fn permutations(&self) -> Permutations<Self::Item> where Self::Item: Clone; + + /// Copies as many elements from `src` as it can into `self` (the + /// shorter of `self.len()` and `src.len()`). Returns the number + /// of elements copied. + /// + /// # Example + /// + /// ```rust + /// let mut dst = [0i, 0, 0]; + /// let src = [1i, 2]; + /// + /// assert!(dst.clone_from_slice(&src) == 2); + /// assert!(dst == [1, 2, 0]); + /// + /// let src2 = [3i, 4, 5, 6]; + /// assert!(dst.clone_from_slice(&src2) == 3); + /// assert!(dst == [3i, 4, 5]); + /// ``` + #[experimental] + fn clone_from_slice(&mut self, &[Self::Item]) -> uint where Self::Item: Clone; + + /// Sorts the slice, in place. + /// + /// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`. + /// + /// # Examples + /// + /// ```rust + /// let mut v = [-5i, 4, 1, -3, 2]; + /// + /// v.sort(); + /// assert!(v == [-5i, -3, 1, 2, 4]); + /// ``` + #[stable] + fn sort(&mut self) where Self::Item: Ord; + + /// Binary search a sorted slice for a given element. + /// + /// If the value is found then `Ok` is returned, containing the + /// index of the matching element; if the value is not found then + /// `Err` is returned, containing the index where a matching + /// element could be inserted while maintaining sorted order. + /// + /// # Example + /// + /// Looks up a series of four elements. The first is found, with a + /// uniquely determined position; the second and third are not + /// found; the fourth could match any position in `[1,4]`. + /// + /// ```rust + /// let s = [0i, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; + /// let s = s.as_slice(); + /// + /// assert_eq!(s.binary_search(&13), Ok(9)); + /// assert_eq!(s.binary_search(&4), Err(7)); + /// assert_eq!(s.binary_search(&100), Err(13)); + /// let r = s.binary_search(&1); + /// assert!(match r { Ok(1...4) => true, _ => false, }); + /// ``` + #[stable] + fn binary_search(&self, x: &Self::Item) -> Result<uint, uint> where Self::Item: Ord; + + /// Deprecated: use `binary_search` instead. + #[deprecated = "use binary_search instead"] + fn binary_search_elem(&self, x: &Self::Item) -> Result<uint, uint> where Self::Item: Ord { + self.binary_search(x) + } + + /// Mutates the slice to the next lexicographic permutation. + /// + /// Returns `true` if successful and `false` if the slice is at the + /// last-ordered permutation. + /// + /// # Example + /// + /// ```rust + /// let v: &mut [_] = &mut [0i, 1, 2]; + /// v.next_permutation(); + /// let b: &mut [_] = &mut [0i, 2, 1]; + /// assert!(v == b); + /// v.next_permutation(); + /// let b: &mut [_] = &mut [1i, 0, 2]; + /// assert!(v == b); + /// ``` + #[unstable = "uncertain if this merits inclusion in std"] + fn next_permutation(&mut self) -> bool where Self::Item: Ord; + + /// Mutates the slice to the previous lexicographic permutation. + /// + /// Returns `true` if successful and `false` if the slice is at the + /// first-ordered permutation. + /// + /// # Example + /// + /// ```rust + /// let v: &mut [_] = &mut [1i, 0, 2]; + /// v.prev_permutation(); + /// let b: &mut [_] = &mut [0i, 2, 1]; + /// assert!(v == b); + /// v.prev_permutation(); + /// let b: &mut [_] = &mut [0i, 1, 2]; + /// assert!(v == b); + /// ``` + #[unstable = "uncertain if this merits inclusion in std"] + fn prev_permutation(&mut self) -> bool where Self::Item: Ord; + + /// Find the first index containing a matching value. + #[experimental] + fn position_elem(&self, t: &Self::Item) -> Option<uint> where Self::Item: PartialEq; + + /// Find the last index containing a matching value. + #[experimental] + fn rposition_elem(&self, t: &Self::Item) -> Option<uint> where Self::Item: PartialEq; + + /// Return true if the slice contains an element with the given value. + #[stable] + fn contains(&self, x: &Self::Item) -> bool where Self::Item: PartialEq; + + /// Returns true if `needle` is a prefix of the slice. + #[stable] + fn starts_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq; + + /// Returns true if `needle` is a suffix of the slice. + #[stable] + fn ends_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq; + + /// Convert `self` into a vector without clones or allocation. + #[experimental] + fn into_vec(self: Box<Self>) -> Vec<Self::Item>; } #[unstable = "trait is unstable"] -impl<T> SliceExt<T> for [T] { +impl<T> SliceExt for [T] { + type Item = T; + #[inline] fn sort_by<F>(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering { merge_sort(self, compare) @@ -777,96 +951,10 @@ impl<T> SliceExt<T> for [T] { fn as_mut_ptr(&mut self) -> *mut T { core_slice::SliceExt::as_mut_ptr(self) } -} - -//////////////////////////////////////////////////////////////////////////////// -// Extension traits for slices over specifc kinds of data -//////////////////////////////////////////////////////////////////////////////// - -/// Extension methods for boxed slices. -#[experimental = "likely to merge into SliceExt if it survives"] -pub trait BoxedSliceExt<T> { - /// Convert `self` into a vector without clones or allocation. - #[experimental] - fn into_vec(self) -> Vec<T>; -} - -#[experimental = "trait is experimental"] -impl<T> BoxedSliceExt<T> for Box<[T]> { - fn into_vec(mut self) -> Vec<T> { - unsafe { - let xs = Vec::from_raw_parts(self.as_mut_ptr(), self.len(), self.len()); - mem::forget(self); - xs - } - } -} - -/// Allocating extension methods for slices containing `Clone` elements. -#[unstable = "likely to be merged into SliceExt"] -pub trait CloneSliceExt<T> for Sized? { - /// Copies `self` into a new `Vec`. - #[stable] - fn to_vec(&self) -> Vec<T>; - - /// Deprecated: use `iter().cloned().partition(f)` instead. - #[deprecated = "use iter().cloned().partition(f) instead"] - fn partitioned<F>(&self, f: F) -> (Vec<T>, Vec<T>) where F: FnMut(&T) -> bool; - - /// Creates an iterator that yields every possible permutation of the - /// vector in succession. - /// - /// # Examples - /// - /// ```rust - /// let v = [1i, 2, 3]; - /// let mut perms = v.permutations(); - /// - /// for p in perms { - /// println!("{}", p); - /// } - /// ``` - /// - /// Iterating through permutations one by one. - /// - /// ```rust - /// let v = [1i, 2, 3]; - /// let mut perms = v.permutations(); - /// - /// assert_eq!(Some(vec![1i, 2, 3]), perms.next()); - /// assert_eq!(Some(vec![1i, 3, 2]), perms.next()); - /// assert_eq!(Some(vec![3i, 1, 2]), perms.next()); - /// ``` - #[unstable] - fn permutations(&self) -> Permutations<T>; - - /// Copies as many elements from `src` as it can into `self` (the - /// shorter of `self.len()` and `src.len()`). Returns the number - /// of elements copied. - /// - /// # Example - /// - /// ```rust - /// let mut dst = [0i, 0, 0]; - /// let src = [1i, 2]; - /// - /// assert!(dst.clone_from_slice(&src) == 2); - /// assert!(dst == [1, 2, 0]); - /// - /// let src2 = [3i, 4, 5, 6]; - /// assert!(dst.clone_from_slice(&src2) == 3); - /// assert!(dst == [3i, 4, 5]); - /// ``` - #[experimental] - fn clone_from_slice(&mut self, &[T]) -> uint; -} - -#[unstable = "trait is unstable"] -impl<T: Clone> CloneSliceExt<T> for [T] { /// Returns a copy of `v`. #[inline] - fn to_vec(&self) -> Vec<T> { + fn to_vec(&self) -> Vec<T> where T: Clone { let mut vector = Vec::with_capacity(self.len()); vector.push_all(self); vector @@ -874,132 +962,71 @@ impl<T: Clone> CloneSliceExt<T> for [T] { #[inline] - fn partitioned<F>(&self, f: F) -> (Vec<T>, Vec<T>) where F: FnMut(&T) -> bool { + fn partitioned<F>(&self, f: F) -> (Vec<T>, Vec<T>) where F: FnMut(&T) -> bool, T: Clone { self.iter().cloned().partition(f) } /// Returns an iterator over all permutations of a vector. - fn permutations(&self) -> Permutations<T> { + fn permutations(&self) -> Permutations<T> where T: Clone { Permutations{ swaps: ElementSwaps::new(self.len()), v: self.to_vec(), } } - fn clone_from_slice(&mut self, src: &[T]) -> uint { - core_slice::CloneSliceExt::clone_from_slice(self, src) + fn clone_from_slice(&mut self, src: &[T]) -> uint where T: Clone { + core_slice::SliceExt::clone_from_slice(self, src) } -} -/// Allocating extension methods for slices on Ord values. -#[unstable = "likely to merge with SliceExt"] -pub trait OrdSliceExt<T> for Sized? { - /// Sorts the slice, in place. - /// - /// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`. - /// - /// # Examples - /// - /// ```rust - /// let mut v = [-5i, 4, 1, -3, 2]; - /// - /// v.sort(); - /// assert!(v == [-5i, -3, 1, 2, 4]); - /// ``` - #[stable] - fn sort(&mut self); + #[inline] + fn sort(&mut self) where T: Ord { + self.sort_by(|a, b| a.cmp(b)) + } - /// Binary search a sorted slice for a given element. - /// - /// If the value is found then `Ok` is returned, containing the - /// index of the matching element; if the value is not found then - /// `Err` is returned, containing the index where a matching - /// element could be inserted while maintaining sorted order. - /// - /// # Example - /// - /// Looks up a series of four elements. The first is found, with a - /// uniquely determined position; the second and third are not - /// found; the fourth could match any position in `[1,4]`. - /// - /// ```rust - /// let s = [0i, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; - /// let s = s.as_slice(); - /// - /// assert_eq!(s.binary_search(&13), Ok(9)); - /// assert_eq!(s.binary_search(&4), Err(7)); - /// assert_eq!(s.binary_search(&100), Err(13)); - /// let r = s.binary_search(&1); - /// assert!(match r { Ok(1...4) => true, _ => false, }); - /// ``` - #[stable] - fn binary_search(&self, x: &T) -> Result<uint, uint>; + fn binary_search(&self, x: &T) -> Result<uint, uint> where T: Ord { + core_slice::SliceExt::binary_search(self, x) + } - /// Deprecated: use `binary_search` instead. - #[deprecated = "use binary_search instead"] - fn binary_search_elem(&self, x: &T) -> Result<uint, uint> { - self.binary_search(x) + fn next_permutation(&mut self) -> bool where T: Ord { + core_slice::SliceExt::next_permutation(self) } - /// Mutates the slice to the next lexicographic permutation. - /// - /// Returns `true` if successful and `false` if the slice is at the - /// last-ordered permutation. - /// - /// # Example - /// - /// ```rust - /// let v: &mut [_] = &mut [0i, 1, 2]; - /// v.next_permutation(); - /// let b: &mut [_] = &mut [0i, 2, 1]; - /// assert!(v == b); - /// v.next_permutation(); - /// let b: &mut [_] = &mut [1i, 0, 2]; - /// assert!(v == b); - /// ``` - #[unstable = "uncertain if this merits inclusion in std"] - fn next_permutation(&mut self) -> bool; + fn prev_permutation(&mut self) -> bool where T: Ord { + core_slice::SliceExt::prev_permutation(self) + } - /// Mutates the slice to the previous lexicographic permutation. - /// - /// Returns `true` if successful and `false` if the slice is at the - /// first-ordered permutation. - /// - /// # Example - /// - /// ```rust - /// let v: &mut [_] = &mut [1i, 0, 2]; - /// v.prev_permutation(); - /// let b: &mut [_] = &mut [0i, 2, 1]; - /// assert!(v == b); - /// v.prev_permutation(); - /// let b: &mut [_] = &mut [0i, 1, 2]; - /// assert!(v == b); - /// ``` - #[unstable = "uncertain if this merits inclusion in std"] - fn prev_permutation(&mut self) -> bool; -} + fn position_elem(&self, t: &T) -> Option<uint> where T: PartialEq { + core_slice::SliceExt::position_elem(self, t) + } -#[unstable = "trait is unstable"] -impl<T: Ord> OrdSliceExt<T> for [T] { - #[inline] - fn sort(&mut self) { - self.sort_by(|a, b| a.cmp(b)) + fn rposition_elem(&self, t: &T) -> Option<uint> where T: PartialEq { + core_slice::SliceExt::rposition_elem(self, t) } - fn binary_search(&self, x: &T) -> Result<uint, uint> { - core_slice::OrdSliceExt::binary_search(self, x) + fn contains(&self, x: &T) -> bool where T: PartialEq { + core_slice::SliceExt::contains(self, x) } - fn next_permutation(&mut self) -> bool { - core_slice::OrdSliceExt::next_permutation(self) + fn starts_with(&self, needle: &[T]) -> bool where T: PartialEq { + core_slice::SliceExt::starts_with(self, needle) } - fn prev_permutation(&mut self) -> bool { - core_slice::OrdSliceExt::prev_permutation(self) + fn ends_with(&self, needle: &[T]) -> bool where T: PartialEq { + core_slice::SliceExt::ends_with(self, needle) + } + + fn into_vec(mut self: Box<Self>) -> Vec<T> { + unsafe { + let xs = Vec::from_raw_parts(self.as_mut_ptr(), self.len(), self.len()); + mem::forget(self); + xs + } } } +//////////////////////////////////////////////////////////////////////////////// +// Extension traits for slices over specifc kinds of data +//////////////////////////////////////////////////////////////////////////////// #[unstable = "U should be an associated type"] /// An extension trait for concatenating slices pub trait SliceConcatExt<Sized? T, U> for Sized? { @@ -1419,7 +1446,7 @@ mod tests { use std::boxed::Box; use prelude::{Some, None, range, Vec, ToString, Clone, Greater, Less, Equal}; use prelude::{SliceExt, Iterator, IteratorExt, DoubleEndedIteratorExt}; - use prelude::{OrdSliceExt, CloneSliceExt, PartialEqSliceExt, AsSlice}; + use prelude::AsSlice; use prelude::{RandomAccessIterator, Ord, SliceConcatExt}; use core::cell::Cell; use core::default::Default; diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 37a6e690f5d..769679ec4d4 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -17,17 +17,18 @@ use core::prelude::*; use core::borrow::{Cow, IntoCow}; +use core::cmp::Equiv; use core::default::Default; use core::fmt; use core::hash; +use core::iter::FromIterator; use core::mem; +use core::ops::{mod, Deref, Add}; use core::ptr; -use core::ops; use core::raw::Slice as RawSlice; use unicode::str as unicode_str; use unicode::str::Utf16Item; -use slice::CloneSliceExt; use str::{mod, CharRange, FromStr, Utf8Error}; use vec::{DerefVec, Vec, as_vec}; @@ -94,7 +95,7 @@ impl String { #[inline] #[experimental = "needs investigation to see if to_string() can match perf"] pub fn from_str(string: &str) -> String { - String { vec: string.as_bytes().to_vec() } + String { vec: ::slice::SliceExt::to_vec(string.as_bytes()) } } /// Returns the vector as a string buffer, if possible, taking care not to @@ -141,14 +142,18 @@ impl String { /// ``` #[stable] pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> CowString<'a> { + let mut i = 0; match str::from_utf8(v) { Ok(s) => return Cow::Borrowed(s), - Err(..) => {} + Err(e) => { + if let Utf8Error::InvalidByte(firstbad) = e { + i = firstbad; + } + } } static TAG_CONT_U8: u8 = 128u8; static REPLACEMENT: &'static [u8] = b"\xEF\xBF\xBD"; // U+FFFD in UTF-8 - let mut i = 0; let total = v.len(); fn unsafe_get(xs: &[u8], i: uint) -> u8 { unsafe { *xs.get_unchecked(i) } @@ -172,7 +177,7 @@ impl String { // subseqidx is the index of the first byte of the subsequence we're looking at. // It's used to copy a bunch of contiguous good codepoints at once instead of copying // them one by one. - let mut subseqidx = 0; + let mut subseqidx = i; while i < total { let i_ = i; @@ -936,7 +941,9 @@ impl ops::Slice<uint, str> for String { } #[experimental = "waiting on Deref stabilization"] -impl ops::Deref<str> for String { +impl ops::Deref for String { + type Target = str; + fn deref<'a>(&'a self) -> &'a str { unsafe { mem::transmute(self.vec[]) } } @@ -948,7 +955,9 @@ pub struct DerefString<'a> { x: DerefVec<'a, u8> } -impl<'a> Deref<String> for DerefString<'a> { +impl<'a> Deref for DerefString<'a> { + type Target = String; + fn deref<'b>(&'b self) -> &'b String { unsafe { mem::transmute(&*self.x) } } @@ -995,9 +1004,11 @@ pub trait ToString { impl<T: fmt::Show> ToString for T { fn to_string(&self) -> String { - let mut buf = Vec::<u8>::new(); - let _ = fmt::write(&mut buf, format_args!("{}", *self)); - String::from_utf8(buf).unwrap() + use core::fmt::Writer; + let mut buf = String::new(); + let _ = buf.write_fmt(format_args!("{}", self)); + buf.shrink_to_fit(); + buf } } @@ -1073,6 +1084,13 @@ impl<'a> Str for CowString<'a> { } } +impl fmt::Writer for String { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.push_str(s); + Ok(()) + } +} + #[cfg(test)] mod tests { use prelude::*; diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index a1952352bad..7e367927421 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -50,21 +50,21 @@ use alloc::boxed::Box; use alloc::heap::{EMPTY, allocate, reallocate, deallocate}; use core::borrow::{Cow, IntoCow}; use core::cmp::max; +use core::cmp::{Equiv, Ordering}; use core::default::Default; use core::fmt; use core::hash::{mod, Hash}; -use core::iter::repeat; +use core::iter::{repeat, FromIterator}; use core::kinds::marker::{ContravariantLifetime, InvariantType}; use core::mem; use core::nonzero::NonZero; use core::num::{Int, UnsignedInt}; +use core::ops::{Index, IndexMut, Deref, Add}; use core::ops; use core::ptr; use core::raw::Slice as RawSlice; use core::uint; -use slice::CloneSliceExt; - /// A growable list type, written `Vec<T>` but pronounced 'vector.' /// /// # Examples @@ -1218,7 +1218,7 @@ unsafe fn dealloc<T>(ptr: *mut T, len: uint) { #[unstable] impl<T:Clone> Clone for Vec<T> { - fn clone(&self) -> Vec<T> { self.as_slice().to_vec() } + fn clone(&self) -> Vec<T> { ::slice::SliceExt::to_vec(self.as_slice()) } fn clone_from(&mut self, other: &Vec<T>) { // drop anything in self that will not be overwritten @@ -1303,12 +1303,14 @@ impl<T> ops::SliceMut<uint, [T]> for Vec<T> { } #[experimental = "waiting on Deref stability"] -impl<T> ops::Deref<[T]> for Vec<T> { +impl<T> ops::Deref for Vec<T> { + type Target = [T]; + fn deref<'a>(&'a self) -> &'a [T] { self.as_slice() } } #[experimental = "waiting on DerefMut stability"] -impl<T> ops::DerefMut<[T]> for Vec<T> { +impl<T> ops::DerefMut for Vec<T> { fn deref_mut<'a>(&'a mut self) -> &'a mut [T] { self.as_mut_slice() } } @@ -1488,9 +1490,9 @@ impl<T:fmt::Show> fmt::Show for Vec<T> { } } -impl<'a> fmt::FormatWriter for Vec<u8> { - fn write(&mut self, buf: &[u8]) -> fmt::Result { - self.push_all(buf); +impl<'a> fmt::Writer for Vec<u8> { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.push_all(s.as_bytes()); Ok(()) } } @@ -1718,7 +1720,9 @@ pub struct DerefVec<'a, T> { } #[experimental] -impl<'a, T> Deref<Vec<T>> for DerefVec<'a, T> { +impl<'a, T> Deref for DerefVec<'a, T> { + type Target = Vec<T>; + fn deref<'b>(&'b self) -> &'b Vec<T> { &self.x } @@ -2263,7 +2267,7 @@ mod tests { } } const NUM_ELEMENTS: uint = 2; - static DROP_COUNTER: AtomicUint = atomic::INIT_ATOMIC_UINT; + static DROP_COUNTER: AtomicUint = atomic::ATOMIC_UINT_INIT; let v = Vec::from_elem(NUM_ELEMENTS, Nothing); diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs index 7c30912cf91..172fd56ed39 100644 --- a/src/libcollections/vec_map.rs +++ b/src/libcollections/vec_map.rs @@ -15,12 +15,14 @@ use core::prelude::*; +use core::cmp::Ordering; use core::default::Default; use core::fmt; use core::hash::{Hash, Writer}; +use core::iter::{Enumerate, FilterMap, Map, FromIterator}; use core::iter; -use core::iter::{Enumerate, FilterMap, Map}; use core::mem::replace; +use core::ops::{Index, IndexMut}; use {vec, slice}; use vec::Vec; diff --git a/src/libcore/array.rs b/src/libcore/array.rs index 28563a60b61..ba7714ad9bc 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -54,7 +54,7 @@ macro_rules! array_impls { #[stable] impl<'a, A, B, Rhs> PartialEq<Rhs> for [A; $N] where A: PartialEq<B>, - Rhs: Deref<[B]>, + Rhs: Deref<Target=[B]>, { #[inline(always)] fn eq(&self, other: &Rhs) -> bool { PartialEq::eq(self[], &**other) } @@ -65,7 +65,7 @@ macro_rules! array_impls { #[stable] impl<'a, A, B, Lhs> PartialEq<[B; $N]> for Lhs where A: PartialEq<B>, - Lhs: Deref<[A]> + Lhs: Deref<Target=[A]> { #[inline(always)] fn eq(&self, other: &[B; $N]) -> bool { PartialEq::eq(&**self, other[]) } diff --git a/src/libcore/atomic.rs b/src/libcore/atomic.rs index 6a40915f4dd..f653998c9bf 100644 --- a/src/libcore/atomic.rs +++ b/src/libcore/atomic.rs @@ -89,17 +89,27 @@ pub enum Ordering { /// An `AtomicBool` initialized to `false`. #[unstable = "may be renamed, pending conventions for static initalizers"] -pub const INIT_ATOMIC_BOOL: AtomicBool = +pub const ATOMIC_BOOL_INIT: AtomicBool = AtomicBool { v: UnsafeCell { value: 0 } }; /// An `AtomicInt` initialized to `0`. #[unstable = "may be renamed, pending conventions for static initalizers"] -pub const INIT_ATOMIC_INT: AtomicInt = +pub const ATOMIC_INT_INIT: AtomicInt = AtomicInt { v: UnsafeCell { value: 0 } }; /// An `AtomicUint` initialized to `0`. #[unstable = "may be renamed, pending conventions for static initalizers"] -pub const INIT_ATOMIC_UINT: AtomicUint = +pub const ATOMIC_UINT_INIT: AtomicUint = AtomicUint { v: UnsafeCell { value: 0, } }; +/// Deprecated +#[deprecated = "renamed to ATOMIC_BOOL_INIT"] +pub const INIT_ATOMIC_BOOL: AtomicBool = ATOMIC_BOOL_INIT; +/// Deprecated +#[deprecated = "renamed to ATOMIC_INT_INIT"] +pub const INIT_ATOMIC_INT: AtomicInt = ATOMIC_INT_INIT; +/// Deprecated +#[deprecated = "renamed to ATOMIC_UINT_INIT"] +pub const INIT_ATOMIC_UINT: AtomicUint = ATOMIC_UINT_INIT; + // NB: Needs to be -1 (0b11111111...) to make fetch_nand work correctly const UINT_TRUE: uint = -1; diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs index 3a2cb8ea7d9..7e4d73d598d 100644 --- a/src/libcore/borrow.rs +++ b/src/libcore/borrow.rs @@ -191,7 +191,9 @@ impl<'a, T, Sized? B> Cow<'a, T, B> where B: ToOwned<T> { } } -impl<'a, T, Sized? B> Deref<B> for Cow<'a, T, B> where B: ToOwned<T> { +impl<'a, T, Sized? B> Deref for Cow<'a, T, B> where B: ToOwned<T> { + type Target = B; + fn deref(&self) -> &B { match *self { Borrowed(borrowed) => borrowed, diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 4b246860006..47204dfc422 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -155,6 +155,8 @@ // FIXME: Can't be shared between threads. Dynamic borrows // FIXME: Relationship to Atomic types and RWLock +#![stable] + use clone::Clone; use cmp::PartialEq; use default::Default; @@ -422,7 +424,9 @@ pub struct Ref<'b, T:'b> { } #[unstable = "waiting for `Deref` to become stable"] -impl<'b, T> Deref<T> for Ref<'b, T> { +impl<'b, T> Deref for Ref<'b, T> { + type Target = T; + #[inline] fn deref<'a>(&'a self) -> &'a T { self._value @@ -478,7 +482,9 @@ pub struct RefMut<'b, T:'b> { } #[unstable = "waiting for `Deref` to become stable"] -impl<'b, T> Deref<T> for RefMut<'b, T> { +impl<'b, T> Deref for RefMut<'b, T> { + type Target = T; + #[inline] fn deref<'a>(&'a self) -> &'a T { self._value @@ -486,7 +492,7 @@ impl<'b, T> Deref<T> for RefMut<'b, T> { } #[unstable = "waiting for `DerefMut` to become stable"] -impl<'b, T> DerefMut<T> for RefMut<'b, T> { +impl<'b, T> DerefMut for RefMut<'b, T> { #[inline] fn deref_mut<'a>(&'a mut self) -> &'a mut T { self._value diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 5d84d0c7797..159c2a505d5 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -25,7 +25,7 @@ use kinds::Sized; /// A common trait for cloning an object. #[stable] -pub trait Clone { +pub trait Clone : Sized { /// Returns a copy of the value. #[stable] fn clone(&self) -> Self; diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 367c794e84b..38906892a33 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -125,11 +125,12 @@ impl Ordering { /// # Example /// /// ```rust + /// use std::cmp::Ordering::{Less, Equal, Greater}; + /// /// assert_eq!(Less.reverse(), Greater); /// assert_eq!(Equal.reverse(), Equal); /// assert_eq!(Greater.reverse(), Less); /// - /// /// let mut data: &mut [_] = &mut [2u, 10, 5, 8]; /// /// // sort the array from largest to smallest. @@ -170,6 +171,8 @@ pub trait Ord for Sized?: Eq + PartialOrd<Self> { /// the expression `self <operator> other` if true. For example: /// /// ``` + /// use std::cmp::Ordering::{Less, Equal, Greater}; + /// /// assert_eq!( 5u.cmp(&10), Less); // because 5 < 10 /// assert_eq!(10u.cmp(&5), Greater); // because 10 > 5 /// assert_eq!( 5u.cmp(&5), Equal); // because 5 == 5 diff --git a/src/libcore/fmt/float.rs b/src/libcore/fmt/float.rs index e1728d762ed..a39168ec1ec 100644 --- a/src/libcore/fmt/float.rs +++ b/src/libcore/fmt/float.rs @@ -23,7 +23,7 @@ use num::FpCategory as Fp; use ops::FnOnce; use result::Result::Ok; use slice::{mod, SliceExt}; -use str::StrExt; +use str::{mod, StrExt}; /// A flag that specifies whether to use exponential (scientific) notation. pub enum ExponentFormat { @@ -95,7 +95,7 @@ pub fn float_to_str_bytes_common<T: Float, U, F>( exp_upper: bool, f: F ) -> U where - F: FnOnce(&[u8]) -> U, + F: FnOnce(&str) -> U, { assert!(2 <= radix && radix <= 36); match exp_format { @@ -109,12 +109,12 @@ pub fn float_to_str_bytes_common<T: Float, U, F>( let _1: T = Float::one(); match num.classify() { - Fp::Nan => return f("NaN".as_bytes()), + Fp::Nan => return f("NaN"), Fp::Infinite if num > _0 => { - return f("inf".as_bytes()); + return f("inf"); } Fp::Infinite if num < _0 => { - return f("-inf".as_bytes()); + return f("-inf"); } _ => {} } @@ -314,11 +314,11 @@ pub fn float_to_str_bytes_common<T: Float, U, F>( end: &'a mut uint, } - impl<'a> fmt::FormatWriter for Filler<'a> { - fn write(&mut self, bytes: &[u8]) -> fmt::Result { + impl<'a> fmt::Writer for Filler<'a> { + fn write_str(&mut self, s: &str) -> fmt::Result { slice::bytes::copy_memory(self.buf.slice_from_mut(*self.end), - bytes); - *self.end += bytes.len(); + s.as_bytes()); + *self.end += s.len(); Ok(()) } } @@ -332,5 +332,5 @@ pub fn float_to_str_bytes_common<T: Float, U, F>( } } - f(buf[..end]) + f(unsafe { str::from_utf8_unchecked(buf[..end]) }) } diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 87fcb12e29f..13fbf5232f8 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -24,7 +24,7 @@ use result::Result::{Ok, Err}; use result; use slice::SliceExt; use slice; -use str::{StrExt, Utf8Error}; +use str::{mod, StrExt, Utf8Error}; pub use self::num::radix; pub use self::num::Radix; @@ -57,7 +57,7 @@ pub struct Error; /// library. The `write!` macro accepts an instance of `io::Writer`, and the /// `io::Writer` trait is favored over implementing this trait. #[experimental = "waiting for core and I/O reconciliation"] -pub trait FormatWriter { +pub trait Writer { /// Writes a slice of bytes into this writer, returning whether the write /// succeeded. /// @@ -68,13 +68,32 @@ pub trait FormatWriter { /// # Errors /// /// This function will return an instance of `FormatError` on error. - fn write(&mut self, bytes: &[u8]) -> Result; + fn write_str(&mut self, s: &str) -> Result; /// Glue for usage of the `write!` macro with implementers of this trait. /// /// This method should generally not be invoked manually, but rather through /// the `write!` macro itself. - fn write_fmt(&mut self, args: Arguments) -> Result { write(self, args) } + fn write_fmt(&mut self, args: Arguments) -> Result { + // This Adapter is needed to allow `self` (of type `&mut + // Self`) to be cast to a FormatWriter (below) without + // requiring a `Sized` bound. + struct Adapter<'a,Sized? T:'a>(&'a mut T); + + impl<'a, Sized? T> Writer for Adapter<'a, T> + where T: Writer + { + fn write_str(&mut self, s: &str) -> Result { + self.0.write_str(s) + } + + fn write_fmt(&mut self, args: Arguments) -> Result { + self.0.write_fmt(args) + } + } + + write(&mut Adapter(self), args) + } } /// A struct to represent both where to emit formatting strings to and how they @@ -88,7 +107,7 @@ pub struct Formatter<'a> { width: Option<uint>, precision: Option<uint>, - buf: &'a mut (FormatWriter+'a), + buf: &'a mut (Writer+'a), curarg: slice::Iter<'a, Argument<'a>>, args: &'a [Argument<'a>], } @@ -258,17 +277,6 @@ pub trait UpperExp for Sized? { fn fmt(&self, &mut Formatter) -> Result; } -static DEFAULT_ARGUMENT: rt::Argument<'static> = rt::Argument { - position: rt::ArgumentNext, - format: rt::FormatSpec { - fill: ' ', - align: rt::AlignUnknown, - flags: 0, - precision: rt::CountImplied, - width: rt::CountImplied, - } -}; - /// The `write` function takes an output stream, a precompiled format string, /// and a list of arguments. The arguments will be formatted according to the /// specified format string into the output stream provided. @@ -279,7 +287,7 @@ static DEFAULT_ARGUMENT: rt::Argument<'static> = rt::Argument { /// * args - the precompiled arguments generated by `format_args!` #[experimental = "libcore and I/O have yet to be reconciled, and this is an \ implementation detail which should not otherwise be exported"] -pub fn write(output: &mut FormatWriter, args: Arguments) -> Result { +pub fn write(output: &mut Writer, args: Arguments) -> Result { let mut formatter = Formatter { flags: 0, width: None, @@ -296,16 +304,16 @@ pub fn write(output: &mut FormatWriter, args: Arguments) -> Result { match args.fmt { None => { // We can use default formatting parameters for all arguments. - for _ in range(0, args.args.len()) { - try!(formatter.buf.write(pieces.next().unwrap().as_bytes())); - try!(formatter.run(&DEFAULT_ARGUMENT)); + for (arg, piece) in args.args.iter().zip(pieces.by_ref()) { + try!(formatter.buf.write_str(*piece)); + try!((arg.formatter)(arg.value, &mut formatter)); } } Some(fmt) => { // Every spec has a corresponding argument that is preceded by // a string piece. for (arg, piece) in fmt.iter().zip(pieces.by_ref()) { - try!(formatter.buf.write(piece.as_bytes())); + try!(formatter.buf.write_str(*piece)); try!(formatter.run(arg)); } } @@ -314,7 +322,7 @@ pub fn write(output: &mut FormatWriter, args: Arguments) -> Result { // There can be only one trailing string piece left. match pieces.next() { Some(piece) => { - try!(formatter.buf.write(piece.as_bytes())); + try!(formatter.buf.write_str(*piece)); } None => {} } @@ -378,7 +386,7 @@ impl<'a> Formatter<'a> { pub fn pad_integral(&mut self, is_positive: bool, prefix: &str, - buf: &[u8]) + buf: &str) -> Result { use char::Char; use fmt::rt::{FlagAlternate, FlagSignPlus, FlagSignAwareZeroPad}; @@ -402,9 +410,10 @@ impl<'a> Formatter<'a> { for c in sign.into_iter() { let mut b = [0; 4]; let n = c.encode_utf8(&mut b).unwrap_or(0); - try!(f.buf.write(b[..n])); + let b = unsafe { str::from_utf8_unchecked(b[0..n]) }; + try!(f.buf.write_str(b)); } - if prefixed { f.buf.write(prefix.as_bytes()) } + if prefixed { f.buf.write_str(prefix) } else { Ok(()) } }; @@ -413,24 +422,26 @@ impl<'a> Formatter<'a> { // If there's no minimum length requirements then we can just // write the bytes. None => { - try!(write_prefix(self)); self.buf.write(buf) + try!(write_prefix(self)); self.buf.write_str(buf) } // Check if we're over the minimum width, if so then we can also // just write the bytes. Some(min) if width >= min => { - try!(write_prefix(self)); self.buf.write(buf) + try!(write_prefix(self)); self.buf.write_str(buf) } // The sign and prefix goes before the padding if the fill character // is zero Some(min) if self.flags & (1 << (FlagSignAwareZeroPad as uint)) != 0 => { self.fill = '0'; try!(write_prefix(self)); - self.with_padding(min - width, rt::AlignRight, |f| f.buf.write(buf)) + self.with_padding(min - width, rt::AlignRight, |f| { + f.buf.write_str(buf) + }) } // Otherwise, the sign and prefix goes after the padding Some(min) => { self.with_padding(min - width, rt::AlignRight, |f| { - try!(write_prefix(f)); f.buf.write(buf) + try!(write_prefix(f)); f.buf.write_str(buf) }) } } @@ -451,7 +462,7 @@ impl<'a> Formatter<'a> { pub fn pad(&mut self, s: &str) -> Result { // Make sure there's a fast path up front if self.width.is_none() && self.precision.is_none() { - return self.buf.write(s.as_bytes()); + return self.buf.write_str(s); } // The `precision` field can be interpreted as a `max-width` for the // string being formatted @@ -463,7 +474,7 @@ impl<'a> Formatter<'a> { let char_len = s.char_len(); if char_len >= max { let nchars = ::cmp::min(max, char_len); - return self.buf.write(s.slice_chars(0, nchars).as_bytes()); + return self.buf.write_str(s.slice_chars(0, nchars)); } } None => {} @@ -472,17 +483,17 @@ impl<'a> Formatter<'a> { match self.width { // If we're under the maximum length, and there's no minimum length // requirements, then we can just emit the string - None => self.buf.write(s.as_bytes()), + None => self.buf.write_str(s), // If we're under the maximum width, check if we're over the minimum // width, if so it's as easy as just emitting the string. Some(width) if s.char_len() >= width => { - self.buf.write(s.as_bytes()) + self.buf.write_str(s) } // If we're under both the maximum and the minimum width, then fill // up the minimum width with the specified string + some alignment. Some(width) => { self.with_padding(width - s.char_len(), rt::AlignLeft, |me| { - me.buf.write(s.as_bytes()) + me.buf.write_str(s) }) } } @@ -507,15 +518,16 @@ impl<'a> Formatter<'a> { let mut fill = [0u8; 4]; let len = self.fill.encode_utf8(&mut fill).unwrap_or(0); + let fill = unsafe { str::from_utf8_unchecked(fill[..len]) }; for _ in range(0, pre_pad) { - try!(self.buf.write(fill[..len])); + try!(self.buf.write_str(fill)); } try!(f(self)); for _ in range(0, post_pad) { - try!(self.buf.write(fill[..len])); + try!(self.buf.write_str(fill)); } Ok(()) @@ -524,8 +536,8 @@ impl<'a> Formatter<'a> { /// Writes some data to the underlying buffer contained within this /// formatter. #[unstable = "reconciling core and I/O may alter this definition"] - pub fn write(&mut self, data: &[u8]) -> Result { - self.buf.write(data) + pub fn write_str(&mut self, data: &str) -> Result { + self.buf.write_str(data) } /// Writes some formatted information into this instance @@ -586,9 +598,6 @@ impl<'a, Sized? T: Show> Show for &'a T { impl<'a, Sized? T: Show> Show for &'a mut T { fn fmt(&self, f: &mut Formatter) -> Result { (**self).fmt(f) } } -impl<'a> Show for &'a (Show+'a) { - fn fmt(&self, f: &mut Formatter) -> Result { (*self).fmt(f) } -} impl Show for bool { fn fmt(&self, f: &mut Formatter) -> Result { @@ -616,7 +625,9 @@ impl Show for char { impl<T> Pointer for *const T { fn fmt(&self, f: &mut Formatter) -> Result { f.flags |= 1 << (rt::FlagAlternate as uint); - LowerHex::fmt(&(*self as uint), f) + let ret = LowerHex::fmt(&(*self as uint), f); + f.flags &= !(1 << (rt::FlagAlternate as uint)); + ret } } diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index 7de3e847dc6..4f0cecbb243 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -18,6 +18,7 @@ use fmt; use iter::DoubleEndedIteratorExt; use num::{Int, cast}; use slice::SliceExt; +use str; /// A type that represents a specific radix #[doc(hidden)] @@ -60,7 +61,8 @@ trait GenericRadix { if x == zero { break }; // No more digits left to accumulate. } } - f.pad_integral(is_positive, self.prefix(), buf[curr..]) + let buf = unsafe { str::from_utf8_unchecked(buf[curr..]) }; + f.pad_integral(is_positive, self.prefix(), buf) } } diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 7c53503b1ce..d7a675b3104 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -54,7 +54,7 @@ //! //! This `for` loop syntax can be applied to any iterator over any type. -pub use self::MinMaxResult::*; +use self::MinMaxResult::*; use clone::Clone; use cmp; @@ -65,6 +65,7 @@ use num::{ToPrimitive, Int}; use ops::{Add, Deref, FnMut}; use option::Option; use option::Option::{Some, None}; +use std::kinds::Sized; use uint; #[deprecated = "renamed to Extend"] pub use self::Extend as Extendable; @@ -109,7 +110,7 @@ pub trait Extend<A> { #[unstable = "new convention for extension traits"] /// An extension trait providing numerous methods applicable to all iterators. -pub trait IteratorExt<A>: Iterator<A> { +pub trait IteratorExt<A>: Iterator<A> + Sized { /// Chain this iterator with another, returning a new iterator that will /// finish iterating over the current iterator, and then iterate /// over the other specified iterator. @@ -692,7 +693,7 @@ impl<A, I> IteratorExt<A> for I where I: Iterator<A> {} /// Extention trait for iterators of pairs. #[unstable = "newly added trait, likely to be merged with IteratorExt"] -pub trait IteratorPairExt<A, B>: Iterator<(A, B)> { +pub trait IteratorPairExt<A, B>: Iterator<(A, B)> + Sized { /// Converts an iterator of pairs into a pair of containers. /// /// Loops through the entire iterator, collecting the first component of @@ -738,7 +739,7 @@ pub trait DoubleEndedIterator<A>: Iterator<A> { /// Extension methods for double-ended iterators. #[unstable = "new extension trait convention"] -pub trait DoubleEndedIteratorExt<A>: DoubleEndedIterator<A> { +pub trait DoubleEndedIteratorExt<A>: DoubleEndedIterator<A> + Sized { /// Change the direction of the iterator /// /// The flipped iterator swaps the ends on an iterator that can already @@ -1035,7 +1036,7 @@ pub trait IteratorOrdExt<A> { /// # Example /// /// ```rust - /// use std::iter::{NoElements, OneElement, MinMax}; + /// use std::iter::MinMaxResult::{NoElements, OneElement, MinMax}; /// /// let v: [int; 0] = []; /// assert_eq!(v.iter().min_max(), NoElements); @@ -1145,7 +1146,7 @@ impl<T: Clone> MinMaxResult<T> { /// # Example /// /// ```rust - /// use std::iter::{NoElements, OneElement, MinMax, MinMaxResult}; + /// use std::iter::MinMaxResult::{mod, NoElements, OneElement, MinMax}; /// /// let r: MinMaxResult<int> = NoElements; /// assert_eq!(r.into_option(), None); @@ -1174,7 +1175,7 @@ pub trait IteratorCloneExt<A> { } #[unstable = "trait is unstable"] -impl<A: Clone, D: Deref<A>, I: Iterator<D>> IteratorCloneExt<A> for I { +impl<A: Clone, D: Deref<Target=A>, I: Iterator<D>> IteratorCloneExt<A> for I { fn cloned(self) -> Cloned<I> { Cloned { it: self } } @@ -1185,7 +1186,7 @@ pub struct Cloned<I> { it: I, } -impl<A: Clone, D: Deref<A>, I: Iterator<D>> Iterator<A> for Cloned<I> { +impl<A: Clone, D: Deref<Target=A>, I: Iterator<D>> Iterator<A> for Cloned<I> { fn next(&mut self) -> Option<A> { self.it.next().cloned() } @@ -1195,7 +1196,7 @@ impl<A: Clone, D: Deref<A>, I: Iterator<D>> Iterator<A> for Cloned<I> { } } -impl<A: Clone, D: Deref<A>, I: DoubleEndedIterator<D>> +impl<A: Clone, D: Deref<Target=A>, I: DoubleEndedIterator<D>> DoubleEndedIterator<A> for Cloned<I> { fn next_back(&mut self) -> Option<A> { self.it.next_back().cloned() @@ -1203,7 +1204,7 @@ impl<A: Clone, D: Deref<A>, I: DoubleEndedIterator<D>> } #[unstable = "trait is unstable"] -impl<A: Clone, D: Deref<A>, I: ExactSizeIterator<D>> ExactSizeIterator<A> for Cloned<I> {} +impl<A: Clone, D: Deref<Target=A>, I: ExactSizeIterator<D>> ExactSizeIterator<A> for Cloned<I> {} #[unstable = "recently renamed for extension trait conventions"] /// An extension trait for cloneable iterators. diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs index c429e4b8212..ba9103520d8 100644 --- a/src/libcore/nonzero.rs +++ b/src/libcore/nonzero.rs @@ -44,7 +44,9 @@ impl<T: Zeroable> NonZero<T> { } } -impl<T: Zeroable> Deref<T> for NonZero<T> { +impl<T: Zeroable> Deref for NonZero<T> { + type Target = T; + #[inline] fn deref<'a>(&'a self) -> &'a T { let NonZero(ref inner) = *self; diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 0d2ce4f6071..d16478dd6cc 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -980,7 +980,7 @@ impl_to_primitive_float! { f64 } /// A generic trait for converting a number to a value. #[experimental = "trait is likely to be removed"] -pub trait FromPrimitive { +pub trait FromPrimitive : ::kinds::Sized { /// Convert an `int` to return an optional value of this type. If the /// value cannot be represented by this value, the `None` is returned. #[inline] diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index af07869e95f..b51d4d91c2f 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -25,6 +25,8 @@ //! demonstrates adding and subtracting two `Point`s. //! //! ```rust +//! use std::ops::{Add, Sub}; +//! //! #[deriving(Show)] //! struct Point { //! x: int, @@ -68,13 +70,13 @@ use option::Option::{mod, Some, None}; /// struct HasDrop; /// /// impl Drop for HasDrop { -/// fn drop(&mut self) { -/// println!("Dropping!"); -/// } +/// fn drop(&mut self) { +/// println!("Dropping!"); +/// } /// } /// /// fn main() { -/// let _x = HasDrop; +/// let _x = HasDrop; /// } /// ``` #[lang="drop"] @@ -91,6 +93,8 @@ pub trait Drop { /// calling `add`, and therefore, `main` prints `Adding!`. /// /// ```rust +/// use std::ops::Add; +/// /// #[deriving(Copy)] /// struct Foo; /// @@ -130,6 +134,8 @@ add_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 } /// calling `sub`, and therefore, `main` prints `Subtracting!`. /// /// ```rust +/// use std::ops::Sub; +/// /// #[deriving(Copy)] /// struct Foo; /// @@ -169,6 +175,8 @@ sub_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 } /// calling `mul`, and therefore, `main` prints `Multiplying!`. /// /// ```rust +/// use std::ops::Mul; +/// /// #[deriving(Copy)] /// struct Foo; /// @@ -208,6 +216,8 @@ mul_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 } /// calling `div`, and therefore, `main` prints `Dividing!`. /// /// ``` +/// use std::ops::Div; +/// /// #[deriving(Copy)] /// struct Foo; /// @@ -247,6 +257,8 @@ div_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 } /// calling `rem`, and therefore, `main` prints `Remainder-ing!`. /// /// ``` +/// use std::ops::Rem; +/// /// #[deriving(Copy)] /// struct Foo; /// @@ -300,6 +312,8 @@ rem_float_impl! { f64, fmod } /// `neg`, and therefore, `main` prints `Negating!`. /// /// ``` +/// use std::ops::Neg; +/// /// struct Foo; /// /// impl Copy for Foo {} @@ -356,6 +370,8 @@ neg_uint_impl! { u64, i64 } /// `not`, and therefore, `main` prints `Not-ing!`. /// /// ``` +/// use std::ops::Not; +/// /// struct Foo; /// /// impl Copy for Foo {} @@ -396,6 +412,8 @@ not_impl! { bool uint u8 u16 u32 u64 int i8 i16 i32 i64 } /// calling `bitand`, and therefore, `main` prints `Bitwise And-ing!`. /// /// ``` +/// use std::ops::BitAnd; +/// /// #[deriving(Copy)] /// struct Foo; /// @@ -435,6 +453,8 @@ bitand_impl! { bool uint u8 u16 u32 u64 int i8 i16 i32 i64 } /// calling `bitor`, and therefore, `main` prints `Bitwise Or-ing!`. /// /// ``` +/// use std::ops::BitOr; +/// /// #[deriving(Copy)] /// struct Foo; /// @@ -474,6 +494,8 @@ bitor_impl! { bool uint u8 u16 u32 u64 int i8 i16 i32 i64 } /// calling `bitxor`, and therefore, `main` prints `Bitwise Xor-ing!`. /// /// ``` +/// use std::ops::BitXor; +/// /// #[deriving(Copy)] /// struct Foo; /// @@ -513,6 +535,8 @@ bitxor_impl! { bool uint u8 u16 u32 u64 int i8 i16 i32 i64 } /// calling `shl`, and therefore, `main` prints `Shifting left!`. /// /// ``` +/// use std::ops::Shl; +/// /// #[deriving(Copy)] /// struct Foo; /// @@ -554,6 +578,8 @@ shl_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 } /// calling `shr`, and therefore, `main` prints `Shifting right!`. /// /// ``` +/// use std::ops::Shr; +/// /// #[deriving(Copy)] /// struct Foo; /// @@ -594,6 +620,8 @@ shr_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 } /// calling `index`, and therefore, `main` prints `Indexing!`. /// /// ``` +/// use std::ops::Index; +/// /// #[deriving(Copy)] /// struct Foo; /// @@ -623,6 +651,8 @@ pub trait Index<Sized? Index, Sized? Result> for Sized? { /// calling `index_mut`, and therefore, `main` prints `Indexing!`. /// /// ``` +/// use std::ops::IndexMut; +/// /// #[deriving(Copy)] /// struct Foo; /// @@ -652,6 +682,8 @@ pub trait IndexMut<Sized? Index, Sized? Result> for Sized? { /// calling `slice_to`, and therefore, `main` prints `Slicing!`. /// /// ```ignore +/// use std::ops::Slice; +/// /// #[deriving(Copy)] /// struct Foo; /// @@ -699,6 +731,8 @@ pub trait Slice<Sized? Idx, Sized? Result> for Sized? { /// calling `slice_from_mut`, and therefore, `main` prints `Slicing!`. /// /// ```ignore +/// use std::ops::SliceMut; +/// /// #[deriving(Copy)] /// struct Foo; /// @@ -827,11 +861,17 @@ pub struct RangeTo<Idx> { /// struct. /// /// ``` +/// #![feature(associated_types)] +/// +/// use std::ops::Deref; +/// /// struct DerefExample<T> { /// value: T /// } /// -/// impl<T> Deref<T> for DerefExample<T> { +/// impl<T> Deref for DerefExample<T> { +/// type Target = T; +/// /// fn deref<'a>(&'a self) -> &'a T { /// &self.value /// } @@ -843,16 +883,22 @@ pub struct RangeTo<Idx> { /// } /// ``` #[lang="deref"] -pub trait Deref<Sized? Result> for Sized? { +pub trait Deref for Sized? { + type Sized? Target; + /// The method called to dereference a value - fn deref<'a>(&'a self) -> &'a Result; + fn deref<'a>(&'a self) -> &'a Self::Target; } -impl<'a, Sized? T> Deref<T> for &'a T { +impl<'a, Sized? T> Deref for &'a T { + type Target = T; + fn deref(&self) -> &T { *self } } -impl<'a, Sized? T> Deref<T> for &'a mut T { +impl<'a, Sized? T> Deref for &'a mut T { + type Target = T; + fn deref(&self) -> &T { *self } } @@ -865,17 +911,23 @@ impl<'a, Sized? T> Deref<T> for &'a mut T { /// struct. /// /// ``` +/// #![feature(associated_types)] +/// +/// use std::ops::{Deref, DerefMut}; +/// /// struct DerefMutExample<T> { /// value: T /// } /// -/// impl<T> Deref<T> for DerefMutExample<T> { +/// impl<T> Deref for DerefMutExample<T> { +/// type Target = T; +/// /// fn deref<'a>(&'a self) -> &'a T { /// &self.value /// } /// } /// -/// impl<T> DerefMut<T> for DerefMutExample<T> { +/// impl<T> DerefMut for DerefMutExample<T> { /// fn deref_mut<'a>(&'a mut self) -> &'a mut T { /// &mut self.value /// } @@ -888,12 +940,12 @@ impl<'a, Sized? T> Deref<T> for &'a mut T { /// } /// ``` #[lang="deref_mut"] -pub trait DerefMut<Sized? Result> for Sized? : Deref<Result> { +pub trait DerefMut for Sized? : Deref { /// The method called to mutably dereference a value - fn deref_mut<'a>(&'a mut self) -> &'a mut Result; + fn deref_mut<'a>(&'a mut self) -> &'a mut <Self as Deref>::Target; } -impl<'a, Sized? T> DerefMut<T> for &'a mut T { +impl<'a, Sized? T> DerefMut for &'a mut T { fn deref_mut(&mut self) -> &mut T { *self } } diff --git a/src/libcore/option.rs b/src/libcore/option.rs index d831a57893b..b9749f57d58 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -699,7 +699,7 @@ impl<T> Option<T> { } } -impl<'a, T: Clone, D: Deref<T>> Option<D> { +impl<'a, T: Clone, D: Deref<Target=T>> Option<D> { /// Maps an Option<D> to an Option<T> by dereffing and cloning the contents of the Option. /// Useful for converting an Option<&T> to an Option<T>. #[unstable = "recently added as part of collections reform"] diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index cecb4938153..8cb63138009 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -30,39 +30,23 @@ // Reexported core operators pub use kinds::{Copy, Send, Sized, Sync}; -pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not}; -pub use ops::{BitAnd, BitOr, BitXor}; -pub use ops::{Drop, Deref, DerefMut}; -pub use ops::{Shl, Shr}; -pub use ops::{Index, IndexMut}; -pub use ops::{Slice, SliceMut}; -pub use ops::{Fn, FnMut, FnOnce}; +pub use ops::{Drop, Fn, FnMut, FnOnce}; // Reexported functions pub use iter::range; pub use mem::drop; -pub use str::from_str; // Reexported types and traits pub use char::Char; pub use clone::Clone; pub use cmp::{PartialEq, PartialOrd, Eq, Ord}; -pub use cmp::{Ordering, Equiv}; -pub use cmp::Ordering::{Less, Equal, Greater}; -pub use iter::{FromIterator, Extend, IteratorExt}; -pub use iter::{Iterator, DoubleEndedIterator, DoubleEndedIteratorExt, RandomAccessIterator}; -pub use iter::{IteratorCloneExt, CloneIteratorExt, IteratorPairExt}; -pub use iter::{IteratorOrdExt, MutableDoubleEndedIterator, ExactSizeIterator}; -pub use num::{ToPrimitive, FromPrimitive}; -pub use option::Option; -pub use option::Option::{Some, None}; +pub use iter::{Extend, IteratorExt}; +pub use iter::{Iterator, DoubleEndedIterator, DoubleEndedIteratorExt}; +pub use iter::{IteratorCloneExt, CloneIteratorExt}; +pub use iter::{IteratorOrdExt, ExactSizeIterator, IteratorPairExt}; +pub use option::Option::{mod, Some, None}; pub use ptr::{PtrExt, MutPtrExt}; -pub use result::Result; -pub use result::Result::{Ok, Err}; -pub use str::{Str, StrExt}; -pub use tuple::{Tuple1, Tuple2, Tuple3, Tuple4}; -pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8}; -pub use tuple::{Tuple9, Tuple10, Tuple11, Tuple12}; -pub use slice::{PartialEqSliceExt, OrdSliceExt}; +pub use result::Result::{mod, Ok, Err}; pub use slice::{AsSlice, SliceExt}; +pub use str::{Str, StrExt}; diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index faf1d781465..f29d7518149 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -92,7 +92,7 @@ use mem; use clone::Clone; use intrinsics; use option::Option::{mod, Some, None}; -use kinds::{Send, Sync}; +use kinds::{Send, Sized, Sync}; use cmp::{PartialEq, Eq, Ord, PartialOrd, Equiv}; use cmp::Ordering::{mod, Less, Equal, Greater}; @@ -243,7 +243,9 @@ pub unsafe fn write<T>(dst: *mut T, src: T) { /// Methods on raw pointers #[stable] -pub trait PtrExt<T> { +pub trait PtrExt: Sized { + type Target; + /// Returns the null pointer. #[deprecated = "call ptr::null instead"] fn null() -> Self; @@ -271,7 +273,7 @@ pub trait PtrExt<T> { /// memory. #[unstable = "Option is not clearly the right return type, and we may want \ to tie the return lifetime to a borrow of the raw pointer"] - unsafe fn as_ref<'a>(&self) -> Option<&'a T>; + unsafe fn as_ref<'a>(&self) -> Option<&'a Self::Target>; /// Calculates the offset from a pointer. `count` is in units of T; e.g. a /// `count` of 3 represents a pointer offset of `3 * sizeof::<T>()` bytes. @@ -287,7 +289,9 @@ pub trait PtrExt<T> { /// Methods on mutable raw pointers #[stable] -pub trait MutPtrExt<T>{ +pub trait MutPtrExt { + type Target; + /// Returns `None` if the pointer is null, or else returns a mutable /// reference to the value wrapped in `Some`. /// @@ -297,11 +301,13 @@ pub trait MutPtrExt<T>{ /// of the returned pointer. #[unstable = "Option is not clearly the right return type, and we may want \ to tie the return lifetime to a borrow of the raw pointer"] - unsafe fn as_mut<'a>(&self) -> Option<&'a mut T>; + unsafe fn as_mut<'a>(&self) -> Option<&'a mut Self::Target>; } #[stable] -impl<T> PtrExt<T> for *const T { +impl<T> PtrExt for *const T { + type Target = T; + #[inline] #[deprecated = "call ptr::null instead"] fn null() -> *const T { null() } @@ -333,7 +339,9 @@ impl<T> PtrExt<T> for *const T { } #[stable] -impl<T> PtrExt<T> for *mut T { +impl<T> PtrExt for *mut T { + type Target = T; + #[inline] #[deprecated = "call ptr::null instead"] fn null() -> *mut T { null_mut() } @@ -365,7 +373,9 @@ impl<T> PtrExt<T> for *mut T { } #[stable] -impl<T> MutPtrExt<T> for *mut T { +impl<T> MutPtrExt for *mut T { + type Target = T; + #[inline] #[unstable = "return value does not necessarily convey all possible \ information"] diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 7d894ac697b..07addf7a569 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -64,57 +64,77 @@ use raw::Slice as RawSlice; /// Extension methods for slices. #[allow(missing_docs)] // docs in libcollections -pub trait SliceExt<T> for Sized? { - fn slice<'a>(&'a self, start: uint, end: uint) -> &'a [T]; - fn slice_from<'a>(&'a self, start: uint) -> &'a [T]; - fn slice_to<'a>(&'a self, end: uint) -> &'a [T]; - fn split_at<'a>(&'a self, mid: uint) -> (&'a [T], &'a [T]); - fn iter<'a>(&'a self) -> Iter<'a, T>; - fn split<'a, P>(&'a self, pred: P) -> Split<'a, T, P> - where P: FnMut(&T) -> bool; - fn splitn<'a, P>(&'a self, n: uint, pred: P) -> SplitN<'a, T, P> - where P: FnMut(&T) -> bool; - fn rsplitn<'a, P>(&'a self, n: uint, pred: P) -> RSplitN<'a, T, P> - where P: FnMut(&T) -> bool; - fn windows<'a>(&'a self, size: uint) -> Windows<'a, T>; - fn chunks<'a>(&'a self, size: uint) -> Chunks<'a, T>; - fn get<'a>(&'a self, index: uint) -> Option<&'a T>; - fn first<'a>(&'a self) -> Option<&'a T>; - fn tail<'a>(&'a self) -> &'a [T]; - fn init<'a>(&'a self) -> &'a [T]; - fn last<'a>(&'a self) -> Option<&'a T>; - unsafe fn get_unchecked<'a>(&'a self, index: uint) -> &'a T; - fn as_ptr(&self) -> *const T; +pub trait SliceExt for Sized? { + type Item; + + fn slice<'a>(&'a self, start: uint, end: uint) -> &'a [Self::Item]; + fn slice_from<'a>(&'a self, start: uint) -> &'a [Self::Item]; + fn slice_to<'a>(&'a self, end: uint) -> &'a [Self::Item]; + fn split_at<'a>(&'a self, mid: uint) -> (&'a [Self::Item], &'a [Self::Item]); + fn iter<'a>(&'a self) -> Iter<'a, Self::Item>; + fn split<'a, P>(&'a self, pred: P) -> Split<'a, Self::Item, P> + where P: FnMut(&Self::Item) -> bool; + fn splitn<'a, P>(&'a self, n: uint, pred: P) -> SplitN<'a, Self::Item, P> + where P: FnMut(&Self::Item) -> bool; + fn rsplitn<'a, P>(&'a self, n: uint, pred: P) -> RSplitN<'a, Self::Item, P> + where P: FnMut(&Self::Item) -> bool; + fn windows<'a>(&'a self, size: uint) -> Windows<'a, Self::Item>; + fn chunks<'a>(&'a self, size: uint) -> Chunks<'a, Self::Item>; + fn get<'a>(&'a self, index: uint) -> Option<&'a Self::Item>; + fn first<'a>(&'a self) -> Option<&'a Self::Item>; + fn tail<'a>(&'a self) -> &'a [Self::Item]; + fn init<'a>(&'a self) -> &'a [Self::Item]; + fn last<'a>(&'a self) -> Option<&'a Self::Item>; + unsafe fn get_unchecked<'a>(&'a self, index: uint) -> &'a Self::Item; + fn as_ptr(&self) -> *const Self::Item; fn binary_search_by<F>(&self, f: F) -> Result<uint, uint> where - F: FnMut(&T) -> Ordering; + F: FnMut(&Self::Item) -> Ordering; fn len(&self) -> uint; fn is_empty(&self) -> bool { self.len() == 0 } - fn get_mut<'a>(&'a mut self, index: uint) -> Option<&'a mut T>; - fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T]; - fn slice_mut<'a>(&'a mut self, start: uint, end: uint) -> &'a mut [T]; - fn slice_from_mut<'a>(&'a mut self, start: uint) -> &'a mut [T]; - fn slice_to_mut<'a>(&'a mut self, end: uint) -> &'a mut [T]; - fn iter_mut<'a>(&'a mut self) -> IterMut<'a, T>; - fn first_mut<'a>(&'a mut self) -> Option<&'a mut T>; - fn tail_mut<'a>(&'a mut self) -> &'a mut [T]; - fn init_mut<'a>(&'a mut self) -> &'a mut [T]; - fn last_mut<'a>(&'a mut self) -> Option<&'a mut T>; - fn split_mut<'a, P>(&'a mut self, pred: P) -> SplitMut<'a, T, P> - where P: FnMut(&T) -> bool; - fn splitn_mut<P>(&mut self, n: uint, pred: P) -> SplitNMut<T, P> - where P: FnMut(&T) -> bool; - fn rsplitn_mut<P>(&mut self, n: uint, pred: P) -> RSplitNMut<T, P> - where P: FnMut(&T) -> bool; - fn chunks_mut<'a>(&'a mut self, chunk_size: uint) -> ChunksMut<'a, T>; + fn get_mut<'a>(&'a mut self, index: uint) -> Option<&'a mut Self::Item>; + fn as_mut_slice<'a>(&'a mut self) -> &'a mut [Self::Item]; + fn slice_mut<'a>(&'a mut self, start: uint, end: uint) -> &'a mut [Self::Item]; + fn slice_from_mut<'a>(&'a mut self, start: uint) -> &'a mut [Self::Item]; + fn slice_to_mut<'a>(&'a mut self, end: uint) -> &'a mut [Self::Item]; + fn iter_mut<'a>(&'a mut self) -> IterMut<'a, Self::Item>; + fn first_mut<'a>(&'a mut self) -> Option<&'a mut Self::Item>; + fn tail_mut<'a>(&'a mut self) -> &'a mut [Self::Item]; + fn init_mut<'a>(&'a mut self) -> &'a mut [Self::Item]; + fn last_mut<'a>(&'a mut self) -> Option<&'a mut Self::Item>; + fn split_mut<'a, P>(&'a mut self, pred: P) -> SplitMut<'a, Self::Item, P> + where P: FnMut(&Self::Item) -> bool; + fn splitn_mut<P>(&mut self, n: uint, pred: P) -> SplitNMut<Self::Item, P> + where P: FnMut(&Self::Item) -> bool; + fn rsplitn_mut<P>(&mut self, n: uint, pred: P) -> RSplitNMut<Self::Item, P> + where P: FnMut(&Self::Item) -> bool; + fn chunks_mut<'a>(&'a mut self, chunk_size: uint) -> ChunksMut<'a, Self::Item>; fn swap(&mut self, a: uint, b: uint); - fn split_at_mut<'a>(&'a mut self, mid: uint) -> (&'a mut [T], &'a mut [T]); + fn split_at_mut<'a>(&'a mut self, mid: uint) -> (&'a mut [Self::Item], &'a mut [Self::Item]); fn reverse(&mut self); - unsafe fn get_unchecked_mut<'a>(&'a mut self, index: uint) -> &'a mut T; - fn as_mut_ptr(&mut self) -> *mut T; + unsafe fn get_unchecked_mut<'a>(&'a mut self, index: uint) -> &'a mut Self::Item; + fn as_mut_ptr(&mut self) -> *mut Self::Item; + + fn position_elem(&self, t: &Self::Item) -> Option<uint> where Self::Item: PartialEq; + + fn rposition_elem(&self, t: &Self::Item) -> Option<uint> where Self::Item: PartialEq; + + fn contains(&self, x: &Self::Item) -> bool where Self::Item: PartialEq; + + fn starts_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq; + + fn ends_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq; + + fn binary_search(&self, x: &Self::Item) -> Result<uint, uint> where Self::Item: Ord; + fn next_permutation(&mut self) -> bool where Self::Item: Ord; + fn prev_permutation(&mut self) -> bool where Self::Item: Ord; + + fn clone_from_slice(&mut self, &[Self::Item]) -> uint where Self::Item: Clone; } #[unstable] -impl<T> SliceExt<T> for [T] { +impl<T> SliceExt for [T] { + type Item = T; + #[inline] fn slice(&self, start: uint, end: uint) -> &[T] { assert!(start <= end); @@ -404,153 +424,41 @@ impl<T> SliceExt<T> for [T] { fn as_mut_ptr(&mut self) -> *mut T { self.repr().data as *mut T } -} - -impl<T> ops::Index<uint, T> for [T] { - fn index(&self, &index: &uint) -> &T { - assert!(index < self.len()); - - unsafe { mem::transmute(self.repr().data.offset(index as int)) } - } -} - -impl<T> ops::IndexMut<uint, T> for [T] { - fn index_mut(&mut self, &index: &uint) -> &mut T { - assert!(index < self.len()); - - unsafe { mem::transmute(self.repr().data.offset(index as int)) } - } -} - -impl<T> ops::Slice<uint, [T]> for [T] { - #[inline] - fn as_slice_<'a>(&'a self) -> &'a [T] { - self - } - - #[inline] - fn slice_from_or_fail<'a>(&'a self, start: &uint) -> &'a [T] { - self.slice_or_fail(start, &self.len()) - } - - #[inline] - fn slice_to_or_fail<'a>(&'a self, end: &uint) -> &'a [T] { - self.slice_or_fail(&0, end) - } - #[inline] - fn slice_or_fail<'a>(&'a self, start: &uint, end: &uint) -> &'a [T] { - assert!(*start <= *end); - assert!(*end <= self.len()); - unsafe { - transmute(RawSlice { - data: self.as_ptr().offset(*start as int), - len: (*end - *start) - }) - } - } -} - -impl<T> ops::SliceMut<uint, [T]> for [T] { - #[inline] - fn as_mut_slice_<'a>(&'a mut self) -> &'a mut [T] { - self - } - - #[inline] - fn slice_from_or_fail_mut<'a>(&'a mut self, start: &uint) -> &'a mut [T] { - let len = &self.len(); - self.slice_or_fail_mut(start, len) - } - - #[inline] - fn slice_to_or_fail_mut<'a>(&'a mut self, end: &uint) -> &'a mut [T] { - self.slice_or_fail_mut(&0, end) - } - #[inline] - fn slice_or_fail_mut<'a>(&'a mut self, start: &uint, end: &uint) -> &'a mut [T] { - assert!(*start <= *end); - assert!(*end <= self.len()); - unsafe { - transmute(RawSlice { - data: self.as_ptr().offset(*start as int), - len: (*end - *start) - }) - } - } -} - -/// Extension methods for slices containing `PartialEq` elements. -#[unstable = "may merge with SliceExt"] -pub trait PartialEqSliceExt<T: PartialEq> for Sized? { - /// Find the first index containing a matching value. - #[experimental] - fn position_elem(&self, t: &T) -> Option<uint>; - - /// Find the last index containing a matching value. - #[experimental] - fn rposition_elem(&self, t: &T) -> Option<uint>; - - /// Return true if the slice contains an element with the given value. - #[stable] - fn contains(&self, x: &T) -> bool; - - /// Returns true if `needle` is a prefix of the slice. - #[stable] - fn starts_with(&self, needle: &[T]) -> bool; - - /// Returns true if `needle` is a suffix of the slice. - #[stable] - fn ends_with(&self, needle: &[T]) -> bool; -} -#[unstable = "trait is unstable"] -impl<T: PartialEq> PartialEqSliceExt<T> for [T] { #[inline] - fn position_elem(&self, x: &T) -> Option<uint> { + fn position_elem(&self, x: &T) -> Option<uint> where T: PartialEq { self.iter().position(|y| *x == *y) } #[inline] - fn rposition_elem(&self, t: &T) -> Option<uint> { + fn rposition_elem(&self, t: &T) -> Option<uint> where T: PartialEq { self.iter().rposition(|x| *x == *t) } #[inline] - fn contains(&self, x: &T) -> bool { + fn contains(&self, x: &T) -> bool where T: PartialEq { self.iter().any(|elt| *x == *elt) } #[inline] - fn starts_with(&self, needle: &[T]) -> bool { + fn starts_with(&self, needle: &[T]) -> bool where T: PartialEq { let n = needle.len(); self.len() >= n && needle == self[..n] } #[inline] - fn ends_with(&self, needle: &[T]) -> bool { + fn ends_with(&self, needle: &[T]) -> bool where T: PartialEq { let (m, n) = (self.len(), needle.len()); m >= n && needle == self[m-n..] } -} -/// Extension methods for slices containing `Ord` elements. -#[unstable = "may merge with other traits"] -#[allow(missing_docs)] // docs in libcollections -pub trait OrdSliceExt<T: Ord> for Sized? { - fn binary_search(&self, x: &T) -> Result<uint, uint>; - fn next_permutation(&mut self) -> bool; - fn prev_permutation(&mut self) -> bool; -} - -#[unstable = "trait is unstable"] -impl<T: Ord> OrdSliceExt<T> for [T] { #[unstable] - fn binary_search(&self, x: &T) -> Result<uint, uint> { + fn binary_search(&self, x: &T) -> Result<uint, uint> where T: Ord { self.binary_search_by(|p| p.cmp(x)) } #[experimental] - fn next_permutation(&mut self) -> bool { + fn next_permutation(&mut self) -> bool where T: Ord { // These cases only have 1 permutation each, so we can't do anything. if self.len() < 2 { return false; } @@ -581,7 +489,7 @@ impl<T: Ord> OrdSliceExt<T> for [T] { } #[experimental] - fn prev_permutation(&mut self) -> bool { + fn prev_permutation(&mut self) -> bool where T: Ord { // These cases only have 1 permutation each, so we can't do anything. if self.len() < 2 { return false; } @@ -610,19 +518,9 @@ impl<T: Ord> OrdSliceExt<T> for [T] { true } -} -/// Extension methods for slices on Clone elements -#[unstable = "may merge with other traits"] -#[allow(missing_docs)] // docs in libcollections -pub trait CloneSliceExt<T> for Sized? { - fn clone_from_slice(&mut self, &[T]) -> uint; -} - -#[unstable = "trait is unstable"] -impl<T: Clone> CloneSliceExt<T> for [T] { #[inline] - fn clone_from_slice(&mut self, src: &[T]) -> uint { + fn clone_from_slice(&mut self, src: &[T]) -> uint where T: Clone { let min = cmp::min(self.len(), src.len()); let dst = self.slice_to_mut(min); let src = src.slice_to(min); @@ -633,6 +531,79 @@ impl<T: Clone> CloneSliceExt<T> for [T] { } } +impl<T> ops::Index<uint, T> for [T] { + fn index(&self, &index: &uint) -> &T { + assert!(index < self.len()); + + unsafe { mem::transmute(self.repr().data.offset(index as int)) } + } +} + +impl<T> ops::IndexMut<uint, T> for [T] { + fn index_mut(&mut self, &index: &uint) -> &mut T { + assert!(index < self.len()); + + unsafe { mem::transmute(self.repr().data.offset(index as int)) } + } +} + +impl<T> ops::Slice<uint, [T]> for [T] { + #[inline] + fn as_slice_<'a>(&'a self) -> &'a [T] { + self + } + + #[inline] + fn slice_from_or_fail<'a>(&'a self, start: &uint) -> &'a [T] { + self.slice_or_fail(start, &self.len()) + } + + #[inline] + fn slice_to_or_fail<'a>(&'a self, end: &uint) -> &'a [T] { + self.slice_or_fail(&0, end) + } + #[inline] + fn slice_or_fail<'a>(&'a self, start: &uint, end: &uint) -> &'a [T] { + assert!(*start <= *end); + assert!(*end <= self.len()); + unsafe { + transmute(RawSlice { + data: self.as_ptr().offset(*start as int), + len: (*end - *start) + }) + } + } +} + +impl<T> ops::SliceMut<uint, [T]> for [T] { + #[inline] + fn as_mut_slice_<'a>(&'a mut self) -> &'a mut [T] { + self + } + + #[inline] + fn slice_from_or_fail_mut<'a>(&'a mut self, start: &uint) -> &'a mut [T] { + let len = &self.len(); + self.slice_or_fail_mut(start, len) + } + + #[inline] + fn slice_to_or_fail_mut<'a>(&'a mut self, end: &uint) -> &'a mut [T] { + self.slice_or_fail_mut(&0, end) + } + #[inline] + fn slice_or_fail_mut<'a>(&'a mut self, start: &uint, end: &uint) -> &'a mut [T] { + assert!(*start <= *end); + assert!(*end <= self.len()); + unsafe { + transmute(RawSlice { + data: self.as_ptr().offset(*start as int), + len: (*end - *start) + }) + } + } +} + //////////////////////////////////////////////////////////////////////////////// // Common traits //////////////////////////////////////////////////////////////////////////////// diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs index 576989fabe7..ad2323296d9 100644 --- a/src/libcore/tuple.rs +++ b/src/libcore/tuple.rs @@ -32,35 +32,6 @@ //! * `PartialOrd` //! * `Ord` //! * `Default` -//! -//! # Examples -//! -//! Using methods: -//! -//! ``` -//! #[allow(deprecated)] -//! # fn main() { -//! let pair = ("pi", 3.14f64); -//! assert_eq!(pair.val0(), "pi"); -//! assert_eq!(pair.val1(), 3.14f64); -//! # } -//! ``` -//! -//! Using traits implemented for tuples: -//! -//! ``` -//! use std::default::Default; -//! -//! let a = (1i, 2i); -//! let b = (3i, 4i); -//! assert!(a != b); -//! -//! let c = b.clone(); -//! assert!(b == c); -//! -//! let d : (u32, f32) = Default::default(); -//! assert_eq!(d, (0u32, 0.0f32)); -//! ``` #![stable] diff --git a/src/libcoretest/atomic.rs b/src/libcoretest/atomic.rs index 1fee304a976..f8e943ec9f6 100644 --- a/src/libcoretest/atomic.rs +++ b/src/libcoretest/atomic.rs @@ -70,9 +70,9 @@ fn int_xor() { assert_eq!(x.load(SeqCst), 0xf731 ^ 0x137f); } -static S_BOOL : AtomicBool = INIT_ATOMIC_BOOL; -static S_INT : AtomicInt = INIT_ATOMIC_INT; -static S_UINT : AtomicUint = INIT_ATOMIC_UINT; +static S_BOOL : AtomicBool = ATOMIC_BOOL_INIT; +static S_INT : AtomicInt = ATOMIC_INT_INIT; +static S_UINT : AtomicUint = ATOMIC_UINT_INIT; #[test] fn static_init() { diff --git a/src/libcoretest/cmp.rs b/src/libcoretest/cmp.rs index 716300f652d..992c99f1f9f 100644 --- a/src/libcoretest/cmp.rs +++ b/src/libcoretest/cmp.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::cmp::{ partial_min, partial_max }; +use core::cmp::{partial_min, partial_max}; +use core::cmp::Ordering::{Less, Greater, Equal}; #[test] fn test_int_totalord() { diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index d450e557383..7952c96a117 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -10,6 +10,7 @@ use core::iter::*; use core::iter::order::*; +use core::iter::MinMaxResult::*; use core::num::SignedInt; use core::uint; use core::cmp; diff --git a/src/libcoretest/num/int_macros.rs b/src/libcoretest/num/int_macros.rs index 55e0f10c865..e409dc61510 100644 --- a/src/libcoretest/num/int_macros.rs +++ b/src/libcoretest/num/int_macros.rs @@ -17,6 +17,7 @@ mod tests { use core::int; use core::num::{FromStrRadix, Int, SignedInt}; use core::str::from_str; + use core::ops::{Shl, Shr, Not, BitXor, BitAnd, BitOr}; use num; #[test] diff --git a/src/libcoretest/num/mod.rs b/src/libcoretest/num/mod.rs index acc593d7be9..82e91c5b712 100644 --- a/src/libcoretest/num/mod.rs +++ b/src/libcoretest/num/mod.rs @@ -13,6 +13,7 @@ use core::fmt::Show; use core::num::{NumCast, cast}; use core::ops::{Add, Sub, Mul, Div, Rem}; use core::kinds::Copy; +use std::str::from_str; mod int_macros; mod i8; @@ -54,6 +55,7 @@ mod test { use core::option::Option::{Some, None}; use core::num::Float; use core::num::from_str_radix; + use core::str::from_str; #[test] fn from_str_issue7588() { diff --git a/src/libcoretest/num/uint_macros.rs b/src/libcoretest/num/uint_macros.rs index b21ac11e6a0..2311c19d557 100644 --- a/src/libcoretest/num/uint_macros.rs +++ b/src/libcoretest/num/uint_macros.rs @@ -16,6 +16,7 @@ mod tests { use core::$T_i::*; use core::num::Int; use num; + use core::ops::{BitOr, BitAnd, BitXor, Shl, Shr, Not}; #[test] fn test_overflows() { diff --git a/src/libcoretest/str.rs b/src/libcoretest/str.rs index 63d6e14a4a6..fc02f46724f 100644 --- a/src/libcoretest/str.rs +++ b/src/libcoretest/str.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::str::from_str; + #[test] fn test_bool_from_str() { assert_eq!(from_str::<bool>("true"), Some(true)); diff --git a/src/libcoretest/tuple.rs b/src/libcoretest/tuple.rs index f7b714757f8..c3bc38a6614 100644 --- a/src/libcoretest/tuple.rs +++ b/src/libcoretest/tuple.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::cmp::Ordering::{Equal, Less, Greater}; + #[test] fn test_clone() { let a = (1i, "2"); diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index 7dd0649e483..01e55fb2edd 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -47,6 +47,7 @@ //! which is cyclic. //! //! ```rust +//! use std::borrow::IntoCow; //! use graphviz as dot; //! //! type Nd = int; @@ -146,6 +147,7 @@ //! entity `&sube`). //! //! ```rust +//! use std::borrow::IntoCow; //! use graphviz as dot; //! //! type Nd = uint; @@ -201,6 +203,7 @@ //! Hasse-diagram for the subsets of the set `{x, y}`. //! //! ```rust +//! use std::borrow::IntoCow; //! use graphviz as dot; //! //! type Nd<'a> = (uint, &'a str); @@ -273,6 +276,7 @@ pub use self::LabelText::*; +use std::borrow::IntoCow; use std::io; use std::str::CowString; use std::vec::CowVec; @@ -586,6 +590,7 @@ mod tests { use super::{Nodes, Edges, GraphWalk, render}; use std::io::IoResult; use std::str; + use std::borrow::IntoCow; /// each node is an index in a vector in the graph. type Node = uint; diff --git a/src/libgraphviz/maybe_owned_vec.rs b/src/libgraphviz/maybe_owned_vec.rs index ddda2b38c22..d0396ddc7ad 100644 --- a/src/libgraphviz/maybe_owned_vec.rs +++ b/src/libgraphviz/maybe_owned_vec.rs @@ -12,8 +12,10 @@ pub use self::MaybeOwnedVector::*; +use std::cmp::{Equiv, Ordering}; use std::default::Default; use std::fmt; +use std::iter::FromIterator; use std::path::BytesContainer; use std::slice; @@ -96,9 +98,9 @@ impl<'a, T: Ord> Ord for MaybeOwnedVector<'a, T> { } #[allow(deprecated)] -impl<'a, T: PartialEq, Sized? V: AsSlice<T>> Equiv<V> for MaybeOwnedVector<'a, T> { - fn equiv(&self, other: &V) -> bool { - self.as_slice() == other.as_slice() +impl<'a, T: PartialEq> Equiv<[T]> for MaybeOwnedVector<'a, T> { + fn equiv(&self, other: &[T]) -> bool { + self.as_slice() == other } } @@ -125,7 +127,7 @@ impl<'a,T> FromIterator<T> for MaybeOwnedVector<'a,T> { fn from_iter<I:Iterator<T>>(iterator: I) -> MaybeOwnedVector<'a,T> { // If we are building from scratch, might as well build the // most flexible variant. - Growable(FromIterator::from_iter(iterator)) + Growable(iterator.collect()) } } diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs index b30938ae7f5..4ee5b2d5e83 100644 --- a/src/liblog/lib.rs +++ b/src/liblog/lib.rs @@ -352,7 +352,7 @@ pub struct LogLocation { #[doc(hidden)] pub fn mod_enabled(level: u32, module: &str) -> bool { static INIT: Once = ONCE_INIT; - INIT.doit(init); + INIT.call_once(init); // It's possible for many threads are in this function, only one of them // will perform the global initialization, but all of them will need to check diff --git a/src/librand/chacha.rs b/src/librand/chacha.rs index 49577cd279b..8e6c7de305f 100644 --- a/src/librand/chacha.rs +++ b/src/librand/chacha.rs @@ -206,7 +206,7 @@ impl Rand for ChaChaRng { #[cfg(test)] mod test { - use std::prelude::*; + use std::prelude::v1::*; use core::iter::order; use {Rng, SeedableRng}; diff --git a/src/librand/distributions/exponential.rs b/src/librand/distributions/exponential.rs index f31f3468a4c..981b0eeee53 100644 --- a/src/librand/distributions/exponential.rs +++ b/src/librand/distributions/exponential.rs @@ -94,7 +94,7 @@ impl IndependentSample<f64> for Exp { #[cfg(test)] mod test { - use std::prelude::*; + use std::prelude::v1::*; use distributions::{Sample, IndependentSample}; use super::Exp; @@ -124,7 +124,7 @@ mod test { mod bench { extern crate test; - use std::prelude::*; + use std::prelude::v1::*; use self::test::Bencher; use std::mem::size_of; diff --git a/src/librand/distributions/gamma.rs b/src/librand/distributions/gamma.rs index 618db380db8..378029d1f9b 100644 --- a/src/librand/distributions/gamma.rs +++ b/src/librand/distributions/gamma.rs @@ -323,7 +323,7 @@ impl IndependentSample<f64> for StudentT { #[cfg(test)] mod test { - use std::prelude::*; + use std::prelude::v1::*; use distributions::{Sample, IndependentSample}; use super::{ChiSquared, StudentT, FisherF}; @@ -385,7 +385,7 @@ mod test { #[cfg(test)] mod bench { extern crate test; - use std::prelude::*; + use std::prelude::v1::*; use self::test::Bencher; use std::mem::size_of; use distributions::IndependentSample; diff --git a/src/librand/distributions/mod.rs b/src/librand/distributions/mod.rs index 54cb8ae1907..d0123d9c76c 100644 --- a/src/librand/distributions/mod.rs +++ b/src/librand/distributions/mod.rs @@ -258,7 +258,7 @@ fn ziggurat<R: Rng, P, Z>( #[cfg(test)] mod tests { - use std::prelude::*; + use std::prelude::v1::*; use {Rng, Rand}; use super::{RandSample, WeightedChoice, Weighted, Sample, IndependentSample}; diff --git a/src/librand/distributions/normal.rs b/src/librand/distributions/normal.rs index 3507282ec48..543e236f96d 100644 --- a/src/librand/distributions/normal.rs +++ b/src/librand/distributions/normal.rs @@ -160,7 +160,7 @@ impl IndependentSample<f64> for LogNormal { #[cfg(test)] mod tests { - use std::prelude::*; + use std::prelude::v1::*; use distributions::{Sample, IndependentSample}; use super::{Normal, LogNormal}; @@ -200,7 +200,7 @@ mod tests { #[cfg(test)] mod bench { extern crate test; - use std::prelude::*; + use std::prelude::v1::*; use self::test::Bencher; use std::mem::size_of; use distributions::{Sample}; diff --git a/src/librand/distributions/range.rs b/src/librand/distributions/range.rs index 20ba3566d5b..558fa201256 100644 --- a/src/librand/distributions/range.rs +++ b/src/librand/distributions/range.rs @@ -164,7 +164,7 @@ float_impl! { f64 } #[cfg(test)] mod tests { use std::num::Int; - use std::prelude::*; + use std::prelude::v1::*; use distributions::{Sample, IndependentSample}; use super::Range; diff --git a/src/librand/isaac.rs b/src/librand/isaac.rs index 1fe435a59ad..1ea47844075 100644 --- a/src/librand/isaac.rs +++ b/src/librand/isaac.rs @@ -487,7 +487,7 @@ impl Rand for Isaac64Rng { #[cfg(test)] mod test { - use std::prelude::*; + use std::prelude::v1::*; use core::iter::order; use {Rng, SeedableRng}; diff --git a/src/librand/lib.rs b/src/librand/lib.rs index 568d2459118..bbcd99afdea 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -52,14 +52,14 @@ pub mod reseeding; mod rand_impls; /// A type that can be randomly generated using an `Rng`. -pub trait Rand { +pub trait Rand : Sized { /// Generates a random instance of this type using the specified source of /// randomness. fn rand<R: Rng>(rng: &mut R) -> Self; } /// A random number generator. -pub trait Rng { +pub trait Rng : Sized { /// Return the next random u32. /// /// This rarely needs to be called directly, prefer `r.gen()` to diff --git a/src/librand/rand_impls.rs b/src/librand/rand_impls.rs index e50153076c3..c331807c1b9 100644 --- a/src/librand/rand_impls.rs +++ b/src/librand/rand_impls.rs @@ -214,7 +214,7 @@ impl<T:Rand> Rand for Option<T> { #[cfg(test)] mod tests { - use std::prelude::*; + use std::prelude::v1::*; use std::rand::{Rng, thread_rng, Open01, Closed01}; struct ConstantRng(u64); diff --git a/src/librand/reseeding.rs b/src/librand/reseeding.rs index 94a11c040e4..46371d427e6 100644 --- a/src/librand/reseeding.rs +++ b/src/librand/reseeding.rs @@ -149,7 +149,7 @@ impl Default for ReseedWithDefault { #[cfg(test)] mod test { - use std::prelude::*; + use std::prelude::v1::*; use core::iter::order; use super::{ReseedingRng, ReseedWithDefault}; diff --git a/src/libregex/re.rs b/src/libregex/re.rs index 51c23463155..3171966a596 100644 --- a/src/libregex/re.rs +++ b/src/libregex/re.rs @@ -11,6 +11,7 @@ pub use self::NamesIter::*; pub use self::Regex::*; +use std::borrow::IntoCow; use std::collections::HashMap; use std::fmt; use std::str::CowString; diff --git a/src/libregex/vm.rs b/src/libregex/vm.rs index 72e0e559c80..603ca57d15d 100644 --- a/src/libregex/vm.rs +++ b/src/libregex/vm.rs @@ -37,6 +37,7 @@ pub use self::MatchKind::*; pub use self::StepState::*; use std::cmp; +use std::cmp::Ordering::{mod, Less, Equal, Greater}; use std::mem; use std::iter::repeat; use std::slice::SliceExt; diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 4647c92e3d1..cdc27244dde 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -22,10 +22,12 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/nightly/")] +#![allow(unknown_features)] #![feature(default_type_params, globs, macro_rules, phase, quote)] #![feature(slicing_syntax, unsafe_destructor)] #![feature(rustc_diagnostic_macros)] #![feature(unboxed_closures)] +#![feature(old_orphan_check)] extern crate arena; extern crate flate; @@ -98,6 +100,7 @@ pub mod middle { pub mod traits; pub mod ty; pub mod ty_fold; + pub mod ty_walk; pub mod weak_lang_items; } diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 82aa40cb0ad..c314fba91d5 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -36,10 +36,11 @@ use util::ppaux::{ty_to_string}; use util::nodemap::{FnvHashMap, NodeSet}; use lint::{Context, LintPass, LintArray}; -use std::{cmp, slice}; use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::num::SignedInt; +use std::{cmp, slice}; use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64}; + use syntax::{abi, ast, ast_map}; use syntax::ast_util::is_shift_binop; use syntax::attr::{mod, AttrMetaMethods}; diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index d079d0e52aa..a25b6d8b8fa 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -32,13 +32,15 @@ use middle::ty::{ImplContainer, TraitContainer}; use middle::ty::{mod, Ty}; use middle::astencode::vtable_decoder_helpers; +use std::collections::HashMap; use std::hash::Hash; use std::hash; use std::io::extensions::u64_from_be_bytes; use std::io; -use std::collections::hash_map::HashMap; +use std::num::FromPrimitive; use std::rc::Rc; use std::str; + use rbml::reader; use rbml; use serialize::Decodable; @@ -441,9 +443,15 @@ pub fn get_impl_trait<'tcx>(cdata: Cmd, -> Option<Rc<ty::TraitRef<'tcx>>> { let item_doc = lookup_item(id, cdata.data()); - reader::maybe_get_doc(item_doc, tag_item_trait_ref).map(|tp| { - doc_trait_ref(tp, tcx, cdata) - }) + let fam = item_family(item_doc); + match fam { + Family::Impl => { + reader::maybe_get_doc(item_doc, tag_item_trait_ref).map(|tp| { + doc_trait_ref(tp, tcx, cdata) + }) + } + _ => None + } } pub fn get_impl_vtables<'tcx>(cdata: Cmd, @@ -1273,9 +1281,9 @@ pub fn each_impl<F>(cdata: Cmd, mut callback: F) where } pub fn each_implementation_for_type<F>(cdata: Cmd, - id: ast::NodeId, - mut callback: F) where - F: FnMut(ast::DefId), + id: ast::NodeId, + mut callback: F) + where F: FnMut(ast::DefId), { let item_doc = lookup_item(id, cdata.data()); reader::tagged_docs(item_doc, diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 8378c620c1d..10383b901f3 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1222,8 +1222,7 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_attributes(rbml_w, item.attrs[]); encode_unsafety(rbml_w, unsafety); match ty.node { - ast::TyPath(ref path, _) if path.segments - .len() == 1 => { + ast::TyPath(ref path, _) if path.segments.len() == 1 => { let ident = path.segments.last().unwrap().identifier; encode_impl_type_basename(rbml_w, ident); } @@ -1351,6 +1350,9 @@ fn encode_info_for_item(ecx: &EncodeContext, // Encode the implementations of this trait. encode_extension_implementations(ecx, rbml_w, def_id); + // Encode inherent implementations for this trait. + encode_inherent_implementations(ecx, rbml_w, def_id); + rbml_w.end_tag(); // Now output the trait item info for each trait item. @@ -1453,9 +1455,6 @@ fn encode_info_for_item(ecx: &EncodeContext, rbml_w.end_tag(); } - - // Encode inherent implementations for this trait. - encode_inherent_implementations(ecx, rbml_w, def_id); } ast::ItemMac(..) => { // macros are encoded separately diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 88c7ccf1b1e..2d3ff95ffa6 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -25,7 +25,6 @@ use middle::ty::{mod, AsPredicate, Ty}; use std::rc::Rc; use std::str; -use std::string::String; use syntax::abi; use syntax::ast; use syntax::parse::token; diff --git a/src/librustc/middle/cfg/graphviz.rs b/src/librustc/middle/cfg/graphviz.rs index 13bd22a67c4..06fef66c1e0 100644 --- a/src/librustc/middle/cfg/graphviz.rs +++ b/src/librustc/middle/cfg/graphviz.rs @@ -11,7 +11,9 @@ /// This module provides linkage between rustc::middle::graph and /// libgraphviz traits. -/// For clarity, rename the graphviz crate locally to dot. +use std::borrow::IntoCow; + +// For clarity, rename the graphviz crate locally to dot. use graphviz as dot; use syntax::ast; diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 4c5d76a2c40..d16224ec5b8 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -24,8 +24,7 @@ use middle::pat_util::*; use middle::ty::*; use middle::ty; use std::fmt; -use std::iter::AdditiveIterator; -use std::iter::{range_inclusive, repeat}; +use std::iter::{range_inclusive, AdditiveIterator, FromIterator, repeat}; use std::num::Float; use std::slice; use syntax::ast::{mod, DUMMY_NODE_ID, NodeId, Pat}; diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 5b89912dd03..9fc5cb03353 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -27,8 +27,8 @@ use syntax::ptr::P; use syntax::visit::{mod, Visitor}; use syntax::{ast_map, ast_util, codemap}; -use std::rc::Rc; use std::collections::hash_map::Entry::Vacant; +use std::rc::Rc; // // This pass classifies expressions by their constant-ness. diff --git a/src/librustc/middle/infer/combine.rs b/src/librustc/middle/infer/combine.rs index e0bcdfc6d8d..ab6f6b601f6 100644 --- a/src/librustc/middle/infer/combine.rs +++ b/src/librustc/middle/infer/combine.rs @@ -57,7 +57,7 @@ use syntax::ast; use syntax::abi; use syntax::codemap::Span; -pub trait Combine<'tcx> { +pub trait Combine<'tcx> : Sized { fn infcx<'a>(&'a self) -> &'a InferCtxt<'a, 'tcx>; fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.infcx().tcx } fn tag(&self) -> String; diff --git a/src/librustc/middle/infer/region_inference/graphviz.rs b/src/librustc/middle/infer/region_inference/graphviz.rs index 8455ee3955b..b6020fe5ce3 100644 --- a/src/librustc/middle/infer/region_inference/graphviz.rs +++ b/src/librustc/middle/infer/region_inference/graphviz.rs @@ -73,7 +73,7 @@ pub fn maybe_print_constraints_for<'a, 'tcx>(region_vars: &RegionVarBindings<'a, let output_path = { let output_template = match requested_output { Some(ref s) if s.as_slice() == "help" => { - static PRINTED_YET : atomic::AtomicBool = atomic::INIT_ATOMIC_BOOL; + static PRINTED_YET : atomic::AtomicBool = atomic::ATOMIC_BOOL_INIT; if !PRINTED_YET.load(atomic::SeqCst) { print_help_message(); PRINTED_YET.store(true, atomic::SeqCst); diff --git a/src/librustc/middle/infer/region_inference/mod.rs b/src/librustc/middle/infer/region_inference/mod.rs index 7372bb267b0..6ac1c5470cc 100644 --- a/src/librustc/middle/infer/region_inference/mod.rs +++ b/src/librustc/middle/infer/region_inference/mod.rs @@ -33,8 +33,9 @@ use util::nodemap::{FnvHashMap, FnvHashSet}; use util::ppaux::Repr; use std::cell::{Cell, RefCell}; -use std::u32; +use std::cmp::Ordering::{mod, Less, Greater, Equal}; use std::iter::repeat; +use std::u32; use syntax::ast; mod doc; diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 2aef4307199..78fabcd588a 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -36,6 +36,7 @@ use syntax::visit::Visitor; use syntax::visit; use std::iter::Enumerate; +use std::num::FromPrimitive; use std::slice; // The actual lang items defined come at the end of this file in one handy table. diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index be89b32cdaa..0e47f338bb9 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -649,7 +649,10 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &ast::Local) { Some(ref expr) => { record_rvalue_scope_if_borrow_expr(visitor, &**expr, blk_scope); - if is_binding_pat(&*local.pat) || is_borrowed_ty(&*local.ty) { + let is_borrow = + if let Some(ref ty) = local.ty { is_borrowed_ty(&**ty) } else { false }; + + if is_binding_pat(&*local.pat) || is_borrow { record_rvalue_scope(visitor, &**expr, blk_scope); } } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index d793f49efe5..505352fa123 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -11,7 +11,8 @@ //! A pass that annotates every item and method with its stability level, //! propagating default levels lexically from parent to children ast nodes. -use util::nodemap::{NodeMap, DefIdMap}; +use middle::ty; +use metadata::csearch; use syntax::codemap::Span; use syntax::{attr, visit}; use syntax::ast; @@ -21,8 +22,8 @@ use syntax::ast::{TypeMethod, Method, Generics, StructField, TypeTraitItem}; use syntax::ast_util::is_local; use syntax::attr::Stability; use syntax::visit::{FnKind, FkMethod, Visitor}; -use middle::ty; -use metadata::csearch; +use util::nodemap::{NodeMap, DefIdMap}; +use util::ppaux::Repr; use std::mem::replace; @@ -154,10 +155,13 @@ impl Index { /// Lookup the stability for a node, loading external crate /// metadata as necessary. pub fn lookup(tcx: &ty::ctxt, id: DefId) -> Option<Stability> { + debug!("lookup(id={})", + id.repr(tcx)); + // is this definition the implementation of a trait method? match ty::trait_item_of_item(tcx, id) { - Some(ty::MethodTraitItemId(trait_method_id)) - if trait_method_id != id => { + Some(ty::MethodTraitItemId(trait_method_id)) if trait_method_id != id => { + debug!("lookup: trait_method_id={}", trait_method_id); return lookup(tcx, trait_method_id) } _ => {} @@ -178,6 +182,7 @@ pub fn lookup(tcx: &ty::ctxt, id: DefId) -> Option<Stability> { // stability of the trait to determine the stability of any // unmarked impls for it. See FIXME above for more details. + debug!("lookup: trait_id={}", trait_id); lookup(tcx, trait_id) } else { None diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs index 3c5459ff3bc..97e74b9f6bb 100644 --- a/src/librustc/middle/subst.rs +++ b/src/librustc/middle/subst.rs @@ -519,7 +519,7 @@ impl<'a,T> Iterator<(ParamSpace, uint, &'a T)> for EnumeratedItems<'a,T> { // `foo`. Or use `foo.subst_spanned(tcx, substs, Some(span))` when // there is more information available (for better errors). -pub trait Subst<'tcx> { +pub trait Subst<'tcx> : Sized { fn subst(&self, tcx: &ty::ctxt<'tcx>, substs: &Substs<'tcx>) -> Self { self.subst_spanned(tcx, substs, None) } diff --git a/src/librustc/middle/traits/coherence.rs b/src/librustc/middle/traits/coherence.rs index d8b39d92c69..4aff36c2624 100644 --- a/src/librustc/middle/traits/coherence.rs +++ b/src/librustc/middle/traits/coherence.rs @@ -14,10 +14,10 @@ use super::SelectionContext; use super::{Obligation, ObligationCause}; use super::util; -use middle::subst; use middle::subst::Subst; use middle::ty::{mod, Ty}; use middle::infer::InferCtxt; +use std::collections::HashSet; use std::rc::Rc; use syntax::ast; use syntax::codemap::DUMMY_SP; @@ -52,9 +52,21 @@ pub fn impl_can_satisfy(infcx: &InferCtxt, selcx.evaluate_impl(impl2_def_id, &obligation) } -pub fn impl_is_local(tcx: &ty::ctxt, - impl_def_id: ast::DefId) - -> bool +#[allow(missing_copy_implementations)] +pub enum OrphanCheckErr { + NoLocalInputType, + UncoveredTypeParameter(ty::ParamTy), +} + +/// Checks the coherence orphan rules. `impl_def_id` should be the +/// def-id of a trait impl. To pass, either the trait must be local, or else +/// two conditions must be satisfied: +/// +/// 1. At least one of the input types must involve a local type. +/// 2. All type parameters must be covered by a local type. +pub fn orphan_check(tcx: &ty::ctxt, + impl_def_id: ast::DefId) + -> Result<(), OrphanCheckErr> { debug!("impl_is_local({})", impl_def_id.repr(tcx)); @@ -63,20 +75,40 @@ pub fn impl_is_local(tcx: &ty::ctxt, let trait_ref = ty::impl_trait_ref(tcx, impl_def_id).unwrap(); debug!("trait_ref={}", trait_ref.repr(tcx)); - // If the trait is local to the crate, ok. + // If the *trait* is local to the crate, ok. if trait_ref.def_id.krate == ast::LOCAL_CRATE { debug!("trait {} is local to current crate", trait_ref.def_id.repr(tcx)); - return true; + return Ok(()); } - // Otherwise, at least one of the input types must be local to the - // crate. - trait_ref.input_types().iter().any(|&t| ty_is_local(tcx, t)) + // Check condition 1: at least one type must be local. + if !trait_ref.input_types().iter().any(|&t| ty_reaches_local(tcx, t)) { + return Err(OrphanCheckErr::NoLocalInputType); + } + + // Check condition 2: type parameters must be "covered" by a local type. + let covered_params: HashSet<_> = + trait_ref.input_types().iter() + .flat_map(|&t| type_parameters_covered_by_ty(tcx, t).into_iter()) + .collect(); + let all_params: HashSet<_> = + trait_ref.input_types().iter() + .flat_map(|&t| type_parameters_reachable_from_ty(t).into_iter()) + .collect(); + for ¶m in all_params.difference(&covered_params) { + return Err(OrphanCheckErr::UncoveredTypeParameter(param)); + } + + return Ok(()); +} + +fn ty_reaches_local<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { + ty.walk().any(|t| ty_is_local_constructor(tcx, t)) } -pub fn ty_is_local<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { - debug!("ty_is_local({})", ty.repr(tcx)); +fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { + debug!("ty_is_local_constructor({})", ty.repr(tcx)); match ty.sty { ty::ty_bool | @@ -84,78 +116,33 @@ pub fn ty_is_local<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { ty::ty_int(..) | ty::ty_uint(..) | ty::ty_float(..) | - ty::ty_str(..) => { - false - } - - ty::ty_unboxed_closure(..) => { - // This routine is invoked on types specified by users as - // part of an impl and hence an unboxed closure type - // cannot appear. - tcx.sess.bug("ty_is_local applied to unboxed closure type") - } - + ty::ty_str(..) | ty::ty_bare_fn(..) | - ty::ty_closure(..) => { + ty::ty_closure(..) | + ty::ty_vec(..) | + ty::ty_ptr(..) | + ty::ty_rptr(..) | + ty::ty_tup(..) | + ty::ty_param(..) | + ty::ty_projection(..) => { false } - ty::ty_uniq(t) => { - let krate = tcx.lang_items.owned_box().map(|d| d.krate); - krate == Some(ast::LOCAL_CRATE) || ty_is_local(tcx, t) - } - - ty::ty_vec(t, _) | - ty::ty_ptr(ty::mt { ty: t, .. }) | - ty::ty_rptr(_, ty::mt { ty: t, .. }) => { - ty_is_local(tcx, t) - } - - ty::ty_tup(ref ts) => { - ts.iter().any(|&t| ty_is_local(tcx, t)) + ty::ty_enum(def_id, _) | + ty::ty_struct(def_id, _) => { + def_id.krate == ast::LOCAL_CRATE } - ty::ty_enum(def_id, ref substs) | - ty::ty_struct(def_id, ref substs) => { - def_id.krate == ast::LOCAL_CRATE || { - let variances = ty::item_variances(tcx, def_id); - subst::ParamSpace::all().iter().any(|&space| { - substs.types.get_slice(space).iter().enumerate().any( - |(i, &t)| { - match *variances.types.get(space, i) { - ty::Bivariant => { - // If Foo<T> is bivariant with respect to - // T, then it doesn't matter whether T is - // local or not, because `Foo<U>` for any - // U will be a subtype of T. - false - } - ty::Contravariant | - ty::Covariant | - ty::Invariant => { - ty_is_local(tcx, t) - } - } - }) - }) - } + ty::ty_uniq(_) => { // treat ~T like Box<T> + let krate = tcx.lang_items.owned_box().map(|d| d.krate); + krate == Some(ast::LOCAL_CRATE) } ty::ty_trait(ref tt) => { tt.principal_def_id().krate == ast::LOCAL_CRATE } - // Type parameters may be bound to types that are not local to - // the crate. - ty::ty_param(..) => { - false - } - - // Associated types could be anything, I guess. - ty::ty_projection(..) => { - false - } - + ty::ty_unboxed_closure(..) | ty::ty_infer(..) | ty::ty_open(..) | ty::ty_err => { @@ -165,3 +152,27 @@ pub fn ty_is_local<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { } } } + +fn type_parameters_covered_by_ty<'tcx>(tcx: &ty::ctxt<'tcx>, + ty: Ty<'tcx>) + -> HashSet<ty::ParamTy> +{ + if ty_is_local_constructor(tcx, ty) { + type_parameters_reachable_from_ty(ty) + } else { + ty.walk_children().flat_map(|t| type_parameters_covered_by_ty(tcx, t).into_iter()).collect() + } +} + +/// All type parameters reachable from `ty` +fn type_parameters_reachable_from_ty<'tcx>(ty: Ty<'tcx>) -> HashSet<ty::ParamTy> { + ty.walk() + .filter_map(|t| { + match t.sty { + ty::ty_param(ref param_ty) => Some(param_ty.clone()), + _ => None, + } + }) + .collect() +} + diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index b10dfa5b718..c83898bcd8a 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -25,24 +25,33 @@ use syntax::codemap::{Span, DUMMY_SP}; use util::ppaux::Repr; pub use self::error_reporting::report_fulfillment_errors; +pub use self::coherence::orphan_check; +pub use self::coherence::OrphanCheckErr; pub use self::fulfill::{FulfillmentContext, RegionObligation}; pub use self::project::MismatchedProjectionTypes; pub use self::project::normalize; pub use self::project::Normalized; +pub use self::object_safety::is_object_safe; +pub use self::object_safety::object_safety_violations; +pub use self::object_safety::ObjectSafetyViolation; +pub use self::object_safety::MethodViolationCode; pub use self::select::SelectionContext; pub use self::select::SelectionCache; pub use self::select::{MethodMatchResult, MethodMatched, MethodAmbiguous, MethodDidNotMatch}; pub use self::select::{MethodMatchedData}; // intentionally don't export variants pub use self::util::elaborate_predicates; +pub use self::util::get_vtable_index_of_object_method; pub use self::util::trait_ref_for_builtin_bound; pub use self::util::supertraits; pub use self::util::Supertraits; pub use self::util::transitive_bounds; +pub use self::util::upcast; mod coherence; mod error_reporting; mod fulfill; mod project; +mod object_safety; mod select; mod util; @@ -210,6 +219,9 @@ pub enum Vtable<'tcx, N> { /// for some type parameter. VtableParam, + /// Virtual calls through an object + VtableObject(VtableObjectData<'tcx>), + /// Successful resolution for a builtin trait. VtableBuiltin(VtableBuiltinData<N>), @@ -245,13 +257,11 @@ pub struct VtableBuiltinData<N> { pub nested: subst::VecPerParamSpace<N> } -/// True if neither the trait nor self type is local. Note that `impl_def_id` must refer to an impl -/// of a trait, not an inherent impl. -pub fn is_orphan_impl(tcx: &ty::ctxt, - impl_def_id: ast::DefId) - -> bool -{ - !coherence::impl_is_local(tcx, impl_def_id) +/// A vtable for some object-safe trait `Foo` automatically derived +/// for the object type `Foo`. +#[deriving(PartialEq,Eq,Clone)] +pub struct VtableObjectData<'tcx> { + pub object_ty: Ty<'tcx>, } /// True if there exist types that satisfy both of the two given impls. @@ -365,6 +375,7 @@ impl<'tcx, N> Vtable<'tcx, N> { VtableFnPointer(..) => (&[]).iter(), VtableUnboxedClosure(..) => (&[]).iter(), VtableParam => (&[]).iter(), + VtableObject(_) => (&[]).iter(), VtableBuiltin(ref i) => i.iter_nested(), } } @@ -375,6 +386,7 @@ impl<'tcx, N> Vtable<'tcx, N> { VtableFnPointer(ref sig) => VtableFnPointer((*sig).clone()), VtableUnboxedClosure(d, ref s) => VtableUnboxedClosure(d, s.clone()), VtableParam => VtableParam, + VtableObject(ref p) => VtableObject(p.clone()), VtableBuiltin(ref b) => VtableBuiltin(b.map_nested(op)), } } @@ -387,6 +399,7 @@ impl<'tcx, N> Vtable<'tcx, N> { VtableFnPointer(sig) => VtableFnPointer(sig), VtableUnboxedClosure(d, s) => VtableUnboxedClosure(d, s), VtableParam => VtableParam, + VtableObject(p) => VtableObject(p), VtableBuiltin(no) => VtableBuiltin(no.map_move_nested(op)), } } diff --git a/src/librustc/middle/traits/object_safety.rs b/src/librustc/middle/traits/object_safety.rs new file mode 100644 index 00000000000..6b7bf82af92 --- /dev/null +++ b/src/librustc/middle/traits/object_safety.rs @@ -0,0 +1,301 @@ +// Copyright 2014 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. + +//! "Object safety" refers to the ability for a trait to be converted +//! to an object. In general, traits may only be converted to an +//! object if all of their methods meet certain criteria. In particular, +//! they must: +//! +//! - have a suitable receiver from which we can extract a vtable; +//! - not reference the erased type `Self` except for in this receiver; +//! - not have generic type parameters + +use super::supertraits; +use super::elaborate_predicates; + +use middle::subst::{mod, SelfSpace}; +use middle::traits; +use middle::ty::{mod, Ty}; +use std::rc::Rc; +use syntax::ast; +use util::ppaux::Repr; + +pub enum ObjectSafetyViolation<'tcx> { + /// Self : Sized declared on the trait + SizedSelf, + + /// Method has someting illegal + Method(Rc<ty::Method<'tcx>>, MethodViolationCode), +} + +/// Reasons a method might not be object-safe. +#[deriving(Copy,Clone,Show)] +pub enum MethodViolationCode { + /// e.g., `fn(self)` + ByValueSelf, + + /// e.g., `fn foo()` + StaticMethod, + + /// e.g., `fn foo(&self, x: Self)` or `fn foo(&self) -> Self` + ReferencesSelf, + + /// e.g., `fn foo<A>()` + Generic, +} + +pub fn is_object_safe<'tcx>(tcx: &ty::ctxt<'tcx>, + trait_ref: ty::PolyTraitRef<'tcx>) + -> bool +{ + // Because we query yes/no results frequently, we keep a cache: + let cached_result = + tcx.object_safety_cache.borrow().get(&trait_ref.def_id()).map(|&r| r); + + let result = + cached_result.unwrap_or_else(|| { + let result = object_safety_violations(tcx, trait_ref.clone()).is_empty(); + + // Record just a yes/no result in the cache; this is what is + // queried most frequently. Note that this may overwrite a + // previous result, but always with the same thing. + tcx.object_safety_cache.borrow_mut().insert(trait_ref.def_id(), result); + + result + }); + + debug!("is_object_safe({}) = {}", trait_ref.repr(tcx), result); + + result +} + +pub fn object_safety_violations<'tcx>(tcx: &ty::ctxt<'tcx>, + sub_trait_ref: ty::PolyTraitRef<'tcx>) + -> Vec<ObjectSafetyViolation<'tcx>> +{ + supertraits(tcx, sub_trait_ref) + .flat_map(|tr| object_safety_violations_for_trait(tcx, tr.def_id()).into_iter()) + .collect() +} + +fn object_safety_violations_for_trait<'tcx>(tcx: &ty::ctxt<'tcx>, + trait_def_id: ast::DefId) + -> Vec<ObjectSafetyViolation<'tcx>> +{ + // Check methods for violations. + let mut violations: Vec<_> = + ty::trait_items(tcx, trait_def_id).iter() + .flat_map(|item| { + match *item { + ty::MethodTraitItem(ref m) => { + object_safety_violations_for_method(tcx, trait_def_id, &**m) + .map(|code| ObjectSafetyViolation::Method(m.clone(), code)) + .into_iter() + } + ty::TypeTraitItem(_) => { + None.into_iter() + } + } + }) + .collect(); + + // Check the trait itself. + if trait_has_sized_self(tcx, trait_def_id) { + violations.push(ObjectSafetyViolation::SizedSelf); + } + + debug!("object_safety_violations_for_trait(trait_def_id={}) = {}", + trait_def_id.repr(tcx), + violations.repr(tcx)); + + violations +} + +fn trait_has_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>, + trait_def_id: ast::DefId) + -> bool +{ + let trait_def = ty::lookup_trait_def(tcx, trait_def_id); + let param_env = ty::construct_parameter_environment(tcx, + &trait_def.generics, + ast::DUMMY_NODE_ID); + let predicates = param_env.caller_bounds.predicates.as_slice().to_vec(); + let sized_def_id = match tcx.lang_items.sized_trait() { + Some(def_id) => def_id, + None => { return false; /* No Sized trait, can't require it! */ } + }; + + // Search for a predicate like `Self : Sized` amongst the trait bounds. + elaborate_predicates(tcx, predicates) + .any(|predicate| { + match predicate { + ty::Predicate::Trait(ref trait_pred) if trait_pred.def_id() == sized_def_id => { + let self_ty = trait_pred.0.self_ty(); + match self_ty.sty { + ty::ty_param(ref data) => data.space == subst::SelfSpace, + _ => false, + } + } + ty::Predicate::Projection(..) | + ty::Predicate::Trait(..) | + ty::Predicate::Equate(..) | + ty::Predicate::RegionOutlives(..) | + ty::Predicate::TypeOutlives(..) => { + false + } + } + }) +} + +fn object_safety_violations_for_method<'tcx>(tcx: &ty::ctxt<'tcx>, + trait_def_id: ast::DefId, + method: &ty::Method<'tcx>) + -> Option<MethodViolationCode> +{ + // The method's first parameter must be something that derefs to + // `&self`. For now, we only accept `&self` and `Box<Self>`. + match method.explicit_self { + ty::ByValueExplicitSelfCategory => { + return Some(MethodViolationCode::ByValueSelf); + } + + ty::StaticExplicitSelfCategory => { + return Some(MethodViolationCode::StaticMethod); + } + + ty::ByReferenceExplicitSelfCategory(..) | + ty::ByBoxExplicitSelfCategory => { + } + } + + // The `Self` type is erased, so it should not appear in list of + // arguments or return type apart from the receiver. + let ref sig = method.fty.sig; + for &input_ty in sig.0.inputs[1..].iter() { + if contains_illegal_self_type_reference(tcx, trait_def_id, input_ty) { + return Some(MethodViolationCode::ReferencesSelf); + } + } + if let ty::FnConverging(result_type) = sig.0.output { + if contains_illegal_self_type_reference(tcx, trait_def_id, result_type) { + return Some(MethodViolationCode::ReferencesSelf); + } + } + + // We can't monomorphize things like `fn foo<A>(...)`. + if !method.generics.types.is_empty_in(subst::FnSpace) { + return Some(MethodViolationCode::Generic); + } + + None +} + +fn contains_illegal_self_type_reference<'tcx>(tcx: &ty::ctxt<'tcx>, + trait_def_id: ast::DefId, + ty: Ty<'tcx>) + -> bool +{ + // This is somewhat subtle. In general, we want to forbid + // references to `Self` in the argument and return types, + // since the value of `Self` is erased. However, there is one + // exception: it is ok to reference `Self` in order to access + // an associated type of the current trait, since we retain + // the value of those associated types in the object type + // itself. + // + // ```rust + // trait SuperTrait { + // type X; + // } + // + // trait Trait : SuperTrait { + // type Y; + // fn foo(&self, x: Self) // bad + // fn foo(&self) -> Self // bad + // fn foo(&self) -> Option<Self> // bad + // fn foo(&self) -> Self::Y // OK, desugars to next example + // fn foo(&self) -> <Self as Trait>::Y // OK + // fn foo(&self) -> Self::X // OK, desugars to next example + // fn foo(&self) -> <Self as SuperTrait>::X // OK + // } + // ``` + // + // However, it is not as simple as allowing `Self` in a projected + // type, because there are illegal ways to use `Self` as well: + // + // ```rust + // trait Trait : SuperTrait { + // ... + // fn foo(&self) -> <Self as SomeOtherTrait>::X; + // } + // ``` + // + // Here we will not have the type of `X` recorded in the + // object type, and we cannot resolve `Self as SomeOtherTrait` + // without knowing what `Self` is. + + let mut supertraits: Option<Vec<ty::PolyTraitRef<'tcx>>> = None; + let mut error = false; + ty::maybe_walk_ty(ty, |ty| { + match ty.sty { + ty::ty_param(ref param_ty) => { + if param_ty.space == SelfSpace { + error = true; + } + + false // no contained types to walk + } + + ty::ty_projection(ref data) => { + // This is a projected type `<Foo as SomeTrait>::X`. + + // Compute supertraits of current trait lazilly. + if supertraits.is_none() { + let trait_def = ty::lookup_trait_def(tcx, trait_def_id); + let trait_ref = ty::Binder(trait_def.trait_ref.clone()); + supertraits = Some(traits::supertraits(tcx, trait_ref).collect()); + } + + // Determine whether the trait reference `Foo as + // SomeTrait` is in fact a supertrait of the + // current trait. In that case, this type is + // legal, because the type `X` will be specified + // in the object type. Note that we can just use + // direct equality here because all of these types + // are part of the formal parameter listing, and + // hence there should be no inference variables. + let projection_trait_ref = ty::Binder(data.trait_ref.clone()); + let is_supertrait_of_current_trait = + supertraits.as_ref().unwrap().contains(&projection_trait_ref); + + if is_supertrait_of_current_trait { + false // do not walk contained types, do not report error, do collect $200 + } else { + true // DO walk contained types, POSSIBLY reporting an error + } + } + + _ => true, // walk contained types, if any + } + }); + + error +} + +impl<'tcx> Repr<'tcx> for ObjectSafetyViolation<'tcx> { + fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { + match *self { + ObjectSafetyViolation::SizedSelf => + format!("SizedSelf"), + ObjectSafetyViolation::Method(ref m, code) => + format!("Method({},{})", m.repr(tcx), code), + } + } +} diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs index c84f31bf6c3..d7f570df072 100644 --- a/src/librustc/middle/traits/project.rs +++ b/src/librustc/middle/traits/project.rs @@ -21,8 +21,10 @@ use super::VtableImplData; use middle::infer; use middle::subst::Subst; -use middle::ty::{mod, AsPredicate, RegionEscape, HasProjectionTypes, ToPolyTraitRef, Ty}; +use middle::ty::{mod, AsPredicate, ReferencesError, RegionEscape, + HasProjectionTypes, ToPolyTraitRef, Ty}; use middle::ty_fold::{mod, TypeFoldable, TypeFolder}; +use std::rc::Rc; use util::ppaux::Repr; pub type PolyProjectionObligation<'tcx> = @@ -372,25 +374,30 @@ fn project_type<'cx,'tcx>( return Err(ProjectionTyError::TraitSelectionError(Overflow)); } + let obligation_trait_ref = + selcx.infcx().resolve_type_vars_if_possible(&obligation.predicate.trait_ref); + + debug!("project: obligation_trait_ref={}", obligation_trait_ref.repr(selcx.tcx())); + + if obligation_trait_ref.references_error() { + return Ok(ProjectedTy::Progress(selcx.tcx().types.err, vec!())); + } + let mut candidates = ProjectionTyCandidateSet { vec: Vec::new(), ambiguous: false, }; - assemble_candidates_from_object_type(selcx, - obligation, - &mut candidates); + assemble_candidates_from_param_env(selcx, + obligation, + &obligation_trait_ref, + &mut candidates); - if candidates.vec.is_empty() { - assemble_candidates_from_param_env(selcx, - obligation, - &mut candidates); - - if let Err(e) = assemble_candidates_from_impls(selcx, - obligation, - &mut candidates) { - return Err(ProjectionTyError::TraitSelectionError(e)); - } + if let Err(e) = assemble_candidates_from_impls(selcx, + obligation, + &obligation_trait_ref, + &mut candidates) { + return Err(ProjectionTyError::TraitSelectionError(e)); } debug!("{} candidates, ambiguous={}", @@ -421,17 +428,20 @@ fn project_type<'cx,'tcx>( /// there that can answer this question. fn assemble_candidates_from_param_env<'cx,'tcx>( selcx: &mut SelectionContext<'cx,'tcx>, - obligation: &ProjectionTyObligation<'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + obligation_trait_ref: &Rc<ty::TraitRef<'tcx>>, candidate_set: &mut ProjectionTyCandidateSet<'tcx>) { let env_predicates = selcx.param_env().caller_bounds.predicates.clone(); let env_predicates = env_predicates.iter().cloned().collect(); - assemble_candidates_from_predicates(selcx, obligation, candidate_set, env_predicates); + assemble_candidates_from_predicates(selcx, obligation, obligation_trait_ref, + candidate_set, env_predicates); } fn assemble_candidates_from_predicates<'cx,'tcx>( selcx: &mut SelectionContext<'cx,'tcx>, - obligation: &ProjectionTyObligation<'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + obligation_trait_ref: &Rc<ty::TraitRef<'tcx>>, candidate_set: &mut ProjectionTyCandidateSet<'tcx>, env_predicates: Vec<ty::Predicate<'tcx>>) { @@ -445,7 +455,7 @@ fn assemble_candidates_from_predicates<'cx,'tcx>( let is_match = infcx.probe(|_| { let origin = infer::Misc(obligation.cause.span); let obligation_poly_trait_ref = - obligation.predicate.trait_ref.to_poly_trait_ref(); + obligation_trait_ref.to_poly_trait_ref(); let data_poly_trait_ref = data.to_poly_trait_ref(); infcx.sub_poly_trait_refs(false, @@ -467,36 +477,41 @@ fn assemble_candidates_from_predicates<'cx,'tcx>( fn assemble_candidates_from_object_type<'cx,'tcx>( selcx: &mut SelectionContext<'cx,'tcx>, obligation: &ProjectionTyObligation<'tcx>, - candidate_set: &mut ProjectionTyCandidateSet<'tcx>) + obligation_trait_ref: &Rc<ty::TraitRef<'tcx>>, + candidate_set: &mut ProjectionTyCandidateSet<'tcx>, + object_ty: Ty<'tcx>) { let infcx = selcx.infcx(); - let trait_ref = infcx.resolve_type_vars_if_possible(&obligation.predicate.trait_ref); - debug!("assemble_candidates_from_object_type(trait_ref={})", - trait_ref.repr(infcx.tcx)); - let self_ty = trait_ref.self_ty(); - let data = match self_ty.sty { + debug!("assemble_candidates_from_object_type(object_ty={})", + object_ty.repr(infcx.tcx)); + let data = match object_ty.sty { ty::ty_trait(ref data) => data, - _ => { return; } + _ => { + selcx.tcx().sess.span_bug( + obligation.cause.span, + format!("assemble_candidates_from_object_type called with non-object: {}", + object_ty.repr(selcx.tcx()))[]); + } }; - let projection_bounds = data.projection_bounds_with_self_ty(selcx.tcx(), self_ty); + let projection_bounds = data.projection_bounds_with_self_ty(selcx.tcx(), object_ty); let env_predicates = projection_bounds.iter() .map(|p| p.as_predicate()) .collect(); - assemble_candidates_from_predicates(selcx, obligation, candidate_set, env_predicates) + assemble_candidates_from_predicates(selcx, obligation, obligation_trait_ref, + candidate_set, env_predicates) } fn assemble_candidates_from_impls<'cx,'tcx>( selcx: &mut SelectionContext<'cx,'tcx>, obligation: &ProjectionTyObligation<'tcx>, + obligation_trait_ref: &Rc<ty::TraitRef<'tcx>>, candidate_set: &mut ProjectionTyCandidateSet<'tcx>) -> Result<(), SelectionError<'tcx>> { // If we are resolving `<T as TraitRef<...>>::Item == Type`, // start out by selecting the predicate `T as TraitRef<...>`: - let trait_ref = - obligation.predicate.trait_ref.to_poly_trait_ref(); - let trait_obligation = - obligation.with(trait_ref.to_poly_trait_predicate()); + let poly_trait_ref = obligation_trait_ref.to_poly_trait_ref(); + let trait_obligation = obligation.with(poly_trait_ref.to_poly_trait_predicate()); let vtable = match selcx.select(&trait_obligation) { Ok(Some(vtable)) => vtable, Ok(None) => { @@ -515,6 +530,11 @@ fn assemble_candidates_from_impls<'cx,'tcx>( candidate_set.vec.push( ProjectionTyCandidate::Impl(data)); } + super::VtableObject(data) => { + assemble_candidates_from_object_type( + selcx, obligation, obligation_trait_ref, candidate_set, + data.object_ty); + } super::VtableParam(..) => { // This case tell us nothing about the value of an // associated type. Consider: diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index f9dced088f8..d09f2a250b0 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -24,8 +24,10 @@ use super::{ObligationCauseCode, BuiltinDerivedObligation}; use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch}; use super::{Selection}; use super::{SelectionResult}; -use super::{VtableBuiltin, VtableImpl, VtableParam, VtableUnboxedClosure, VtableFnPointer}; -use super::{VtableImplData, VtableBuiltinData}; +use super::{VtableBuiltin, VtableImpl, VtableParam, VtableUnboxedClosure, + VtableFnPointer, VtableObject}; +use super::{VtableImplData, VtableObjectData, VtableBuiltinData}; +use super::object_safety; use super::{util}; use middle::fast_reject; @@ -147,6 +149,8 @@ enum SelectionCandidate<'tcx> { /// types generated for a fn pointer type (e.g., `fn(int)->int`) FnPointerCandidate, + ObjectCandidate, + ErrorCandidate, } @@ -289,6 +293,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + fn evaluate_predicates_recursively<'a,'o,I>(&mut self, + stack: Option<&TraitObligationStack<'o, 'tcx>>, + mut predicates: I) + -> EvaluationResult<'tcx> + where I : Iterator<&'a PredicateObligation<'tcx>>, 'tcx:'a + { + let mut result = EvaluatedToOk; + for obligation in predicates { + match self.evaluate_predicate_recursively(stack, obligation) { + EvaluatedToErr(e) => { return EvaluatedToErr(e); } + EvaluatedToAmbig => { result = EvaluatedToAmbig; } + EvaluatedToOk => { } + } + } + result + } + fn evaluate_predicate_recursively<'o>(&mut self, previous_stack: Option<&TraitObligationStack<'o, 'tcx>>, obligation: &PredicateObligation<'tcx>) @@ -320,9 +341,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { EvaluatedToOk } - ty::Predicate::Projection(..) => { - // FIXME(#20296) -- we should be able to give a more precise answer here - EvaluatedToAmbig + ty::Predicate::Projection(ref data) => { + self.infcx.probe(|_| { + let project_obligation = obligation.with(data.clone()); + match project::poly_project_and_unify_type(self, &project_obligation) { + Ok(Some(subobligations)) => { + self.evaluate_predicates_recursively(previous_stack, + subobligations.iter()) + } + Ok(None) => { + EvaluatedToAmbig + } + Err(_) => { + EvaluatedToErr(Unimplemented) + } + } + }) } } } @@ -717,6 +751,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { try!(self.assemble_unboxed_closure_candidates(obligation, &mut candidates)); try!(self.assemble_fn_pointer_candidates(obligation, &mut candidates)); try!(self.assemble_candidates_from_impls(obligation, &mut candidates.vec)); + self.assemble_candidates_from_object_ty(obligation, &mut candidates); } } @@ -878,7 +913,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let matching_bounds = all_bounds.filter( |bound| self.infcx.probe( - |_| self.match_where_clause(obligation, bound.clone())).is_ok()); + |_| self.match_poly_trait_ref(obligation, bound.clone())).is_ok()); let param_candidates = matching_bounds.map(|bound| ParamCandidate(bound)); @@ -945,7 +980,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let self_ty = self.infcx.shallow_resolve(obligation.self_ty()); match self_ty.sty { - ty::ty_infer(..) => { + ty::ty_infer(ty::TyVar(_)) => { candidates.ambiguous = true; // could wind up being a fn() type } @@ -991,6 +1026,62 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(()) } + /// Search for impls that might apply to `obligation`. + fn assemble_candidates_from_object_ty(&mut self, + obligation: &TraitObligation<'tcx>, + candidates: &mut SelectionCandidateSet<'tcx>) + { + let self_ty = self.infcx.shallow_resolve(obligation.self_ty()); + + debug!("assemble_candidates_from_object_ty(self_ty={})", + self_ty.repr(self.tcx())); + + // Object-safety candidates are only applicable to object-safe + // traits. Including this check is useful because it helps + // inference in cases of traits like `BorrowFrom`, which are + // not object-safe, and which rely on being able to infer the + // self-type from one of the other inputs. Without this check, + // these cases wind up being considered ambiguous due to a + // (spurious) ambiguity introduced here. + if !object_safety::is_object_safe(self.tcx(), obligation.predicate.to_poly_trait_ref()) { + return; + } + + let poly_trait_ref = match self_ty.sty { + ty::ty_trait(ref data) => { + data.principal_trait_ref_with_self_ty(self.tcx(), self_ty) + } + ty::ty_infer(ty::TyVar(_)) => { + debug!("assemble_candidates_from_object_ty: ambiguous"); + candidates.ambiguous = true; // could wind up being an object type + return; + } + _ => { + return; + } + }; + + debug!("assemble_candidates_from_object_ty: poly_trait_ref={}", + poly_trait_ref.repr(self.tcx())); + + // see whether the object trait can be upcast to the trait we are looking for + let obligation_def_id = obligation.predicate.def_id(); + let upcast_trait_ref = match util::upcast(self.tcx(), poly_trait_ref, obligation_def_id) { + Some(r) => r, + None => { return; } + }; + + debug!("assemble_candidates_from_object_ty: upcast_trait_ref={}", + upcast_trait_ref.repr(self.tcx())); + + // check whether the upcast version of the trait-ref matches what we are looking for + if let Ok(()) = self.infcx.probe(|_| self.match_poly_trait_ref(obligation, + upcast_trait_ref.clone())) { + debug!("assemble_candidates_from_object_ty: matched, pushing candidate"); + candidates.vec.push(ObjectCandidate); + } + } + /////////////////////////////////////////////////////////////////////////// // WINNOW // @@ -1026,15 +1117,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { selection: Selection<'tcx>) -> EvaluationResult<'tcx> { - let mut result = EvaluatedToOk; - for obligation in selection.iter_nested() { - match self.evaluate_predicate_recursively(stack, obligation) { - EvaluatedToErr(e) => { return EvaluatedToErr(e); } - EvaluatedToAmbig => { result = EvaluatedToAmbig; } - EvaluatedToOk => { } - } - } - result + self.evaluate_predicates_recursively(stack, selection.iter_nested()) } /// Returns true if `candidate_i` should be dropped in favor of `candidate_j`. @@ -1544,6 +1627,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(VtableUnboxedClosure(closure_def_id, substs)) } + ObjectCandidate => { + let data = self.confirm_object_candidate(obligation); + Ok(VtableObject(data)) + } + FnPointerCandidate => { let fn_type = try!(self.confirm_fn_pointer_candidate(obligation)); @@ -1727,6 +1815,48 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { nested: impl_predicates } } + fn confirm_object_candidate(&mut self, + obligation: &TraitObligation<'tcx>) + -> VtableObjectData<'tcx> + { + debug!("confirm_object_candidate({})", + obligation.repr(self.tcx())); + + let self_ty = self.infcx.shallow_resolve(obligation.self_ty()); + let poly_trait_ref = match self_ty.sty { + ty::ty_trait(ref data) => { + data.principal_trait_ref_with_self_ty(self.tcx(), self_ty) + } + _ => { + self.tcx().sess.span_bug(obligation.cause.span, + "object candidate with non-object"); + } + }; + + let obligation_def_id = obligation.predicate.def_id(); + let upcast_trait_ref = match util::upcast(self.tcx(), + poly_trait_ref.clone(), + obligation_def_id) { + Some(r) => r, + None => { + self.tcx().sess.span_bug(obligation.cause.span, + format!("unable to upcast from {} to {}", + poly_trait_ref.repr(self.tcx()), + obligation_def_id.repr(self.tcx())).as_slice()); + } + }; + + match self.match_poly_trait_ref(obligation, upcast_trait_ref) { + Ok(()) => { } + Err(()) => { + self.tcx().sess.span_bug(obligation.cause.span, + "failed to match trait refs"); + } + } + + VtableObjectData { object_ty: self_ty } + } + fn confirm_fn_pointer_candidate(&mut self, obligation: &TraitObligation<'tcx>) -> Result<ty::Ty<'tcx>,SelectionError<'tcx>> @@ -1962,12 +2092,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }) } - fn match_where_clause(&mut self, - obligation: &TraitObligation<'tcx>, - where_clause_trait_ref: ty::PolyTraitRef<'tcx>) - -> Result<(),()> + fn match_poly_trait_ref(&mut self, + obligation: &TraitObligation<'tcx>, + where_clause_trait_ref: ty::PolyTraitRef<'tcx>) + -> Result<(),()> { - debug!("match_where_clause: obligation={} where_clause_trait_ref={}", + debug!("match_poly_trait_ref: obligation={} where_clause_trait_ref={}", obligation.repr(self.tcx()), where_clause_trait_ref.repr(self.tcx())); @@ -2161,6 +2291,9 @@ impl<'tcx> Repr<'tcx> for SelectionCandidate<'tcx> { ImplCandidate(a) => format!("ImplCandidate({})", a.repr(tcx)), ProjectionCandidate => format!("ProjectionCandidate"), FnPointerCandidate => format!("FnPointerCandidate"), + ObjectCandidate => { + format!("ObjectCandidate") + } UnboxedClosureCandidate(c, ref s) => { format!("UnboxedClosureCandidate({},{})", c, s.repr(tcx)) } diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs index 109810fc7ee..41a59d6a5d8 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -238,6 +238,12 @@ impl<'tcx, N> fmt::Show for VtableImplData<'tcx, N> { } } +impl<'tcx> fmt::Show for super::VtableObjectData<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "VtableObject(...)") + } +} + /// See `super::obligations_for_generics` pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>, cause: ObligationCause<'tcx>, @@ -291,6 +297,58 @@ pub fn predicate_for_builtin_bound<'tcx>( }) } +/// Cast a trait reference into a reference to one of its super +/// traits; returns `None` if `target_trait_def_id` is not a +/// supertrait. +pub fn upcast<'tcx>(tcx: &ty::ctxt<'tcx>, + source_trait_ref: ty::PolyTraitRef<'tcx>, + target_trait_def_id: ast::DefId) + -> Option<ty::PolyTraitRef<'tcx>> +{ + if source_trait_ref.def_id() == target_trait_def_id { + return Some(source_trait_ref); // shorcut the most common case + } + + for super_trait_ref in supertraits(tcx, source_trait_ref) { + if super_trait_ref.def_id() == target_trait_def_id { + return Some(super_trait_ref); + } + } + + None +} + +/// Given an object of type `object_trait_ref`, returns the index of +/// the method `n_method` found in the trait `trait_def_id` (which +/// should be a supertrait of `object_trait_ref`) within the vtable +/// for `object_trait_ref`. +pub fn get_vtable_index_of_object_method<'tcx>(tcx: &ty::ctxt<'tcx>, + object_trait_ref: ty::PolyTraitRef<'tcx>, + trait_def_id: ast::DefId, + method_index_in_trait: uint) -> uint { + // We need to figure the "real index" of the method in a + // listing of all the methods of an object. We do this by + // iterating down the supertraits of the object's trait until + // we find the trait the method came from, counting up the + // methods from them. + let mut method_count = 0; + ty::each_bound_trait_and_supertraits(tcx, &[object_trait_ref], |bound_ref| { + if bound_ref.def_id() == trait_def_id { + false + } else { + let trait_items = ty::trait_items(tcx, bound_ref.def_id()); + for trait_item in trait_items.iter() { + match *trait_item { + ty::MethodTraitItem(_) => method_count += 1, + ty::TypeTraitItem(_) => {} + } + } + true + } + }); + method_count + method_index_in_trait +} + impl<'tcx,O:Repr<'tcx>> Repr<'tcx> for super::Obligation<'tcx, O> { fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { format!("Obligation(predicate={},depth={})", @@ -314,6 +372,10 @@ impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::Vtable<'tcx, N> { format!("VtableFnPointer({})", d.repr(tcx)), + super::VtableObject(ref d) => + format!("VtableObject({})", + d.repr(tcx)), + super::VtableParam => format!("VtableParam"), @@ -339,6 +401,13 @@ impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableBuiltinData<N> { } } +impl<'tcx> Repr<'tcx> for super::VtableObjectData<'tcx> { + fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { + format!("VtableObject(object_ty={})", + self.object_ty.repr(tcx)) + } +} + impl<'tcx> Repr<'tcx> for super::SelectionError<'tcx> { fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { match *self { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 7bc5d3d0708..999bc23c270 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -59,6 +59,7 @@ use middle::subst::{mod, Subst, Substs, VecPerParamSpace}; use middle::traits; use middle::ty; use middle::ty_fold::{mod, TypeFoldable, TypeFolder}; +use middle::ty_walk::TypeWalker; use util::ppaux::{note_and_explain_region, bound_region_ptr_to_string}; use util::ppaux::{trait_store_to_string, ty_to_string}; use util::ppaux::{Repr, UserString}; @@ -69,7 +70,7 @@ use util::nodemap::{FnvHashMap}; use arena::TypedArena; use std::borrow::BorrowFrom; use std::cell::{Cell, RefCell}; -use std::cmp; +use std::cmp::{mod, Ordering}; use std::fmt::{mod, Show}; use std::hash::{Hash, sip, Writer}; use std::mem; @@ -128,7 +129,7 @@ impl ImplOrTraitItemContainer { } } -#[deriving(Clone)] +#[deriving(Clone, Show)] pub enum ImplOrTraitItem<'tcx> { MethodTraitItem(Rc<Method<'tcx>>), TypeTraitItem(Rc<AssociatedType>), @@ -173,7 +174,7 @@ impl<'tcx> ImplOrTraitItem<'tcx> { } } -#[deriving(Clone, Copy)] +#[deriving(Clone, Copy, Show)] pub enum ImplOrTraitItemId { MethodTraitItemId(ast::DefId), TypeTraitItemId(ast::DefId), @@ -232,7 +233,7 @@ impl<'tcx> Method<'tcx> { } } -#[deriving(Clone, Copy)] +#[deriving(Clone, Copy, Show)] pub struct AssociatedType { pub name: ast::Name, pub vis: ast::Visibility, @@ -827,6 +828,9 @@ pub struct ctxt<'tcx> { /// parameters are never placed into this cache, because their /// results are dependent on the parameter environment. pub type_impls_sized_cache: RefCell<HashMap<Ty<'tcx>,bool>>, + + /// Caches whether traits are object safe + pub object_safety_cache: RefCell<DefIdMap<bool>>, } // Flags that we track on types. These flags are propagated upwards @@ -2384,6 +2388,7 @@ pub fn mk_ctxt<'tcx>(s: Session, repr_hint_cache: RefCell::new(DefIdMap::new()), type_impls_copy_cache: RefCell::new(HashMap::new()), type_impls_sized_cache: RefCell::new(HashMap::new()), + object_safety_cache: RefCell::new(DefIdMap::new()), } } @@ -2831,59 +2836,61 @@ pub fn mk_param_from_def<'tcx>(cx: &ctxt<'tcx>, def: &TypeParameterDef) -> Ty<'t pub fn mk_open<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { mk_t(cx, ty_open(ty)) } -pub fn walk_ty<'tcx, F>(ty: Ty<'tcx>, mut f: F) where - F: FnMut(Ty<'tcx>), +impl<'tcx> TyS<'tcx> { + /// Iterator that walks `self` and any types reachable from + /// `self`, in depth-first order. Note that just walks the types + /// that appear in `self`, it does not descend into the fields of + /// structs or variants. For example: + /// + /// ```notrust + /// int => { int } + /// Foo<Bar<int>> => { Foo<Bar<int>>, Bar<int>, int } + /// [int] => { [int], int } + /// ``` + pub fn walk(&'tcx self) -> TypeWalker<'tcx> { + TypeWalker::new(self) + } + + /// Iterator that walks types reachable from `self`, in + /// depth-first order. Note that this is a shallow walk. For + /// example: + /// + /// ```notrust + /// int => { } + /// Foo<Bar<int>> => { Bar<int>, int } + /// [int] => { int } + /// ``` + pub fn walk_children(&'tcx self) -> TypeWalker<'tcx> { + // Walks type reachable from `self` but not `self + let mut walker = self.walk(); + let r = walker.next(); + assert_eq!(r, Some(self)); + walker + } +} + +pub fn walk_ty<'tcx, F>(ty_root: Ty<'tcx>, mut f: F) + where F: FnMut(Ty<'tcx>), { - maybe_walk_ty(ty, |ty| { f(ty); true }); + for ty in ty_root.walk() { + f(ty); + } } -pub fn maybe_walk_ty<'tcx, F>(ty: Ty<'tcx>, mut f: F) where F: FnMut(Ty<'tcx>) -> bool { - // FIXME(#19596) This is a workaround, but there should be a better way to do this - fn maybe_walk_ty_<'tcx, F>(ty: Ty<'tcx>, f: &mut F) where F: FnMut(Ty<'tcx>) -> bool { - if !(*f)(ty) { - return; - } - match ty.sty { - ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) | - ty_str | ty_infer(_) | ty_param(_) | ty_err => {} - ty_uniq(ty) | ty_vec(ty, _) | ty_open(ty) => maybe_walk_ty_(ty, f), - ty_ptr(ref tm) | ty_rptr(_, ref tm) => { - maybe_walk_ty_(tm.ty, f); - } - ty_trait(box TyTrait { ref principal, .. }) => { - for subty in principal.0.substs.types.iter() { - maybe_walk_ty_(*subty, f); - } - } - ty_projection(ProjectionTy { ref trait_ref, .. }) => { - for subty in trait_ref.substs.types.iter() { - maybe_walk_ty_(*subty, f); - } - } - ty_enum(_, ref substs) | - ty_struct(_, ref substs) | - ty_unboxed_closure(_, _, ref substs) => { - for subty in substs.types.iter() { - maybe_walk_ty_(*subty, f); - } - } - ty_tup(ref ts) => { for tt in ts.iter() { maybe_walk_ty_(*tt, f); } } - ty_bare_fn(_, ref ft) => { - for a in ft.sig.0.inputs.iter() { maybe_walk_ty_(*a, f); } - if let ty::FnConverging(output) = ft.sig.0.output { - maybe_walk_ty_(output, f); - } - } - ty_closure(ref ft) => { - for a in ft.sig.0.inputs.iter() { maybe_walk_ty_(*a, f); } - if let ty::FnConverging(output) = ft.sig.0.output { - maybe_walk_ty_(output, f); - } - } +/// Walks `ty` and any types appearing within `ty`, invoking the +/// callback `f` on each type. If the callback returns false, then the +/// children of the current type are ignored. +/// +/// Note: prefer `ty.walk()` where possible. +pub fn maybe_walk_ty<'tcx,F>(ty_root: Ty<'tcx>, mut f: F) + where F : FnMut(Ty<'tcx>) -> bool +{ + let mut walker = ty_root.walk(); + while let Some(ty) = walker.next() { + if !f(ty) { + walker.skip_current_subtree(); } } - - maybe_walk_ty_(ty, &mut f); } // Folds types from the bottom up. @@ -4960,10 +4967,11 @@ pub fn provided_trait_methods<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) } } -/// Helper for looking things up in the various maps that are populated during typeck::collect -/// (e.g., `cx.impl_or_trait_items`, `cx.tcache`, etc). All of these share the pattern that if the -/// id is local, it should have been loaded into the map by the `typeck::collect` phase. If the -/// def-id is external, then we have to go consult the crate loading code (and cache the result for +/// Helper for looking things up in the various maps that are populated during +/// typeck::collect (e.g., `cx.impl_or_trait_items`, `cx.tcache`, etc). All of +/// these share the pattern that if the id is local, it should have been loaded +/// into the map by the `typeck::collect` phase. If the def-id is external, +/// then we have to go consult the crate loading code (and cache the result for /// the future). fn lookup_locally_or_in_crate_store<V, F>(descr: &str, def_id: ast::DefId, @@ -6034,11 +6042,12 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt, return } + debug!("populate_implementations_for_type_if_necessary: searching for {}", type_id); + let mut inherent_impls = Vec::new(); csearch::each_implementation_for_type(&tcx.sess.cstore, type_id, |impl_def_id| { - let impl_items = csearch::get_impl_items(&tcx.sess.cstore, - impl_def_id); + let impl_items = csearch::get_impl_items(&tcx.sess.cstore, impl_def_id); // Record the trait->implementation mappings, if applicable. let associated_traits = csearch::get_impl_trait(tcx, impl_def_id); @@ -6120,22 +6129,9 @@ pub fn populate_implementations_for_trait_if_necessary( /// Given the def_id of an impl, return the def_id of the trait it implements. /// If it implements no trait, return `None`. pub fn trait_id_of_impl(tcx: &ctxt, - def_id: ast::DefId) -> Option<ast::DefId> { - let node = match tcx.map.find(def_id.node) { - Some(node) => node, - None => return None - }; - match node { - ast_map::NodeItem(item) => { - match item.node { - ast::ItemImpl(_, _, Some(ref trait_ref), _, _) => { - Some(node_id_to_trait_ref(tcx, trait_ref.ref_id).def_id) - } - _ => None - } - } - _ => None - } + def_id: ast::DefId) + -> Option<ast::DefId> { + ty::impl_trait_ref(tcx, def_id).map(|tr| tr.def_id) } /// If the given def ID describes a method belonging to an impl, return the @@ -7269,7 +7265,7 @@ impl<T:ReferencesError> ReferencesError for Binder<T> { impl<T:ReferencesError> ReferencesError for Rc<T> { fn references_error(&self) -> bool { - (&*self).references_error() + (&**self).references_error() } } diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 83d2f6fb0e6..abbf530529b 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -56,7 +56,7 @@ pub trait TypeFoldable<'tcx> { /// default implementation that does an "identity" fold. Within each /// identity fold, it should invoke `foo.fold_with(self)` to fold each /// sub-item. -pub trait TypeFolder<'tcx> { +pub trait TypeFolder<'tcx> : Sized { fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>; /// Invoked by the `super_*` routines when we enter a region @@ -503,6 +503,15 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N> } traits::VtableParam => traits::VtableParam, traits::VtableBuiltin(ref d) => traits::VtableBuiltin(d.fold_with(folder)), + traits::VtableObject(ref d) => traits::VtableObject(d.fold_with(folder)), + } + } +} + +impl<'tcx> TypeFoldable<'tcx> for traits::VtableObjectData<'tcx> { + fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableObjectData<'tcx> { + traits::VtableObjectData { + object_ty: self.object_ty.fold_with(folder) } } } diff --git a/src/librustc/middle/ty_walk.rs b/src/librustc/middle/ty_walk.rs new file mode 100644 index 00000000000..406ebf4bc38 --- /dev/null +++ b/src/librustc/middle/ty_walk.rs @@ -0,0 +1,112 @@ +// Copyright 2012-2014 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. + +//! An iterator over the type substructure. + +use middle::ty::{mod, Ty}; +use std::iter::Iterator; + +pub struct TypeWalker<'tcx> { + stack: Vec<Ty<'tcx>>, + last_subtree: uint, +} + +impl<'tcx> TypeWalker<'tcx> { + pub fn new(ty: Ty<'tcx>) -> TypeWalker<'tcx> { + TypeWalker { stack: vec!(ty), last_subtree: 1, } + } + + fn push_subtypes(&mut self, parent_ty: Ty<'tcx>) { + match parent_ty.sty { + ty::ty_bool | ty::ty_char | ty::ty_int(_) | ty::ty_uint(_) | ty::ty_float(_) | + ty::ty_str | ty::ty_infer(_) | ty::ty_param(_) | ty::ty_err => { + } + ty::ty_uniq(ty) | ty::ty_vec(ty, _) | ty::ty_open(ty) => { + self.stack.push(ty); + } + ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => { + self.stack.push(mt.ty); + } + ty::ty_projection(ref data) => { + self.push_reversed(data.trait_ref.substs.types.as_slice()); + } + ty::ty_trait(box ty::TyTrait { ref principal, .. }) => { + self.push_reversed(principal.substs().types.as_slice()); + } + ty::ty_enum(_, ref substs) | + ty::ty_struct(_, ref substs) | + ty::ty_unboxed_closure(_, _, ref substs) => { + self.push_reversed(substs.types.as_slice()); + } + ty::ty_tup(ref ts) => { + self.push_reversed(ts.as_slice()); + } + ty::ty_bare_fn(_, ref ft) => { + self.push_sig_subtypes(&ft.sig); + } + ty::ty_closure(ref ft) => { + self.push_sig_subtypes(&ft.sig); + } + } + } + + fn push_sig_subtypes(&mut self, sig: &ty::PolyFnSig<'tcx>) { + match sig.0.output { + ty::FnConverging(output) => { self.stack.push(output); } + ty::FnDiverging => { } + } + self.push_reversed(sig.0.inputs.as_slice()); + } + + fn push_reversed(&mut self, tys: &[Ty<'tcx>]) { + // We push slices on the stack in reverse order so as to + // maintain a pre-order traversal. As of the time of this + // writing, the fact that the traversal is pre-order is not + // known to be significant to any code, but it seems like the + // natural order one would expect (basically, the order of the + // types as they are written). + for &ty in tys.iter().rev() { + self.stack.push(ty); + } + } + + /// Skips the subtree of types corresponding to the last type + /// returned by `next()`. + /// + /// Example: Imagine you are walking `Foo<Bar<int>, uint>`. + /// + /// ```rust + /// let mut iter: TypeWalker = ...; + /// iter.next(); // yields Foo + /// iter.next(); // yields Bar<int> + /// iter.skip_current_subtree(); // skips int + /// iter.next(); // yields uint + /// ``` + pub fn skip_current_subtree(&mut self) { + self.stack.truncate(self.last_subtree); + } +} + +impl<'tcx> Iterator<Ty<'tcx>> for TypeWalker<'tcx> { + fn next(&mut self) -> Option<Ty<'tcx>> { + debug!("next(): stack={}", self.stack); + match self.stack.pop() { + None => { + return None; + } + Some(ty) => { + self.last_subtree = self.stack.len(); + self.push_subtypes(ty); + debug!("next: stack={}", self.stack); + Some(ty) + } + } + } +} diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 19ac6d466fb..f299ea939ed 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -394,6 +394,7 @@ macro_rules! cgoptions { mod cgsetters { use super::{CodegenOptions, Passes, SomePasses, AllPasses}; + use std::str::from_str; $( pub fn $opt(cg: &mut CodegenOptions, v: Option<&str>) -> bool { @@ -743,7 +744,7 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> { opt::multi("l", "", "Link the generated crate(s) to the specified native library NAME. The optional KIND can be one of, static, dylib, or framework. If omitted, dylib is - assumed.", "NAME[:KIND]"), + assumed.", "[KIND=]NAME"), opt::multi("", "crate-type", "Comma separated list of types of crates for the compiler to emit", "[bin|lib|rlib|dylib|staticlib]"), @@ -1016,6 +1017,24 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { } let libs = matches.opt_strs("l").into_iter().map(|s| { + let mut parts = s.splitn(1, '='); + let kind = parts.next().unwrap(); + if let Some(name) = parts.next() { + let kind = match kind { + "dylib" => cstore::NativeUnknown, + "framework" => cstore::NativeFramework, + "static" => cstore::NativeStatic, + s => { + early_error(format!("unknown library kind `{}`, expected \ + one of dylib, framework, or static", + s)[]); + } + }; + return (name.to_string(), kind) + } + + // FIXME(acrichto) remove this once crates have stopped using it, this + // is deprecated behavior now. let mut parts = s.rsplitn(1, ':'); let kind = parts.next().unwrap(); let (name, kind) = match (parts.next(), kind) { diff --git a/src/librustc/session/search_paths.rs b/src/librustc/session/search_paths.rs index 8a6217a49f5..56b4cae2e43 100644 --- a/src/librustc/session/search_paths.rs +++ b/src/librustc/session/search_paths.rs @@ -34,15 +34,14 @@ impl SearchPaths { } pub fn add_path(&mut self, path: &str) { - let (kind, path) = if path.ends_with(":native") { - (PathKind::Native, path.slice_to(path.len() - ":native".len())) - } else if path.ends_with(":crate") { - (PathKind::Crate, path.slice_to(path.len() - ":crate".len())) - } else if path.ends_with(":dependency") { - (PathKind::Dependency, - path.slice_to(path.len() - ":dependency".len())) - } else if path.ends_with(":all") { - (PathKind::All, path.slice_to(path.len() - ":all".len())) + let (kind, path) = if path.starts_with("native=") { + (PathKind::Native, path.slice_from("native=".len())) + } else if path.starts_with("crate=") { + (PathKind::Crate, path.slice_from("crate=".len())) + } else if path.starts_with("dependency=") { + (PathKind::Dependency, path.slice_from("dependency=".len())) + } else if path.starts_with("all=") { + (PathKind::All, path.slice_from("all=".len())) } else { (PathKind::All, path) }; diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index cb547df7d9c..2bb99a7141f 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -32,6 +32,7 @@ #![allow(unknown_features)] #![feature(globs, phase, macro_rules, slicing_syntax)] #![feature(unboxed_closures)] +#![feature(old_orphan_check)] #[phase(plugin, link)] extern crate log; diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs index 73b345a70af..8d3aa397f30 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs @@ -33,7 +33,7 @@ impl<'tcx> MoveErrorCollector<'tcx> { } pub fn report_potential_errors<'a>(&self, bccx: &BorrowckCtxt<'a, 'tcx>) { - report_move_errors(bccx, self.errors.borrow().deref()) + report_move_errors(bccx, &*self.errors.borrow()) } } diff --git a/src/librustc_borrowck/graphviz.rs b/src/librustc_borrowck/graphviz.rs index e2813c8e988..ac6b962d647 100644 --- a/src/librustc_borrowck/graphviz.rs +++ b/src/librustc_borrowck/graphviz.rs @@ -24,6 +24,7 @@ use rustc::middle::cfg::{CFGIndex}; use rustc::middle::dataflow::{DataFlowOperator, DataFlowContext, EntryOrExit}; use rustc::middle::dataflow; use std::rc::Rc; +use std::borrow::IntoCow; #[deriving(Show, Copy)] pub enum Variant { diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs index 664d470b11b..b886883c73a 100644 --- a/src/librustc_borrowck/lib.rs +++ b/src/librustc_borrowck/lib.rs @@ -16,10 +16,12 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/nightly/")] +#![allow(unknown_features)] #![feature(default_type_params, globs, macro_rules, phase, quote)] #![feature(slicing_syntax, unsafe_destructor)] #![feature(rustc_diagnostic_macros)] #![feature(unboxed_closures)] +#![feature(old_orphan_check)] #![allow(non_camel_case_types)] #[phase(plugin, link)] extern crate log; diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 91902b90673..a92c2fe2ccb 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -28,7 +28,7 @@ use rustc_trans::save; use rustc_trans::trans; use rustc_typeck as typeck; -use serialize::{json, Encodable}; +use serialize::json; use std::io; use std::io::fs; @@ -143,10 +143,7 @@ pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input) }); if sess.opts.debugging_opts & config::AST_JSON_NOEXPAND != 0 { - let mut stdout = io::BufferedWriter::new(io::stdout()); - let mut json = json::PrettyEncoder::new(&mut stdout); - // unwrapping so IoError isn't ignored - krate.encode(&mut json).unwrap(); + println!("{}", json::as_json(&krate)); } if sess.show_span() { @@ -338,10 +335,7 @@ pub fn assign_node_ids_and_map<'ast>(sess: &Session, ast_map::map_crate(forest, NodeIdAssigner { sess: sess })); if sess.opts.debugging_opts & config::AST_JSON != 0 { - let mut stdout = io::BufferedWriter::new(io::stdout()); - let mut json = json::PrettyEncoder::new(&mut stdout); - // unwrapping so IoError isn't ignored - map.krate().encode(&mut json).unwrap(); + println!("{}", json::as_json(map.krate())); } map diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 181f38d8993..be55da8c59d 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -54,9 +54,11 @@ use rustc::metadata; use rustc::DIAGNOSTICS; use std::any::AnyRefExt; +use std::cmp::Ordering::Equal; use std::io; use std::iter::repeat; use std::os; +use std::sync::mpsc::channel; use std::thread; use rustc::session::early_error; diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 773ea30d401..a046d9d5d39 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -154,7 +154,7 @@ trait PrinterSupport<'ast>: pprust::PpAnn { /// /// (Rust does not yet support upcasting from a trait object to /// an object for one of its super-traits.) - fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self as &pprust::PpAnn } + fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn; } struct NoAnn<'ast> { @@ -168,6 +168,8 @@ impl<'ast> PrinterSupport<'ast> for NoAnn<'ast> { fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map<'ast>> { self.ast_map.as_ref() } + + fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self } } impl<'ast> pprust::PpAnn for NoAnn<'ast> {} @@ -183,6 +185,8 @@ impl<'ast> PrinterSupport<'ast> for IdentifiedAnnotation<'ast> { fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map<'ast>> { self.ast_map.as_ref() } + + fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self } } impl<'ast> pprust::PpAnn for IdentifiedAnnotation<'ast> { @@ -232,6 +236,8 @@ impl<'ast> PrinterSupport<'ast> for HygieneAnnotation<'ast> { fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map<'ast>> { self.ast_map.as_ref() } + + fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self } } impl<'ast> pprust::PpAnn for HygieneAnnotation<'ast> { @@ -265,6 +271,8 @@ impl<'tcx> PrinterSupport<'tcx> for TypedAnnotation<'tcx> { fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map<'tcx>> { Some(&self.analysis.ty_cx.map) } + + fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self } } impl<'tcx> pprust::PpAnn for TypedAnnotation<'tcx> { diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 6329acfb578..eddcc750068 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -34,8 +34,6 @@ use syntax::codemap::{Span, CodeMap, DUMMY_SP}; use syntax::diagnostic::{Level, RenderSpan, Bug, Fatal, Error, Warning, Note, Help}; use syntax::parse::token; -use arena::TypedArena; - struct Env<'a, 'tcx: 'a> { infcx: &'a infer::InferCtxt<'a, 'tcx>, } @@ -831,3 +829,57 @@ fn subst_region_renumber_region() { assert_eq!(t_substituted, t_expected); }) } + +#[test] +fn walk_ty() { + test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { + let tcx = env.infcx.tcx; + let int_ty = tcx.types.int; + let uint_ty = tcx.types.uint; + let tup1_ty = ty::mk_tup(tcx, vec!(int_ty, uint_ty, int_ty, uint_ty)); + let tup2_ty = ty::mk_tup(tcx, vec!(tup1_ty, tup1_ty, uint_ty)); + let uniq_ty = ty::mk_uniq(tcx, tup2_ty); + let walked: Vec<_> = uniq_ty.walk().collect(); + assert_eq!(vec!(uniq_ty, + tup2_ty, + tup1_ty, int_ty, uint_ty, int_ty, uint_ty, + tup1_ty, int_ty, uint_ty, int_ty, uint_ty, + uint_ty), + walked); + }) +} + +#[test] +fn walk_ty_skip_subtree() { + test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { + let tcx = env.infcx.tcx; + let int_ty = tcx.types.int; + let uint_ty = tcx.types.uint; + let tup1_ty = ty::mk_tup(tcx, vec!(int_ty, uint_ty, int_ty, uint_ty)); + let tup2_ty = ty::mk_tup(tcx, vec!(tup1_ty, tup1_ty, uint_ty)); + let uniq_ty = ty::mk_uniq(tcx, tup2_ty); + + // types we expect to see (in order), plus a boolean saying + // whether to skip the subtree. + let mut expected = vec!((uniq_ty, false), + (tup2_ty, false), + (tup1_ty, false), + (int_ty, false), + (uint_ty, false), + (int_ty, false), + (uint_ty, false), + (tup1_ty, true), // skip the int/uint/int/uint + (uint_ty, false)); + expected.reverse(); + + let mut walker = uniq_ty.walk(); + while let Some(t) = walker.next() { + debug!("walked to {}", t); + let (expected_ty, skip) = expected.pop().unwrap(); + assert_eq!(t, expected_ty); + if skip { walker.skip_current_subtree(); } + } + + assert!(expected.is_empty()); + }) +} diff --git a/src/librustc_llvm/archive_ro.rs b/src/librustc_llvm/archive_ro.rs index 6c3778787e2..53992d4567a 100644 --- a/src/librustc_llvm/archive_ro.rs +++ b/src/librustc_llvm/archive_ro.rs @@ -13,8 +13,9 @@ use libc; use ArchiveRef; -use std::raw; +use std::c_str::ToCStr; use std::mem; +use std::raw; pub struct ArchiveRO { ptr: ArchiveRef, diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index efb9b636247..aa3ac83c027 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -61,8 +61,9 @@ use syntax::parse::token::{mod, special_idents}; use syntax::codemap::{Span, DUMMY_SP}; use syntax::visit::{mod, Visitor}; -use std::rc::Rc; use std::mem::replace; +use std::ops::{Deref, DerefMut}; +use std::rc::Rc; // Specifies how duplicates should be handled when adding a child item if // another item exists with the same name in some namespace. @@ -95,13 +96,15 @@ struct GraphBuilder<'a, 'b:'a, 'tcx:'b> { resolver: &'a mut Resolver<'b, 'tcx> } -impl<'a, 'b:'a, 'tcx:'b> Deref<Resolver<'b, 'tcx>> for GraphBuilder<'a, 'b, 'tcx> { +impl<'a, 'b:'a, 'tcx:'b> Deref for GraphBuilder<'a, 'b, 'tcx> { + type Target = Resolver<'b, 'tcx>; + fn deref(&self) -> &Resolver<'b, 'tcx> { &*self.resolver } } -impl<'a, 'b:'a, 'tcx:'b> DerefMut<Resolver<'b, 'tcx>> for GraphBuilder<'a, 'b, 'tcx> { +impl<'a, 'b:'a, 'tcx:'b> DerefMut for GraphBuilder<'a, 'b, 'tcx> { fn deref_mut(&mut self) -> &mut Resolver<'b, 'tcx> { &mut *self.resolver } diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index 78527315199..1bfe4c0407a 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -17,6 +17,8 @@ // `use` directives. // +use std::ops::{Deref, DerefMut}; + use Resolver; use Namespace::{TypeNS, ValueNS}; @@ -33,13 +35,15 @@ struct UnusedImportCheckVisitor<'a, 'b:'a, 'tcx:'b> { } // Deref and DerefMut impls allow treating UnusedImportCheckVisitor as Resolver. -impl<'a, 'b, 'tcx:'b> Deref<Resolver<'b, 'tcx>> for UnusedImportCheckVisitor<'a, 'b, 'tcx> { +impl<'a, 'b, 'tcx:'b> Deref for UnusedImportCheckVisitor<'a, 'b, 'tcx> { + type Target = Resolver<'b, 'tcx>; + fn deref<'c>(&'c self) -> &'c Resolver<'b, 'tcx> { &*self.resolver } } -impl<'a, 'b, 'tcx:'b> DerefMut<Resolver<'b, 'tcx>> for UnusedImportCheckVisitor<'a, 'b, 'tcx> { +impl<'a, 'b, 'tcx:'b> DerefMut for UnusedImportCheckVisitor<'a, 'b, 'tcx> { fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b, 'tcx> { &mut *self.resolver } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 11328bedcc4..4ac9224969c 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -18,6 +18,7 @@ #![feature(globs, phase, slicing_syntax)] #![feature(rustc_diagnostic_macros)] +#![feature(associated_types)] #[phase(plugin, link)] extern crate log; #[phase(plugin, link)] extern crate syntax; @@ -3402,7 +3403,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn resolve_local(&mut self, local: &Local) { // Resolve the type. - self.resolve_type(&*local.ty); + if let Some(ref ty) = local.ty { + self.resolve_type(&**ty); + } // Resolve the initializer, if necessary. match local.init { diff --git a/src/librustc_resolve/record_exports.rs b/src/librustc_resolve/record_exports.rs index 9c2437c376d..ff415750d64 100644 --- a/src/librustc_resolve/record_exports.rs +++ b/src/librustc_resolve/record_exports.rs @@ -27,6 +27,7 @@ use rustc::middle::def::Export; use syntax::ast; use syntax::parse::token; +use std::ops::{Deref, DerefMut}; use std::rc::Rc; struct ExportRecorder<'a, 'b:'a, 'tcx:'b> { @@ -34,13 +35,15 @@ struct ExportRecorder<'a, 'b:'a, 'tcx:'b> { } // Deref and DerefMut impls allow treating ExportRecorder as Resolver. -impl<'a, 'b, 'tcx:'b> Deref<Resolver<'b, 'tcx>> for ExportRecorder<'a, 'b, 'tcx> { +impl<'a, 'b, 'tcx:'b> Deref for ExportRecorder<'a, 'b, 'tcx> { + type Target = Resolver<'b, 'tcx>; + fn deref<'c>(&'c self) -> &'c Resolver<'b, 'tcx> { &*self.resolver } } -impl<'a, 'b, 'tcx:'b> DerefMut<Resolver<'b, 'tcx>> for ExportRecorder<'a, 'b, 'tcx> { +impl<'a, 'b, 'tcx:'b> DerefMut for ExportRecorder<'a, 'b, 'tcx> { fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b, 'tcx> { &mut *self.resolver } diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs index 1271330897e..7cf4bafe032 100644 --- a/src/librustc_trans/back/lto.rs +++ b/src/librustc_trans/back/lto.rs @@ -20,6 +20,7 @@ use rustc::util::common::time; use libc; use flate; +use std::c_str::ToCStr; use std::iter; use std::mem; use std::num::Int; diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index a6f2c7dfed0..5cd62675c1d 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -30,6 +30,7 @@ use std::ptr; use std::str; use std::mem; use std::sync::{Arc, Mutex}; +use std::sync::mpsc::channel; use std::thread; use libc::{c_uint, c_int, c_void}; @@ -928,13 +929,13 @@ fn run_work_multithreaded(sess: &Session, } } - tx.take().unwrap().send(()); + tx.take().unwrap().send(()).unwrap(); }).detach(); } let mut panicked = false; for rx in futures.into_iter() { - match rx.recv_opt() { + match rx.recv() { Ok(()) => {}, Err(_) => { panicked = true; @@ -1009,7 +1010,7 @@ unsafe fn configure_llvm(sess: &Session) { } } - INIT.doit(|| { + INIT.call_once(|| { llvm::LLVMInitializePasses(); // Only initialize the platforms supported by Rust here, because diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 784002287b7..5ffe9b2d647 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -22,10 +22,12 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/nightly/")] +#![allow(unknown_features)] #![feature(default_type_params, globs, macro_rules, phase, quote)] #![feature(slicing_syntax, unsafe_destructor)] #![feature(rustc_diagnostic_macros)] #![feature(unboxed_closures)] +#![feature(old_orphan_check)] extern crate arena; extern crate flate; diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 51ea0af8e10..73961f00d70 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -1202,8 +1202,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { let glob_map = &self.analysis.glob_map; let glob_map = glob_map.as_ref().unwrap(); if glob_map.contains_key(&id) { - let names = glob_map.index(&id); - for n in names.iter() { + for n in glob_map[id].iter() { if name_string.len() > 0 { name_string.push_str(", "); } @@ -1496,7 +1495,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { self.collected_paths.clear(); // Just walk the initialiser and type (don't want to walk the pattern again). - self.visit_ty(&*l.ty); + visit::walk_ty_opt(self, &l.ty); visit::walk_expr_opt(self, &l.init); } } diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 18155d75680..bf53885e9e5 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -3097,7 +3097,7 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>) use std::sync::{Once, ONCE_INIT}; static INIT: Once = ONCE_INIT; static mut POISONED: bool = false; - INIT.doit(|| { + INIT.call_once(|| { if llvm::LLVMStartMultithreaded() != 1 { // use an extra bool to make sure that all future usage of LLVM // cannot proceed despite the Once not running more than once. diff --git a/src/librustc_trans/trans/builder.rs b/src/librustc_trans/trans/builder.rs index b39dbd71117..97f0b92a290 100644 --- a/src/librustc_trans/trans/builder.rs +++ b/src/librustc_trans/trans/builder.rs @@ -20,7 +20,7 @@ use trans::machine::llalign_of_pref; use trans::type_::Type; use util::nodemap::FnvHashMap; use libc::{c_uint, c_char}; -use std::string::String; +use std::c_str::ToCStr; use syntax::codemap::Span; pub struct Builder<'a, 'tcx: 'a> { diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index c651255226b..1a0007cf0fc 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -853,7 +853,7 @@ pub fn create_global_var_metadata(cx: &CrateContext, /// local in `bcx.fcx.lllocals`. /// Adds the created metadata nodes directly to the crate's IR. pub fn create_local_var_metadata(bcx: Block, local: &ast::Local) { - if fn_should_be_ignored(bcx.fcx) { + if bcx.unreachable.get() || fn_should_be_ignored(bcx.fcx) { return; } @@ -897,7 +897,7 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, env_index: uint, captured_by_ref: bool, span: Span) { - if fn_should_be_ignored(bcx.fcx) { + if bcx.unreachable.get() || fn_should_be_ignored(bcx.fcx) { return; } @@ -980,7 +980,7 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pub fn create_match_binding_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, variable_ident: ast::Ident, binding: BindingInfo<'tcx>) { - if fn_should_be_ignored(bcx.fcx) { + if bcx.unreachable.get() || fn_should_be_ignored(bcx.fcx) { return; } @@ -1020,7 +1020,7 @@ pub fn create_match_binding_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// argument in `bcx.fcx.lllocals`. /// Adds the created metadata nodes directly to the crate's IR. pub fn create_argument_metadata(bcx: Block, arg: &ast::Arg) { - if fn_should_be_ignored(bcx.fcx) { + if bcx.unreachable.get() || fn_should_be_ignored(bcx.fcx) { return; } @@ -1074,7 +1074,7 @@ pub fn create_argument_metadata(bcx: Block, arg: &ast::Arg) { /// loop variable in `bcx.fcx.lllocals`. /// Adds the created metadata nodes directly to the crate's IR. pub fn create_for_loop_var_metadata(bcx: Block, pat: &ast::Pat) { - if fn_should_be_ignored(bcx.fcx) { + if bcx.unreachable.get() || fn_should_be_ignored(bcx.fcx) { return; } diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs index 83765270ef1..99dc971ed94 100644 --- a/src/librustc_trans/trans/foreign.rs +++ b/src/librustc_trans/trans/foreign.rs @@ -26,6 +26,7 @@ use trans::type_of; use middle::ty::{mod, Ty}; use middle::subst::{Substs}; use std::cmp; +use std::c_str::ToCStr; use libc::c_uint; use syntax::abi::{Cdecl, Aapcs, C, Win64, Abi}; use syntax::abi::{RustIntrinsic, Rust, RustCall, Stdcall, Fastcall, System}; diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 9535ffaec0e..99624f1b1e7 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -8,12 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use arena::TypedArena; use back::abi; -use llvm; -use llvm::ValueRef; +use back::link; +use llvm::{mod, ValueRef, get_param}; use metadata::csearch; -use middle::subst::{Substs}; +use middle::subst::{Subst, Substs}; use middle::subst::VecPerParamSpace; use middle::subst; use middle::traits; @@ -370,6 +370,10 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let llfn = trans_fn_pointer_shim(bcx.ccx(), fn_ty); Callee { bcx: bcx, data: Fn(llfn) } } + traits::VtableObject(ref data) => { + let llfn = trans_object_shim(bcx.ccx(), data.object_ty, trait_id, n_method); + Callee { bcx: bcx, data: Fn(llfn) } + } traits::VtableBuiltin(..) | traits::VtableParam(..) => { bcx.sess().bug( @@ -503,6 +507,137 @@ pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, }; } +/// Generate a shim function that allows an object type like `SomeTrait` to +/// implement the type `SomeTrait`. Imagine a trait definition: +/// +/// trait SomeTrait { fn get(&self) -> int; ... } +/// +/// And a generic bit of code: +/// +/// fn foo<T:SomeTrait>(t: &T) { +/// let x = SomeTrait::get; +/// x(t) +/// } +/// +/// What is the value of `x` when `foo` is invoked with `T=SomeTrait`? +/// The answer is that it it is a shim function generate by this +/// routine: +/// +/// fn shim(t: &SomeTrait) -> int { +/// // ... call t.get() virtually ... +/// } +/// +/// In fact, all virtual calls can be thought of as normal trait calls +/// that go through this shim function. +pub fn trans_object_shim<'a, 'tcx>( + ccx: &'a CrateContext<'a, 'tcx>, + object_ty: Ty<'tcx>, + trait_id: ast::DefId, + method_offset_in_trait: uint) + -> ValueRef +{ + let _icx = push_ctxt("trans_object_shim"); + let tcx = ccx.tcx(); + + debug!("trans_object_shim(object_ty={}, trait_id={}, n_method={})", + object_ty.repr(tcx), + trait_id.repr(tcx), + method_offset_in_trait); + + let object_trait_ref = + match object_ty.sty { + ty::ty_trait(ref data) => { + data.principal_trait_ref_with_self_ty(tcx, object_ty) + } + _ => { + tcx.sess.bug(format!("trans_object_shim() called on non-object: {}", + object_ty.repr(tcx)).as_slice()); + } + }; + + // Upcast to the trait in question and extract out the substitutions. + let upcast_trait_ref = traits::upcast(ccx.tcx(), object_trait_ref.clone(), trait_id).unwrap(); + let object_substs = upcast_trait_ref.substs().clone().erase_regions(); + debug!("trans_object_shim: object_substs={}", object_substs.repr(tcx)); + + // Lookup the type of this method as deeclared in the trait and apply substitutions. + let method_ty = match ty::trait_item(tcx, trait_id, method_offset_in_trait) { + ty::MethodTraitItem(method) => method, + ty::TypeTraitItem(_) => { + tcx.sess.bug("can't create a method shim for an associated type") + } + }; + let fty = method_ty.fty.subst(tcx, &object_substs); + let fty = tcx.mk_bare_fn(fty); + debug!("trans_object_shim: fty={}", fty.repr(tcx)); + + // + let method_bare_fn_ty = + ty::mk_bare_fn(tcx, None, fty); + let function_name = + link::mangle_internal_name_by_type_and_seq(ccx, method_bare_fn_ty, "object_shim"); + let llfn = + decl_internal_rust_fn(ccx, method_bare_fn_ty, function_name.as_slice()); + + // + let block_arena = TypedArena::new(); + let empty_substs = Substs::trans_empty(); + let fcx = new_fn_ctxt(ccx, + llfn, + ast::DUMMY_NODE_ID, + false, + fty.sig.0.output, + &empty_substs, + None, + &block_arena); + let mut bcx = init_function(&fcx, false, fty.sig.0.output); + + // the first argument (`self`) will be a trait object + let llobject = get_param(fcx.llfn, fcx.arg_pos(0) as u32); + + debug!("trans_object_shim: llobject={}", + bcx.val_to_string(llobject)); + + // the remaining arguments will be, well, whatever they are + let llargs: Vec<_> = + fty.sig.0.inputs[1..].iter() + .enumerate() + .map(|(i, _)| { + let llarg = get_param(fcx.llfn, fcx.arg_pos(i+1) as u32); + debug!("trans_object_shim: input #{} == {}", + i, bcx.val_to_string(llarg)); + llarg + }) + .collect(); + assert!(!fcx.needs_ret_allocas); + + let dest = + fcx.llretslotptr.get().map( + |_| expr::SaveIn(fcx.get_ret_slot(bcx, fty.sig.0.output, "ret_slot"))); + + let method_offset_in_vtable = + traits::get_vtable_index_of_object_method(bcx.tcx(), + object_trait_ref.clone(), + trait_id, + method_offset_in_trait); + debug!("trans_object_shim: method_offset_in_vtable={}", + method_offset_in_vtable); + + bcx = trans_call_inner(bcx, + None, + method_bare_fn_ty, + |bcx, _| trans_trait_callee_from_llval(bcx, + method_bare_fn_ty, + method_offset_in_vtable, + llobject), + ArgVals(llargs.as_slice()), + dest).bcx; + + finish_fn(&fcx, bcx, fty.sig.0.output); + + llfn +} + /// Creates a returns a dynamic vtable for the given type and vtable origin. /// This is used only for objects. /// @@ -560,6 +695,14 @@ pub fn get_vtable<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let llfn = vec![trans_fn_pointer_shim(bcx.ccx(), bare_fn_ty)]; llfn.into_iter() } + traits::VtableObject(ref data) => { + // this would imply that the Self type being erased is + // an object type; this cannot happen because we + // cannot cast an unsized type into a trait object + bcx.sess().bug( + format!("cannot get vtable for an object type: {}", + data.repr(bcx.tcx())).as_slice()); + } traits::VtableParam => { bcx.sess().bug( format!("resolved vtable for {} to bad vtable {} in trans", diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index a751b65a0f8..ee859bbe8f5 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -633,17 +633,16 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { target_trait_def_id: ast::DefId) -> ty::PolyTraitRef<'tcx> { - for super_trait_ref in traits::supertraits(self.tcx(), source_trait_ref.clone()) { - if super_trait_ref.def_id() == target_trait_def_id { - return super_trait_ref; + match traits::upcast(self.tcx(), source_trait_ref.clone(), target_trait_def_id) { + Some(super_trait_ref) => super_trait_ref, + None => { + self.tcx().sess.span_bug( + self.span, + format!("cannot upcast `{}` to `{}`", + source_trait_ref.repr(self.tcx()), + target_trait_def_id.repr(self.tcx()))[]); } } - - self.tcx().sess.span_bug( - self.span, - format!("cannot upcast `{}` to `{}`", - source_trait_ref.repr(self.tcx()), - target_trait_def_id.repr(self.tcx()))[]); } fn replace_late_bound_regions_with_fresh_var<T>(&self, value: &ty::Binder<T>) -> T diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index f00e3e2d452..52860abb6f9 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -267,6 +267,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { return; // already visited } + debug!("assemble_inherent_impl_probe {}", impl_def_id); + let method = match impl_method(self.tcx(), impl_def_id, self.method_name) { Some(m) => m, None => { return; } // No method with correct name on this impl @@ -308,7 +310,10 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { let trait_ref = data.principal_trait_ref_with_self_ty(self.tcx(), self_ty); self.elaborate_bounds(&[trait_ref.clone()], false, |this, new_trait_ref, m, method_num| { let vtable_index = - get_method_index(tcx, &new_trait_ref, trait_ref.clone(), method_num); + traits::get_vtable_index_of_object_method(tcx, + trait_ref.clone(), + new_trait_ref.def_id(), + method_num); let xform_self_ty = this.xform_self_ty(&m, new_trait_ref.substs()); @@ -432,7 +437,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { } fn assemble_extension_candidates_for_trait(&mut self, - trait_def_id: ast::DefId) { + trait_def_id: ast::DefId) { debug!("assemble_extension_candidates_for_trait: trait_def_id={}", trait_def_id.repr(self.tcx())); @@ -984,6 +989,7 @@ fn trait_method<'tcx>(tcx: &ty::ctxt<'tcx>, -> Option<(uint, Rc<ty::Method<'tcx>>)> { let trait_items = ty::trait_items(tcx, trait_def_id); + debug!("trait_method; items: {}", trait_items); trait_items .iter() .filter(|item| @@ -996,35 +1002,6 @@ fn trait_method<'tcx>(tcx: &ty::ctxt<'tcx>, .and_then(|(idx, item)| item.as_opt_method().map(|m| (idx, m))) } -// Determine the index of a method in the list of all methods belonging -// to a trait and its supertraits. -fn get_method_index<'tcx>(tcx: &ty::ctxt<'tcx>, - trait_ref: &ty::PolyTraitRef<'tcx>, - subtrait: ty::PolyTraitRef<'tcx>, - n_method: uint) -> uint { - // We need to figure the "real index" of the method in a - // listing of all the methods of an object. We do this by - // iterating down the supertraits of the object's trait until - // we find the trait the method came from, counting up the - // methods from them. - let mut method_count = n_method; - ty::each_bound_trait_and_supertraits(tcx, &[subtrait], |bound_ref| { - if bound_ref.def_id() == trait_ref.def_id() { - false - } else { - let trait_items = ty::trait_items(tcx, bound_ref.def_id()); - for trait_item in trait_items.iter() { - match *trait_item { - ty::MethodTraitItem(_) => method_count += 1, - ty::TypeTraitItem(_) => {} - } - } - true - } - }); - method_count -} - impl<'tcx> Candidate<'tcx> { fn to_unadjusted_pick(&self) -> Pick<'tcx> { Pick { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d4e025a3813..19ec85dc61e 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -507,9 +507,9 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> { impl<'a, 'tcx, 'v> Visitor<'v> for GatherLocalsVisitor<'a, 'tcx> { // Add explicitly-declared locals. fn visit_local(&mut self, local: &ast::Local) { - let o_ty = match local.ty.node { - ast::TyInfer => None, - _ => Some(self.fcx.to_ty(&*local.ty)) + let o_ty = match local.ty { + Some(ref ty) => Some(self.fcx.to_ty(&**ty)), + None => None }; self.assign(local.span, local.id, o_ty); debug!("Local variable {} is assigned type {}", diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs index c85b542b6ca..1ef6c114032 100644 --- a/src/librustc_typeck/check/vtable.rs +++ b/src/librustc_typeck/check/vtable.rs @@ -9,8 +9,7 @@ // except according to those terms. use check::{FnCtxt, structurally_resolved_type}; -use middle::subst::{FnSpace, SelfSpace}; -use middle::traits; +use middle::traits::{mod, ObjectSafetyViolation, MethodViolationCode}; use middle::traits::{Obligation, ObligationCause}; use middle::traits::report_fulfillment_errors; use middle::ty::{mod, Ty, AsPredicate}; @@ -133,217 +132,56 @@ pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>, object_trait: &ty::TyTrait<'tcx>, span: Span) { - // Also check that the type `object_trait` specifies all - // associated types for all supertraits. - let mut associated_types: FnvHashSet<(ast::DefId, ast::Name)> = FnvHashSet::new(); - let object_trait_ref = object_trait.principal_trait_ref_with_self_ty(tcx, tcx.types.err); - for tr in traits::supertraits(tcx, object_trait_ref.clone()) { - check_object_safety_inner(tcx, &tr, span); - - let trait_def = ty::lookup_trait_def(tcx, object_trait_ref.def_id()); - for &associated_type_name in trait_def.associated_type_names.iter() { - associated_types.insert((object_trait_ref.def_id(), associated_type_name)); - } - } - for projection_bound in object_trait.bounds.projection_bounds.iter() { - let pair = (projection_bound.0.projection_ty.trait_ref.def_id, - projection_bound.0.projection_ty.item_name); - associated_types.remove(&pair); + if traits::is_object_safe(tcx, object_trait_ref.clone()) { + return; } - for (trait_def_id, name) in associated_types.into_iter() { - tcx.sess.span_err( - span, - format!("the value of the associated type `{}` (from the trait `{}`) must be specified", - name.user_string(tcx), - ty::item_path_str(tcx, trait_def_id)).as_slice()); - } -} - -fn check_object_safety_inner<'tcx>(tcx: &ty::ctxt<'tcx>, - object_trait: &ty::PolyTraitRef<'tcx>, - span: Span) { - let trait_items = ty::trait_items(tcx, object_trait.def_id()); - - let mut errors = Vec::new(); - for item in trait_items.iter() { - match *item { - ty::MethodTraitItem(ref m) => { - errors.push(check_object_safety_of_method(tcx, object_trait, &**m)) + span_err!(tcx.sess, span, E0038, + "cannot convert to a trait object because trait `{}` is not object-safe", + ty::item_path_str(tcx, object_trait_ref.def_id())); + + let violations = traits::object_safety_violations(tcx, object_trait_ref.clone()); + for violation in violations.into_iter() { + match violation { + ObjectSafetyViolation::SizedSelf => { + tcx.sess.span_note( + span, + "the trait cannot require that `Self : Sized`"); } - ty::TypeTraitItem(_) => {} - } - } - - let mut errors = errors.iter().flat_map(|x| x.iter()).peekable(); - if errors.peek().is_some() { - let trait_name = ty::item_path_str(tcx, object_trait.def_id()); - span_err!(tcx.sess, span, E0038, - "cannot convert to a trait object because trait `{}` is not object-safe", - trait_name); - - for msg in errors { - tcx.sess.note(msg[]); - } - } - /// Returns a vec of error messages. If the vec is empty - no errors! - /// - /// There are some limitations to calling functions through an object, because (a) the self - /// type is not known (that's the whole point of a trait instance, after all, to obscure the - /// self type), (b) the call must go through a vtable and hence cannot be monomorphized and - /// (c) the trait contains static methods which can't be called because we don't know the - /// concrete type. - fn check_object_safety_of_method<'tcx>(tcx: &ty::ctxt<'tcx>, - object_trait: &ty::PolyTraitRef<'tcx>, - method: &ty::Method<'tcx>) - -> Vec<String> { - let mut msgs = Vec::new(); - - let method_name = method.name.repr(tcx); - - match method.explicit_self { - ty::ByValueExplicitSelfCategory => { // reason (a) above - msgs.push(format!("cannot call a method (`{}`) with a by-value \ - receiver through a trait object", method_name)) + ObjectSafetyViolation::Method(method, MethodViolationCode::ByValueSelf) => { + tcx.sess.span_note( + span, + format!("method `{}` has a receiver type of `Self`, \ + which cannot be used with a trait object", + method.name.user_string(tcx)).as_slice()); } - ty::StaticExplicitSelfCategory => { - // Static methods are never object safe (reason (c)). - msgs.push(format!("cannot call a static method (`{}`) \ - through a trait object", - method_name)); - return msgs; + ObjectSafetyViolation::Method(method, MethodViolationCode::StaticMethod) => { + tcx.sess.span_note( + span, + format!("method `{}` has no receiver", + method.name.user_string(tcx)).as_slice()); } - ty::ByReferenceExplicitSelfCategory(..) | - ty::ByBoxExplicitSelfCategory => {} - } - // reason (a) above - let check_for_self_ty = |&: ty| { - if contains_illegal_self_type_reference(tcx, object_trait.def_id(), ty) { - Some(format!( - "cannot call a method (`{}`) whose type contains \ - a self-type (`{}`) through a trait object", - method_name, ty.user_string(tcx))) - } else { - None - } - }; - let ref sig = method.fty.sig; - for &input_ty in sig.0.inputs[1..].iter() { - if let Some(msg) = check_for_self_ty(input_ty) { - msgs.push(msg); - } - } - if let ty::FnConverging(result_type) = sig.0.output { - if let Some(msg) = check_for_self_ty(result_type) { - msgs.push(msg); + ObjectSafetyViolation::Method(method, MethodViolationCode::ReferencesSelf) => { + tcx.sess.span_note( + span, + format!("method `{}` references the `Self` type \ + in its arguments or return type", + method.name.user_string(tcx)).as_slice()); } - } - - if method.generics.has_type_params(FnSpace) { - // reason (b) above - msgs.push(format!("cannot call a generic method (`{}`) through a trait object", - method_name)); - } - - msgs - } - fn contains_illegal_self_type_reference<'tcx>(tcx: &ty::ctxt<'tcx>, - trait_def_id: ast::DefId, - ty: Ty<'tcx>) - -> bool - { - // This is somewhat subtle. In general, we want to forbid - // references to `Self` in the argument and return types, - // since the value of `Self` is erased. However, there is one - // exception: it is ok to reference `Self` in order to access - // an associated type of the current trait, since we retain - // the value of those associated types in the object type - // itself. - // - // ```rust - // trait SuperTrait { - // type X; - // } - // - // trait Trait : SuperTrait { - // type Y; - // fn foo(&self, x: Self) // bad - // fn foo(&self) -> Self // bad - // fn foo(&self) -> Option<Self> // bad - // fn foo(&self) -> Self::Y // OK, desugars to next example - // fn foo(&self) -> <Self as Trait>::Y // OK - // fn foo(&self) -> Self::X // OK, desugars to next example - // fn foo(&self) -> <Self as SuperTrait>::X // OK - // } - // ``` - // - // However, it is not as simple as allowing `Self` in a projected - // type, because there are illegal ways to use `Self` as well: - // - // ```rust - // trait Trait : SuperTrait { - // ... - // fn foo(&self) -> <Self as SomeOtherTrait>::X; - // } - // ``` - // - // Here we will not have the type of `X` recorded in the - // object type, and we cannot resolve `Self as SomeOtherTrait` - // without knowing what `Self` is. - - let mut supertraits: Option<Vec<ty::PolyTraitRef<'tcx>>> = None; - let mut error = false; - ty::maybe_walk_ty(ty, |ty| { - match ty.sty { - ty::ty_param(ref param_ty) => { - if param_ty.space == SelfSpace { - error = true; - } - - false // no contained types to walk - } - - ty::ty_projection(ref data) => { - // This is a projected type `<Foo as SomeTrait>::X`. - - // Compute supertraits of current trait lazilly. - if supertraits.is_none() { - let trait_def = ty::lookup_trait_def(tcx, trait_def_id); - let trait_ref = ty::Binder(trait_def.trait_ref.clone()); - supertraits = Some(traits::supertraits(tcx, trait_ref).collect()); - } - - // Determine whether the trait reference `Foo as - // SomeTrait` is in fact a supertrait of the - // current trait. In that case, this type is - // legal, because the type `X` will be specified - // in the object type. Note that we can just use - // direct equality here because all of these types - // are part of the formal parameter listing, and - // hence there should be no inference variables. - let projection_trait_ref = ty::Binder(data.trait_ref.clone()); - let is_supertrait_of_current_trait = - supertraits.as_ref().unwrap().contains(&projection_trait_ref); - - if is_supertrait_of_current_trait { - false // do not walk contained types, do not report error, do collect $200 - } else { - true // DO walk contained types, POSSIBLY reporting an error - } - } - - _ => true, // walk contained types, if any + ObjectSafetyViolation::Method(method, MethodViolationCode::Generic) => { + tcx.sess.span_note( + span, + format!("method `{}` has generic type parameters", + method.name.user_string(tcx)).as_slice()); } - }); - - error + } } } @@ -392,7 +230,7 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, cause.clone()); } - // Finally, create obligations for the projection predicates. + // Create obligations for the projection predicates. let projection_bounds = object_trait.projection_bounds_with_self_ty(fcx.tcx(), referent_ty); for projection_bound in projection_bounds.iter() { @@ -401,9 +239,47 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, fcx.register_predicate(projection_obligation); } + // Finally, check that there IS a projection predicate for every associated type. + check_object_type_binds_all_associated_types(fcx.tcx(), + span, + object_trait); + object_trait_ref } +fn check_object_type_binds_all_associated_types<'tcx>(tcx: &ty::ctxt<'tcx>, + span: Span, + object_trait: &ty::TyTrait<'tcx>) +{ + let object_trait_ref = + object_trait.principal_trait_ref_with_self_ty(tcx, tcx.types.err); + + let mut associated_types: FnvHashSet<(ast::DefId, ast::Name)> = + traits::supertraits(tcx, object_trait_ref.clone()) + .flat_map(|tr| { + let trait_def = ty::lookup_trait_def(tcx, tr.def_id()); + trait_def.associated_type_names + .clone() + .into_iter() + .map(move |associated_type_name| (tr.def_id(), associated_type_name)) + }) + .collect(); + + for projection_bound in object_trait.bounds.projection_bounds.iter() { + let pair = (projection_bound.0.projection_ty.trait_ref.def_id, + projection_bound.0.projection_ty.item_name); + associated_types.remove(&pair); + } + + for (trait_def_id, name) in associated_types.into_iter() { + tcx.sess.span_err( + span, + format!("the value of the associated type `{}` (from the trait `{}`) must be specified", + name.user_string(tcx), + ty::item_path_str(tcx, trait_def_id)).as_slice()); + } +} + pub fn select_all_fcx_obligations_or_error(fcx: &FnCtxt) { debug!("select_all_fcx_obligations_or_error"); diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index 79443200ddf..1da49799712 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -18,7 +18,7 @@ use syntax::ast; use syntax::ast_util; use syntax::codemap::Span; use syntax::visit; -use util::ppaux::Repr; +use util::ppaux::{Repr, UserString}; pub fn check(tcx: &ty::ctxt) { let mut orphan = OrphanChecker { tcx: tcx }; @@ -57,6 +57,11 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> { ty::ty_trait(ref data) => { self.check_def_id(item.span, data.principal_def_id()); } + ty::ty_uniq(..) => { + self.check_def_id(item.span, + self.tcx.lang_items.owned_box() + .unwrap()); + } _ => { span_err!(self.tcx.sess, item.span, E0118, "no base type found for inherent implementation; \ @@ -67,10 +72,27 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> { ast::ItemImpl(_, _, Some(_), _, _) => { // "Trait" impl debug!("coherence2::orphan check: trait impl {}", item.repr(self.tcx)); - if traits::is_orphan_impl(self.tcx, def_id) { - span_err!(self.tcx.sess, item.span, E0117, - "cannot provide an extension implementation \ - where both trait and type are not defined in this crate"); + match traits::orphan_check(self.tcx, def_id) { + Ok(()) => { } + Err(traits::OrphanCheckErr::NoLocalInputType) => { + span_err!(self.tcx.sess, item.span, E0117, + "cannot provide an extension implementation \ + where both trait and type are not defined in this crate"); + } + Err(traits::OrphanCheckErr::UncoveredTypeParameter(param_ty)) => { + if !self.tcx.sess.features.borrow().old_orphan_check { + self.tcx.sess.span_err( + item.span, + format!("type parameter `{}` must also appear as a type parameter \ + of some type defined within this crate", + param_ty.user_string(self.tcx)).as_slice()); + self.tcx.sess.span_note( + item.span, + format!("for a limited time, you can add \ + `#![feature(old_orphan_check)]` to your crate \ + to disable this rule").as_slice()); + } + } } } _ => { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 9e184db3b84..fe61b3de2cf 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -843,6 +843,7 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let bounds = compute_bounds(ccx, self_param_ty.to_ty(ccx.tcx), bounds.as_slice(), + SizedByDefault::No, it.span); let associated_type_names: Vec<_> = @@ -1098,6 +1099,7 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let bounds = compute_bounds(ccx, assoc_ty, assoc_type_def.bounds.as_slice(), + SizedByDefault::Yes, assoc_type_def.span); ty::predicates(ccx.tcx, assoc_ty, &bounds).into_iter() @@ -1306,6 +1308,7 @@ fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC, let bounds = compute_bounds(this, param_ty.to_ty(this.tcx()), param.bounds[], + SizedByDefault::Yes, param.span); let default = match param.default { None => None, @@ -1342,29 +1345,35 @@ fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC, def } +enum SizedByDefault { Yes, No } + /// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the /// built-in trait (formerly known as kind): Send. fn compute_bounds<'tcx,AC>(this: &AC, param_ty: ty::Ty<'tcx>, ast_bounds: &[ast::TyParamBound], + sized_by_default: SizedByDefault, span: Span) -> ty::ParamBounds<'tcx> - where AC: AstConv<'tcx> { + where AC: AstConv<'tcx> +{ let mut param_bounds = conv_param_bounds(this, span, param_ty, ast_bounds); - add_unsized_bound(this, - &mut param_bounds.builtin_bounds, - ast_bounds, - span); + if let SizedByDefault::Yes = sized_by_default { + add_unsized_bound(this, + &mut param_bounds.builtin_bounds, + ast_bounds, + span); - check_bounds_compatible(this.tcx(), - param_ty, - ¶m_bounds, - span); + check_bounds_compatible(this.tcx(), + param_ty, + ¶m_bounds, + span); + } param_bounds.trait_bounds.sort_by(|a,b| a.def_id().cmp(&b.def_id())); diff --git a/src/librustdoc/flock.rs b/src/librustdoc/flock.rs index a89b20c949b..0f0dbf6a24d 100644 --- a/src/librustdoc/flock.rs +++ b/src/librustdoc/flock.rs @@ -18,10 +18,10 @@ pub use self::imp::Lock; - #[cfg(unix)] mod imp { use libc; + use std::c_str::ToCStr; #[cfg(target_os = "linux")] mod os { diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index 5623c0f0e53..4f277cc868a 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -12,7 +12,7 @@ use clean::*; use std::iter::Extend; use std::mem::{replace, swap}; -pub trait DocFolder { +pub trait DocFolder : Sized { fn fold_item(&mut self, item: Item) -> Option<Item> { self.fold_item_recur(item) } diff --git a/src/librustdoc/html/escape.rs b/src/librustdoc/html/escape.rs index fe93dbbc081..b4afb67170b 100644 --- a/src/librustdoc/html/escape.rs +++ b/src/librustdoc/html/escape.rs @@ -29,7 +29,7 @@ impl<'a> fmt::Show for Escape<'a> { for (i, ch) in s.bytes().enumerate() { match ch as char { '<' | '>' | '&' | '\'' | '"' => { - try!(fmt.write(pile_o_bits.slice(last, i).as_bytes())); + try!(fmt.write_str(pile_o_bits.slice(last, i))); let s = match ch as char { '>' => ">", '<' => "<", @@ -38,7 +38,7 @@ impl<'a> fmt::Show for Escape<'a> { '"' => """, _ => unreachable!() }; - try!(fmt.write(s.as_bytes())); + try!(fmt.write_str(s)); last = i + 1; } _ => {} @@ -46,7 +46,7 @@ impl<'a> fmt::Show for Escape<'a> { } if last < s.len() { - try!(fmt.write(pile_o_bits.slice_from(last).as_bytes())); + try!(fmt.write_str(pile_o_bits.slice_from(last))); } Ok(()) } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 3c09a10f3d9..36619566f8c 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -69,7 +69,7 @@ impl<'a> fmt::Show for TyParamBounds<'a> { let &TyParamBounds(bounds) = self; for (i, bound) in bounds.iter().enumerate() { if i > 0 { - try!(f.write(" + ".as_bytes())); + try!(f.write_str(" + ")); } try!(write!(f, "{}", *bound)); } @@ -80,24 +80,24 @@ impl<'a> fmt::Show for TyParamBounds<'a> { impl fmt::Show for clean::Generics { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if self.lifetimes.len() == 0 && self.type_params.len() == 0 { return Ok(()) } - try!(f.write("<".as_bytes())); + try!(f.write_str("<")); for (i, life) in self.lifetimes.iter().enumerate() { if i > 0 { - try!(f.write(", ".as_bytes())); + try!(f.write_str(", ")); } try!(write!(f, "{}", *life)); } if self.type_params.len() > 0 { if self.lifetimes.len() > 0 { - try!(f.write(", ".as_bytes())); + try!(f.write_str(", ")); } for (i, tp) in self.type_params.iter().enumerate() { if i > 0 { - try!(f.write(", ".as_bytes())) + try!(f.write_str(", ")) } - try!(f.write(tp.name.as_bytes())); + try!(f.write_str(tp.name[])); if tp.bounds.len() > 0 { try!(write!(f, ": {}", TyParamBounds(tp.bounds.as_slice()))); @@ -109,7 +109,7 @@ impl fmt::Show for clean::Generics { }; } } - try!(f.write(">".as_bytes())); + try!(f.write_str(">")); Ok(()) } } @@ -120,10 +120,10 @@ impl<'a> fmt::Show for WhereClause<'a> { if gens.where_predicates.len() == 0 { return Ok(()); } - try!(f.write(" <span class='where'>where ".as_bytes())); + try!(f.write_str(" <span class='where'>where ")); for (i, pred) in gens.where_predicates.iter().enumerate() { if i > 0 { - try!(f.write(", ".as_bytes())); + try!(f.write_str(", ")); } match pred { &clean::WherePredicate::BoundPredicate { ref ty, ref bounds } => { @@ -135,7 +135,7 @@ impl<'a> fmt::Show for WhereClause<'a> { try!(write!(f, "{}: ", lifetime)); for (i, lifetime) in bounds.iter().enumerate() { if i > 0 { - try!(f.write(" + ".as_bytes())); + try!(f.write_str(" + ")); } try!(write!(f, "{}", lifetime)); @@ -146,14 +146,14 @@ impl<'a> fmt::Show for WhereClause<'a> { } } } - try!(f.write("</span>".as_bytes())); + try!(f.write_str("</span>")); Ok(()) } } impl fmt::Show for clean::Lifetime { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(f.write(self.get_ref().as_bytes())); + try!(f.write_str(self.get_ref())); Ok(()) } } @@ -161,14 +161,14 @@ impl fmt::Show for clean::Lifetime { impl fmt::Show for clean::PolyTrait { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if self.lifetimes.len() > 0 { - try!(f.write("for<".as_bytes())); + try!(f.write_str("for<")); for (i, lt) in self.lifetimes.iter().enumerate() { if i > 0 { - try!(f.write(", ".as_bytes())); + try!(f.write_str(", ")); } try!(write!(f, "{}", lt)); } - try!(f.write("> ".as_bytes())); + try!(f.write_str("> ")); } write!(f, "{}", self.trait_) } @@ -196,38 +196,38 @@ impl fmt::Show for clean::PathParameters { match *self { clean::PathParameters::AngleBracketed { ref lifetimes, ref types } => { if lifetimes.len() > 0 || types.len() > 0 { - try!(f.write("<".as_bytes())); + try!(f.write_str("<")); let mut comma = false; for lifetime in lifetimes.iter() { if comma { - try!(f.write(", ".as_bytes())); + try!(f.write_str(", ")); } comma = true; try!(write!(f, "{}", *lifetime)); } for ty in types.iter() { if comma { - try!(f.write(", ".as_bytes())); + try!(f.write_str(", ")); } comma = true; try!(write!(f, "{}", *ty)); } - try!(f.write(">".as_bytes())); + try!(f.write_str(">")); } } clean::PathParameters::Parenthesized { ref inputs, ref output } => { - try!(f.write("(".as_bytes())); + try!(f.write_str("(")); let mut comma = false; for ty in inputs.iter() { if comma { - try!(f.write(", ".as_bytes())); + try!(f.write_str(", ")); } comma = true; try!(write!(f, "{}", *ty)); } - try!(f.write(")".as_bytes())); + try!(f.write_str(")")); if let Some(ref ty) = *output { - try!(f.write(" -> ".as_bytes())); + try!(f.write_str(" -> ")); try!(write!(f, "{}", ty)); } } @@ -238,7 +238,7 @@ impl fmt::Show for clean::PathParameters { impl fmt::Show for clean::PathSegment { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(f.write(self.name.as_bytes())); + try!(f.write_str(self.name.as_slice())); write!(f, "{}", self.params) } } @@ -246,12 +246,12 @@ impl fmt::Show for clean::PathSegment { impl fmt::Show for clean::Path { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if self.global { - try!(f.write("::".as_bytes())) + try!(f.write_str("::")) } for (i, seg) in self.segments.iter().enumerate() { if i > 0 { - try!(f.write("::".as_bytes())) + try!(f.write_str("::")) } try!(write!(f, "{}", seg)); } @@ -433,10 +433,10 @@ impl fmt::Show for clean::Type { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { clean::TyParamBinder(id) => { - f.write(cache().typarams[ast_util::local_def(id)].as_bytes()) + f.write_str(cache().typarams[ast_util::local_def(id)][]) } clean::Generic(ref name) => { - f.write(name.as_bytes()) + f.write_str(name.as_slice()) } clean::ResolvedPath{ did, ref typarams, ref path } => { try!(resolved_path(f, did, path, false)); @@ -522,7 +522,7 @@ impl fmt::Show for clean::Type { primitive_link(f, clean::Slice, format!("[{}, ..{}]", **t, *s).as_slice()) } - clean::Bottom => f.write("!".as_bytes()), + clean::Bottom => f.write_str("!"), clean::RawPointer(m, ref t) => { write!(f, "*{}{}", RawMutableSpace(m), **t) } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 2c05524ea7f..1fce5d59698 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -29,11 +29,12 @@ use libc; use std::ascii::AsciiExt; +use std::c_str::ToCStr; use std::cell::{RefCell, Cell}; +use std::collections::HashMap; use std::fmt; use std::slice; use std::str; -use std::collections::HashMap; use html::toc::TocBuilder; use html::highlight; @@ -302,7 +303,7 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { if ret.is_ok() { let buf = slice::from_raw_buf(&(*ob).data, (*ob).size as uint); - ret = w.write(buf); + ret = w.write_str(str::from_utf8(buf).unwrap()); } hoedown_buffer_free(ob); ret diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index f8a0b88b408..0cfc1042ae6 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -35,6 +35,7 @@ pub use self::ExternalLocation::*; use std::cell::RefCell; +use std::cmp::Ordering::{mod, Less, Greater, Equal}; use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::collections::{HashMap, HashSet}; use std::default::Default; @@ -49,7 +50,6 @@ use std::sync::Arc; use externalfiles::ExternalHtml; use serialize::json; -use serialize::Encodable; use serialize::json::ToJson; use syntax::ast; use syntax::ast_util; @@ -1095,7 +1095,7 @@ impl Context { try!(self.recurse(stability.name.clone(), |this| { let json_dst = &this.dst.join("stability.json"); let mut json_out = BufferedWriter::new(try!(File::create(json_dst))); - try!(stability.encode(&mut json::Encoder::new(&mut json_out))); + try!(write!(&mut json_out, "{}", json::as_json(&stability))); let mut title = stability.name.clone(); title.push_str(" - Stability dashboard"); @@ -1311,7 +1311,8 @@ impl<'a> Item<'a> { // has anchors for the line numbers that we're linking to. if ast_util::is_local(self.item.def_id) { let mut path = Vec::new(); - clean_srcpath(&cx.src_root, self.item.source.filename.as_bytes(), |component| { + clean_srcpath(&cx.src_root, self.item.source.filename.as_bytes(), + |component| { path.push(component.to_string()); }); let href = if self.item.source.loline == self.item.source.hiline { @@ -1713,7 +1714,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, try!(write!(w, ";\n")); } if types.len() > 0 && required.len() > 0 { - try!(w.write("\n".as_bytes())); + try!(w.write_str("\n")); } for m in required.iter() { try!(write!(w, " ")); @@ -1721,7 +1722,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, try!(write!(w, ";\n")); } if required.len() > 0 && provided.len() > 0 { - try!(w.write("\n".as_bytes())); + try!(w.write_str("\n")); } for m in provided.iter() { try!(write!(w, " ")); @@ -1811,6 +1812,18 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, Ok(()) } +fn assoc_type(w: &mut fmt::Formatter, it: &clean::Item, + typ: &clean::TyParam) -> fmt::Result { + try!(write!(w, "type {}", it.name.as_ref().unwrap())); + if typ.bounds.len() > 0 { + try!(write!(w, ": {}", TyParamBounds(&*typ.bounds))) + } + if let Some(ref default) = typ.default { + try!(write!(w, " = {}", default)); + } + Ok(()) +} + fn render_method(w: &mut fmt::Formatter, meth: &clean::Item) -> fmt::Result { fn method(w: &mut fmt::Formatter, it: &clean::Item, unsafety: ast::Unsafety, g: &clean::Generics, selfty: &clean::SelfTy, @@ -1827,17 +1840,6 @@ fn render_method(w: &mut fmt::Formatter, meth: &clean::Item) -> fmt::Result { decl = Method(selfty, d), where_clause = WhereClause(g)) } - fn assoc_type(w: &mut fmt::Formatter, it: &clean::Item, - typ: &clean::TyParam) -> fmt::Result { - try!(write!(w, "type {}", it.name.as_ref().unwrap())); - if typ.bounds.len() > 0 { - try!(write!(w, ": {}", TyParamBounds(&*typ.bounds))) - } - if let Some(ref default) = typ.default { - try!(write!(w, " = {}", default)); - } - Ok(()) - } match meth.inner { clean::TyMethodItem(ref m) => { method(w, meth, m.unsafety, &m.generics, &m.self_, &m.decl) @@ -2122,6 +2124,15 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl) -> fmt::Result { try!(write!(w, "type {} = {}", name, tydef.type_)); try!(write!(w, "</code></h4>\n")); } + clean::AssociatedTypeItem(ref typaram) => { + let name = item.name.as_ref().unwrap(); + try!(write!(w, "<h4 id='assoc_type.{}' class='{}'>{}<code>", + *name, + shortty(item), + ConciseStability(&item.stability))); + try!(assoc_type(w, item, typaram)); + try!(write!(w, "</code></h4>\n")); + } _ => panic!("can't make docs for trait item with name {}", item.name) } match item.doc_value() { @@ -2260,8 +2271,9 @@ impl<'a> fmt::Show for Source<'a> { fn item_macro(w: &mut fmt::Formatter, it: &clean::Item, t: &clean::Macro) -> fmt::Result { - try!(w.write(highlight::highlight(t.source.as_slice(), Some("macro"), - None).as_bytes())); + try!(w.write_str(highlight::highlight(t.source.as_slice(), + Some("macro"), + None)[])); document(w, it) } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index ccdc8164255..1beeeaf629d 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -20,6 +20,7 @@ #![allow(unknown_features)] #![feature(globs, macro_rules, phase, slicing_syntax)] #![feature(unboxed_closures)] +#![feature(old_orphan_check)] extern crate arena; extern crate getopts; @@ -41,7 +42,7 @@ use std::io::File; use std::io; use std::rc::Rc; use externalfiles::ExternalHtml; -use serialize::{Decodable, Encodable}; +use serialize::Decodable; use serialize::json::{mod, Json}; use rustc::session::search_paths::SearchPaths; @@ -493,14 +494,7 @@ fn json_output(krate: clean::Crate, res: Vec<plugins::PluginJson> , // FIXME #8335: yuck, Rust -> str -> JSON round trip! No way to .encode // straight to the Rust JSON representation. - let crate_json_str = { - let mut w = Vec::new(); - { - let mut encoder = json::Encoder::new(&mut w as &mut io::Writer); - krate.encode(&mut encoder).unwrap(); - } - String::from_utf8(w).unwrap() - }; + let crate_json_str = format!("{}", json::as_json(&krate)); let crate_json = match json::from_str(crate_json_str.as_slice()) { Ok(j) => j, Err(e) => panic!("Rust generated JSON is invalid: {}", e) @@ -510,5 +504,5 @@ fn json_output(krate: clean::Crate, res: Vec<plugins::PluginJson> , json.insert("plugins".to_string(), Json::Object(plugins_json)); let mut file = try!(File::create(&dst)); - Json::Object(json).to_writer(&mut file) + write!(&mut file, "{}", Json::Object(json)) } diff --git a/src/librustdoc/stability_summary.rs b/src/librustdoc/stability_summary.rs index 2e3adf8e767..058a7acd455 100644 --- a/src/librustdoc/stability_summary.rs +++ b/src/librustdoc/stability_summary.rs @@ -13,8 +13,9 @@ //! hierarchy, with item counts for every stability level per module. A parent //! module's count includes its children's. -use std::ops::Add; +use std::cmp::Ordering; use std::num::Zero; +use std::ops::Add; use syntax::attr::{Deprecated, Experimental, Unstable, Stable, Frozen, Locked}; use syntax::ast::Public; diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index ba66c51b8fc..743c8b240d1 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -9,14 +9,14 @@ // except according to those terms. use std::cell::RefCell; +use std::sync::mpsc::channel; use std::dynamic_lib::DynamicLibrary; use std::io::{Command, TempDir}; use std::io; use std::os; use std::str; -use std::string::String; -use std::thunk::Thunk; use std::thread::Thread; +use std::thunk::Thunk; use std::collections::{HashSet, HashMap}; use testing; diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index 8a9c2eebf3a..a87044bb3b3 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -76,12 +76,13 @@ //! Create a struct called `TestStruct` and serialize and deserialize it to and from JSON using the //! serialization API, using the derived serialization code. //! -//! ```rust +//! ```notrust +//! // FIXME(#19470): this cannot be ```rust``` because it fails orphan checking at the moment //! extern crate serialize; //! use serialize::json; //! //! // Automatically generate `Decodable` and `Encodable` trait implementations -//! #[deriving(Decodable, Encodable)] +//! #[deriving(RustcDecodable, RustcEncodable)] //! pub struct TestStruct { //! data_int: u8, //! data_str: String, @@ -110,7 +111,8 @@ //! //! ### Simple example of `ToJson` usage //! -//! ```rust +//! ```notrust +//! // FIXME(#19470): this cannot be ```rust``` because it fails orphan checking at the moment //! extern crate serialize; //! use serialize::json::{mod, ToJson, Json}; //! @@ -149,7 +151,8 @@ //! //! ### Verbose example of `ToJson` usage //! -//! ```rust +//! ```notrust +//! // FIXME(#19470): this cannot be ```rust``` because it fails orphan checking at the moment //! extern crate serialize; //! use std::collections::BTreeMap; //! use serialize::json::{mod, Json, ToJson}; @@ -227,6 +230,11 @@ pub enum Json { pub type Array = Vec<Json>; pub type Object = BTreeMap<string::String, Json>; +pub struct PrettyJson<'a> { inner: &'a Json } + +pub struct AsJson<'a, T: 'a> { inner: &'a T } +pub struct AsPrettyJson<'a, T: 'a> { inner: &'a T, indent: Option<uint> } + /// The errors that can arise while parsing a JSON stream. #[deriving(Clone, Copy, PartialEq)] pub enum ErrorCode { @@ -303,9 +311,15 @@ pub fn decode<T: ::Decodable<Decoder, DecoderError>>(s: &str) -> DecodeResult<T> } /// Shortcut function to encode a `T` into a JSON `String` -pub fn encode<'a, T: Encodable<Encoder<'a>, io::IoError>>(object: &T) -> string::String { - let buff = Encoder::buffer_encode(object); - string::String::from_utf8(buff).unwrap() +pub fn encode<T>(object: &T) -> string::String + where T: for<'a> Encodable<Encoder<'a>, fmt::Error> +{ + let mut s = String::new(); + { + let mut encoder = Encoder::new(&mut s); + let _ = object.encode(&mut encoder); + } + s } impl fmt::Show for ErrorCode { @@ -323,16 +337,16 @@ impl std::error::Error for DecoderError { fn detail(&self) -> Option<std::string::String> { Some(self.to_string()) } } -pub type EncodeResult = io::IoResult<()>; +pub type EncodeResult = fmt::Result; pub type DecodeResult<T> = Result<T, DecoderError>; -pub fn escape_bytes(wr: &mut io::Writer, bytes: &[u8]) -> Result<(), io::IoError> { +fn escape_str(wr: &mut fmt::Writer, v: &str) -> fmt::Result { try!(wr.write_str("\"")); let mut start = 0; - for (i, byte) in bytes.iter().enumerate() { - let escaped = match *byte { + for (i, byte) in v.bytes().enumerate() { + let escaped = match byte { b'"' => "\\\"", b'\\' => "\\\\", b'\x00' => "\\u0000", @@ -372,7 +386,7 @@ pub fn escape_bytes(wr: &mut io::Writer, bytes: &[u8]) -> Result<(), io::IoError }; if start < i { - try!(wr.write(bytes[start..i])); + try!(wr.write_str(v[start..i])); } try!(wr.write_str(escaped)); @@ -380,34 +394,30 @@ pub fn escape_bytes(wr: &mut io::Writer, bytes: &[u8]) -> Result<(), io::IoError start = i + 1; } - if start != bytes.len() { - try!(wr.write(bytes[start..])); + if start != v.len() { + try!(wr.write_str(v[start..])); } wr.write_str("\"") } -fn escape_str(writer: &mut io::Writer, v: &str) -> Result<(), io::IoError> { - escape_bytes(writer, v.as_bytes()) -} - -fn escape_char(writer: &mut io::Writer, v: char) -> Result<(), io::IoError> { +fn escape_char(writer: &mut fmt::Writer, v: char) -> fmt::Result { let mut buf = [0; 4]; - let len = v.encode_utf8(&mut buf).unwrap(); - escape_bytes(writer, buf[mut ..len]) + let n = v.encode_utf8(&mut buf).unwrap(); + let buf = unsafe { str::from_utf8_unchecked(buf[0..n]) }; + escape_str(writer, buf) } -fn spaces(wr: &mut io::Writer, mut n: uint) -> Result<(), io::IoError> { - const LEN: uint = 16; - static BUF: [u8; LEN] = [b' '; LEN]; +fn spaces(wr: &mut fmt::Writer, mut n: uint) -> fmt::Result { + const BUF: &'static str = " "; - while n >= LEN { - try!(wr.write(&BUF)); - n -= LEN; + while n >= BUF.len() { + try!(wr.write_str(BUF)); + n -= BUF.len(); } if n > 0 { - wr.write(BUF[..n]) + wr.write_str(BUF[..n]) } else { Ok(()) } @@ -423,31 +433,18 @@ fn fmt_number_or_null(v: f64) -> string::String { /// A structure for implementing serialization to JSON. pub struct Encoder<'a> { - writer: &'a mut (io::Writer+'a), + writer: &'a mut (fmt::Writer+'a), } impl<'a> Encoder<'a> { /// Creates a new JSON encoder whose output will be written to the writer /// specified. - pub fn new(writer: &'a mut io::Writer) -> Encoder<'a> { + pub fn new(writer: &'a mut fmt::Writer) -> Encoder<'a> { Encoder { writer: writer } } - - /// Encode the specified struct into a json [u8] - pub fn buffer_encode<T: Encodable<Encoder<'a>, io::IoError>>(object: &T) -> Vec<u8> { - //Serialize the object in a string using a writer - let mut m = Vec::new(); - // FIXME(14302) remove the transmute and unsafe block. - unsafe { - let mut encoder = Encoder::new(&mut m as &mut io::Writer); - // Vec<u8> never Errs - let _ = object.encode(transmute(&mut encoder)); - } - m - } } -impl<'a> ::Encoder<io::IoError> for Encoder<'a> { +impl<'a> ::Encoder<fmt::Error> for Encoder<'a> { fn emit_nil(&mut self) -> EncodeResult { write!(self.writer, "null") } fn emit_uint(&mut self, v: uint) -> EncodeResult { write!(self.writer, "{}", v) } @@ -646,14 +643,14 @@ impl<'a> ::Encoder<io::IoError> for Encoder<'a> { /// Another encoder for JSON, but prints out human-readable JSON instead of /// compact data pub struct PrettyEncoder<'a> { - writer: &'a mut (io::Writer+'a), + writer: &'a mut (fmt::Writer+'a), curr_indent: uint, indent: uint, } impl<'a> PrettyEncoder<'a> { /// Creates a new encoder whose output will be written to the specified writer - pub fn new(writer: &'a mut io::Writer) -> PrettyEncoder<'a> { + pub fn new(writer: &'a mut fmt::Writer) -> PrettyEncoder<'a> { PrettyEncoder { writer: writer, curr_indent: 0, indent: 2, } } @@ -667,7 +664,7 @@ impl<'a> PrettyEncoder<'a> { } } -impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> { +impl<'a> ::Encoder<fmt::Error> for PrettyEncoder<'a> { fn emit_nil(&mut self) -> EncodeResult { write!(self.writer, "null") } fn emit_uint(&mut self, v: uint) -> EncodeResult { write!(self.writer, "{}", v) } @@ -927,25 +924,23 @@ impl<E: ::Encoder<S>, S> Encodable<E, S> for Json { } } -impl Json { - /// Encodes a json value into an io::writer. Uses a single line. - pub fn to_writer(&self, writer: &mut io::Writer) -> EncodeResult { - let mut encoder = Encoder::new(writer); - self.encode(&mut encoder) - } +/// Create an `AsJson` wrapper which can be used to print a value as JSON +/// on-the-fly via `write!` +pub fn as_json<T>(t: &T) -> AsJson<T> { + AsJson { inner: t } +} - /// Encodes a json value into an io::writer. - /// Pretty-prints in a more readable format. - pub fn to_pretty_writer(&self, writer: &mut io::Writer) -> EncodeResult { - let mut encoder = PrettyEncoder::new(writer); - self.encode(&mut encoder) - } +/// Create an `AsPrettyJson` wrapper which can be used to print a value as JSON +/// on-the-fly via `write!` +pub fn as_pretty_json<T>(t: &T) -> AsPrettyJson<T> { + AsPrettyJson { inner: t, indent: None } +} - /// Encodes a json value into a string - pub fn to_pretty_str(&self) -> string::String { - let mut s = Vec::new(); - self.to_pretty_writer(&mut s as &mut io::Writer).unwrap(); - string::String::from_utf8(s).unwrap() +impl Json { + /// Borrow this json object as a pretty object to generate a pretty + /// representation for it via `Show`. + pub fn pretty(&self) -> PrettyJson { + PrettyJson { inner: self } } /// If the Json value is an Object, returns the value associated with the provided key. @@ -2424,10 +2419,65 @@ impl<A:ToJson> ToJson for Option<A> { } } +struct FormatShim<'a, 'b: 'a> { + inner: &'a mut fmt::Formatter<'b>, +} + +impl<'a, 'b> fmt::Writer for FormatShim<'a, 'b> { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.inner.write_str(s) + } +} + impl fmt::Show for Json { /// Encodes a json value into a string fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.to_writer(f).map_err(|_| fmt::Error) + let mut shim = FormatShim { inner: f }; + let mut encoder = Encoder::new(&mut shim); + self.encode(&mut encoder) + } +} + +impl<'a> fmt::Show for PrettyJson<'a> { + /// Encodes a json value into a string + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut shim = FormatShim { inner: f }; + let mut encoder = PrettyEncoder::new(&mut shim); + self.inner.encode(&mut encoder) + } +} + +impl<'a, T> fmt::Show for AsJson<'a, T> + where T: for<'b> Encodable<Encoder<'b>, fmt::Error> +{ + /// Encodes a json value into a string + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut shim = FormatShim { inner: f }; + let mut encoder = Encoder::new(&mut shim); + self.inner.encode(&mut encoder) + } +} + +impl<'a, T> AsPrettyJson<'a, T> { + /// Set the indentation level for the emitted JSON + pub fn indent(mut self, indent: uint) -> AsPrettyJson<'a, T> { + self.indent = Some(indent); + self + } +} + +impl<'a, T> fmt::Show for AsPrettyJson<'a, T> + where T: for<'b> Encodable<PrettyEncoder<'b>, fmt::Error> +{ + /// Encodes a json value into a string + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut shim = FormatShim { inner: f }; + let mut encoder = PrettyEncoder::new(&mut shim); + match self.indent { + Some(n) => encoder.set_indent(n), + None => {} + } + self.inner.encode(&mut encoder) } } @@ -2450,9 +2500,9 @@ mod tests { use super::DecoderError::*; use super::JsonEvent::*; use super::StackElement::*; - use super::{PrettyEncoder, Json, from_str, DecodeResult, DecoderError, JsonEvent, Parser, - StackElement, Stack, Encoder, Decoder}; - use std::{i64, u64, f32, f64, io}; + use super::{Json, from_str, DecodeResult, DecoderError, JsonEvent, Parser, + StackElement, Stack, Decoder}; + use std::{i64, u64, f32, f64}; use std::collections::BTreeMap; use std::num::Float; use std::string; @@ -2523,74 +2573,74 @@ mod tests { #[test] fn test_write_null() { assert_eq!(Null.to_string(), "null"); - assert_eq!(Null.to_pretty_str(), "null"); + assert_eq!(Null.pretty().to_string(), "null"); } #[test] fn test_write_i64() { assert_eq!(U64(0).to_string(), "0"); - assert_eq!(U64(0).to_pretty_str(), "0"); + assert_eq!(U64(0).pretty().to_string(), "0"); assert_eq!(U64(1234).to_string(), "1234"); - assert_eq!(U64(1234).to_pretty_str(), "1234"); + assert_eq!(U64(1234).pretty().to_string(), "1234"); assert_eq!(I64(-5678).to_string(), "-5678"); - assert_eq!(I64(-5678).to_pretty_str(), "-5678"); + assert_eq!(I64(-5678).pretty().to_string(), "-5678"); assert_eq!(U64(7650007200025252000).to_string(), "7650007200025252000"); - assert_eq!(U64(7650007200025252000).to_pretty_str(), "7650007200025252000"); + assert_eq!(U64(7650007200025252000).pretty().to_string(), "7650007200025252000"); } #[test] fn test_write_f64() { assert_eq!(F64(3.0).to_string(), "3.0"); - assert_eq!(F64(3.0).to_pretty_str(), "3.0"); + assert_eq!(F64(3.0).pretty().to_string(), "3.0"); assert_eq!(F64(3.1).to_string(), "3.1"); - assert_eq!(F64(3.1).to_pretty_str(), "3.1"); + assert_eq!(F64(3.1).pretty().to_string(), "3.1"); assert_eq!(F64(-1.5).to_string(), "-1.5"); - assert_eq!(F64(-1.5).to_pretty_str(), "-1.5"); + assert_eq!(F64(-1.5).pretty().to_string(), "-1.5"); assert_eq!(F64(0.5).to_string(), "0.5"); - assert_eq!(F64(0.5).to_pretty_str(), "0.5"); + assert_eq!(F64(0.5).pretty().to_string(), "0.5"); assert_eq!(F64(f64::NAN).to_string(), "null"); - assert_eq!(F64(f64::NAN).to_pretty_str(), "null"); + assert_eq!(F64(f64::NAN).pretty().to_string(), "null"); assert_eq!(F64(f64::INFINITY).to_string(), "null"); - assert_eq!(F64(f64::INFINITY).to_pretty_str(), "null"); + assert_eq!(F64(f64::INFINITY).pretty().to_string(), "null"); assert_eq!(F64(f64::NEG_INFINITY).to_string(), "null"); - assert_eq!(F64(f64::NEG_INFINITY).to_pretty_str(), "null"); + assert_eq!(F64(f64::NEG_INFINITY).pretty().to_string(), "null"); } #[test] fn test_write_str() { assert_eq!(String("".to_string()).to_string(), "\"\""); - assert_eq!(String("".to_string()).to_pretty_str(), "\"\""); + assert_eq!(String("".to_string()).pretty().to_string(), "\"\""); assert_eq!(String("homura".to_string()).to_string(), "\"homura\""); - assert_eq!(String("madoka".to_string()).to_pretty_str(), "\"madoka\""); + assert_eq!(String("madoka".to_string()).pretty().to_string(), "\"madoka\""); } #[test] fn test_write_bool() { assert_eq!(Boolean(true).to_string(), "true"); - assert_eq!(Boolean(true).to_pretty_str(), "true"); + assert_eq!(Boolean(true).pretty().to_string(), "true"); assert_eq!(Boolean(false).to_string(), "false"); - assert_eq!(Boolean(false).to_pretty_str(), "false"); + assert_eq!(Boolean(false).pretty().to_string(), "false"); } #[test] fn test_write_array() { assert_eq!(Array(vec![]).to_string(), "[]"); - assert_eq!(Array(vec![]).to_pretty_str(), "[]"); + assert_eq!(Array(vec![]).pretty().to_string(), "[]"); assert_eq!(Array(vec![Boolean(true)]).to_string(), "[true]"); assert_eq!( - Array(vec![Boolean(true)]).to_pretty_str(), + Array(vec![Boolean(true)]).pretty().to_string(), "\ [\n \ true\n\ @@ -2605,7 +2655,7 @@ mod tests { assert_eq!(long_test_array.to_string(), "[false,null,[\"foo\\nbar\",3.5]]"); assert_eq!( - long_test_array.to_pretty_str(), + long_test_array.pretty().to_string(), "\ [\n \ false,\n \ @@ -2621,7 +2671,7 @@ mod tests { #[test] fn test_write_object() { assert_eq!(mk_object(&[]).to_string(), "{}"); - assert_eq!(mk_object(&[]).to_pretty_str(), "{}"); + assert_eq!(mk_object(&[]).pretty().to_string(), "{}"); assert_eq!( mk_object(&[ @@ -2630,7 +2680,7 @@ mod tests { "{\"a\":true}" ); assert_eq!( - mk_object(&[("a".to_string(), Boolean(true))]).to_pretty_str(), + mk_object(&[("a".to_string(), Boolean(true))]).pretty().to_string(), "\ {\n \ \"a\": true\n\ @@ -2654,7 +2704,7 @@ mod tests { }" ); assert_eq!( - complex_obj.to_pretty_str(), + complex_obj.pretty().to_string(), "\ {\n \ \"b\": [\n \ @@ -2678,48 +2728,29 @@ mod tests { // We can't compare the strings directly because the object fields be // printed in a different order. - assert_eq!(a.clone(), from_str(a.to_string().as_slice()).unwrap()); - assert_eq!(a.clone(), - from_str(a.to_pretty_str().as_slice()).unwrap()); - } - - fn with_str_writer<F>(f: F) -> string::String where F: FnOnce(&mut io::Writer){ - let mut m = Vec::new(); - f(&mut m as &mut io::Writer); - string::String::from_utf8(m).unwrap() + assert_eq!(a.clone(), a.to_string().parse().unwrap()); + assert_eq!(a.clone(), a.pretty().to_string().parse().unwrap()); } #[test] fn test_write_enum() { let animal = Dog; assert_eq!( - with_str_writer(|writer| { - let mut encoder = Encoder::new(writer); - animal.encode(&mut encoder).unwrap(); - }), + format!("{}", super::as_json(&animal)), "\"Dog\"" ); assert_eq!( - with_str_writer(|writer| { - let mut encoder = PrettyEncoder::new(writer); - animal.encode(&mut encoder).unwrap(); - }), + format!("{}", super::as_pretty_json(&animal)), "\"Dog\"" ); let animal = Frog("Henry".to_string(), 349); assert_eq!( - with_str_writer(|writer| { - let mut encoder = Encoder::new(writer); - animal.encode(&mut encoder).unwrap(); - }), + format!("{}", super::as_json(&animal)), "{\"variant\":\"Frog\",\"fields\":[\"Henry\",349]}" ); assert_eq!( - with_str_writer(|writer| { - let mut encoder = PrettyEncoder::new(writer); - animal.encode(&mut encoder).unwrap(); - }), + format!("{}", super::as_pretty_json(&animal)), "{\n \ \"variant\": \"Frog\",\n \ \"fields\": [\n \ @@ -2732,16 +2763,10 @@ mod tests { macro_rules! check_encoder_for_simple { ($value:expr, $expected:expr) => ({ - let s = with_str_writer(|writer| { - let mut encoder = Encoder::new(writer); - $value.encode(&mut encoder).unwrap(); - }); + let s = format!("{}", super::as_json(&$value)); assert_eq!(s, $expected); - let s = with_str_writer(|writer| { - let mut encoder = PrettyEncoder::new(writer); - $value.encode(&mut encoder).unwrap(); - }); + let s = format!("{}", super::as_pretty_json(&$value)); assert_eq!(s, $expected); }) } @@ -3320,10 +3345,7 @@ mod tests { let mut hm: HashMap<uint, bool> = HashMap::new(); hm.insert(1, true); let mut mem_buf = Vec::new(); - { - let mut encoder = Encoder::new(&mut mem_buf as &mut io::Writer); - hm.encode(&mut encoder).unwrap(); - } + write!(&mut mem_buf, "{}", super::as_pretty_json(&hm)).unwrap(); let json_str = from_utf8(mem_buf[]).unwrap(); match from_str(json_str) { Err(_) => panic!("Unable to parse json_str: {}", json_str), @@ -3339,10 +3361,7 @@ mod tests { let mut hm: HashMap<uint, bool> = HashMap::new(); hm.insert(1, true); let mut mem_buf = Vec::new(); - { - let mut encoder = PrettyEncoder::new(&mut mem_buf as &mut io::Writer); - hm.encode(&mut encoder).unwrap() - } + write!(&mut mem_buf, "{}", super::as_pretty_json(&hm)).unwrap(); let json_str = from_utf8(mem_buf[]).unwrap(); match from_str(json_str) { Err(_) => panic!("Unable to parse json_str: {}", json_str), @@ -3373,18 +3392,15 @@ mod tests { // Helper function for counting indents fn indents(source: &str) -> uint { - let trimmed = source.trim_left_chars(' '); + let trimmed = source.trim_left_matches(' '); source.len() - trimmed.len() } // Test up to 4 spaces of indents (more?) for i in range(0, 4u) { let mut writer = Vec::new(); - { - let ref mut encoder = PrettyEncoder::new(&mut writer); - encoder.set_indent(i); - json.encode(encoder).unwrap(); - } + write!(&mut writer, "{}", + super::as_pretty_json(&json).indent(i)).unwrap(); let printed = from_utf8(writer[]).unwrap(); diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index 2c2b7313a7b..857a7072009 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -315,8 +315,8 @@ static ASCII_UPPERCASE_MAP: [u8; 256] = [ #[cfg(test)] mod tests { + use prelude::v1::*; use super::*; - use prelude::*; use char::from_u32; #[test] diff --git a/src/libstd/bitflags.rs b/src/libstd/bitflags.rs index aeb4df402a2..c07531d3f32 100644 --- a/src/libstd/bitflags.rs +++ b/src/libstd/bitflags.rs @@ -209,7 +209,7 @@ macro_rules! bitflags { } } - impl BitOr<$BitFlags, $BitFlags> for $BitFlags { + impl ::std::ops::BitOr<$BitFlags, $BitFlags> for $BitFlags { /// Returns the union of the two sets of flags. #[inline] fn bitor(self, other: $BitFlags) -> $BitFlags { @@ -217,7 +217,7 @@ macro_rules! bitflags { } } - impl BitXor<$BitFlags, $BitFlags> for $BitFlags { + impl ::std::ops::BitXor<$BitFlags, $BitFlags> for $BitFlags { /// Returns the left flags, but with all the right flags toggled. #[inline] fn bitxor(self, other: $BitFlags) -> $BitFlags { @@ -225,7 +225,7 @@ macro_rules! bitflags { } } - impl BitAnd<$BitFlags, $BitFlags> for $BitFlags { + impl ::std::ops::BitAnd<$BitFlags, $BitFlags> for $BitFlags { /// Returns the intersection between the two sets of flags. #[inline] fn bitand(self, other: $BitFlags) -> $BitFlags { @@ -233,7 +233,7 @@ macro_rules! bitflags { } } - impl Sub<$BitFlags, $BitFlags> for $BitFlags { + impl ::std::ops::Sub<$BitFlags, $BitFlags> for $BitFlags { /// Returns the set difference of the two sets of flags. #[inline] fn sub(self, other: $BitFlags) -> $BitFlags { @@ -241,7 +241,7 @@ macro_rules! bitflags { } } - impl Not<$BitFlags> for $BitFlags { + impl ::std::ops::Not<$BitFlags> for $BitFlags { /// Returns the complement of this set of flags. #[inline] fn not(self) -> $BitFlags { @@ -266,7 +266,6 @@ macro_rules! bitflags { mod tests { use hash; use option::Option::{Some, None}; - use ops::{BitOr, BitAnd, BitXor, Sub, Not}; bitflags! { #[doc = "> The first principle is that you must not fool yourself — and"] diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs index 46498610e56..b1433ad7fdc 100644 --- a/src/libstd/c_str.rs +++ b/src/libstd/c_str.rs @@ -45,6 +45,8 @@ //! ```rust //! extern crate libc; //! +//! use std::c_str::ToCStr; +//! //! extern { //! fn puts(s: *const libc::c_char); //! } @@ -70,6 +72,7 @@ use core::prelude::*; use libc; +use cmp::Ordering; use fmt; use hash; use mem; @@ -155,6 +158,8 @@ impl CString { /// one). /// /// ```rust + /// use std::c_str::ToCStr; + /// /// let foo = "some string"; /// /// // right @@ -170,6 +175,8 @@ impl CString { /// ```rust /// extern crate libc; /// + /// use std::c_str::ToCStr; + /// /// fn main() { /// let c_str = "foo bar".to_c_str(); /// unsafe { @@ -189,6 +196,8 @@ impl CString { /// one). /// /// ```rust + /// use std::c_str::ToCStr; + /// /// let foo = "some string"; /// /// // right @@ -309,6 +318,8 @@ pub trait ToCStr for Sized? { /// ```rust /// extern crate libc; /// + /// use std::c_str::ToCStr; + /// /// fn main() { /// let s = "PATH".with_c_str(|path| unsafe { /// libc::getenv(path) @@ -538,9 +549,8 @@ pub unsafe fn from_c_multistring<F>(buf: *const libc::c_char, #[cfg(test)] mod tests { + use prelude::v1::*; use super::*; - use prelude::{spawn, Some, None, Option, FnOnce, ToString, CloneSliceExt}; - use prelude::{Clone, PtrExt, Iterator, SliceExt, StrExt}; use ptr; use thread::Thread; use libc; @@ -613,7 +623,7 @@ mod tests { #[test] fn test_unwrap() { let c_str = "hello".to_c_str(); - unsafe { libc::free(c_str.unwrap() as *mut libc::c_void) } + unsafe { libc::free(c_str.into_inner() as *mut libc::c_void) } } #[test] @@ -732,9 +742,10 @@ mod tests { mod bench { extern crate test; + use prelude::v1::*; use self::test::Bencher; use libc; - use prelude::*; + use c_str::ToCStr; #[inline] fn check(s: &str, c_str: *const libc::c_char) { diff --git a/src/libstd/c_vec.rs b/src/libstd/c_vec.rs index 0aa51ee66ed..40942f1b987 100644 --- a/src/libstd/c_vec.rs +++ b/src/libstd/c_vec.rs @@ -172,7 +172,7 @@ impl<T> AsSlice<T> for CVec<T> { #[cfg(test)] mod tests { - use prelude::*; + use prelude::v1::*; use super::CVec; use libc; @@ -228,7 +228,7 @@ mod tests { let cv = CVec::new_with_dtor(1 as *mut int, 0, move|:| panic!("Don't run this destructor!")); - let p = cv.unwrap(); + let p = cv.into_inner(); assert_eq!(p, 1 as *mut int); } } diff --git a/src/libstd/collections/hash/bench.rs b/src/libstd/collections/hash/bench.rs index 87aebb24f98..28689767cb0 100644 --- a/src/libstd/collections/hash/bench.rs +++ b/src/libstd/collections/hash/bench.rs @@ -11,7 +11,7 @@ #![cfg(test)] extern crate test; -use prelude::*; +use prelude::v1::*; use self::test::Bencher; use iter::{range_inclusive}; diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index f6063df5434..d4fc4150fae 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -87,7 +87,7 @@ impl DefaultResizePolicy { #[test] fn test_resize_policy() { - use prelude::*; + use prelude::v1::*; let rp = DefaultResizePolicy; for n in range(0u, 1000) { assert!(rp.min_capacity(rp.usable_capacity(n)) <= n); @@ -311,7 +311,7 @@ fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F) -> SearchResult<K, V, M> where - M: Deref<RawTable<K, V>>, + M: Deref<Target=RawTable<K, V>>, F: FnMut(&K) -> bool, { let size = table.size(); @@ -1530,8 +1530,9 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> Extend<(K, V)> for HashMap<K #[cfg(test)] mod test_map { - use prelude::*; + use prelude::v1::*; + use cmp::Equiv; use super::HashMap; use super::Entry::{Occupied, Vacant}; use hash; @@ -1541,6 +1542,7 @@ mod test_map { struct KindaIntLike(int); + #[allow(deprecated)] impl Equiv<int> for KindaIntLike { fn equiv(&self, other: &int) -> bool { let KindaIntLike(this) = *self; @@ -1868,7 +1870,7 @@ mod test_map { } #[test] - #[allow(experimental)] + #[allow(deprecated)] fn test_pop_equiv() { let mut m = HashMap::new(); m.insert(1i, 2i); diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 74fb63a7a9e..6132d288da2 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -866,7 +866,7 @@ impl<'a, T, S, H> Iterator<&'a T> for Union<'a, T, H> #[cfg(test)] mod test_set { - use prelude::*; + use prelude::v1::*; use super::HashSet; diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index 6938ab9b0b6..a687ba3da8d 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -210,7 +210,7 @@ impl<K, V, M> Bucket<K, V, M> { } } -impl<K, V, M: Deref<RawTable<K, V>>> Bucket<K, V, M> { +impl<K, V, M: Deref<Target=RawTable<K, V>>> Bucket<K, V, M> { pub fn new(table: M, hash: SafeHash) -> Bucket<K, V, M> { Bucket::at_index(table, hash.inspect() as uint) } @@ -279,7 +279,7 @@ impl<K, V, M: Deref<RawTable<K, V>>> Bucket<K, V, M> { } } -impl<K, V, M: Deref<RawTable<K, V>>> EmptyBucket<K, V, M> { +impl<K, V, M: Deref<Target=RawTable<K, V>>> EmptyBucket<K, V, M> { #[inline] pub fn next(self) -> Bucket<K, V, M> { let mut bucket = self.into_bucket(); @@ -315,7 +315,7 @@ impl<K, V, M: Deref<RawTable<K, V>>> EmptyBucket<K, V, M> { } } -impl<K, V, M: DerefMut<RawTable<K, V>>> EmptyBucket<K, V, M> { +impl<K, V, M: Deref<Target=RawTable<K, V>> + DerefMut> EmptyBucket<K, V, M> { /// Puts given key and value pair, along with the key's hash, /// into this bucket in the hashtable. Note how `self` is 'moved' into /// this function, because this slot will no longer be empty when @@ -337,7 +337,7 @@ impl<K, V, M: DerefMut<RawTable<K, V>>> EmptyBucket<K, V, M> { } } -impl<K, V, M: Deref<RawTable<K, V>>> FullBucket<K, V, M> { +impl<K, V, M: Deref<Target=RawTable<K, V>>> FullBucket<K, V, M> { #[inline] pub fn next(self) -> Bucket<K, V, M> { let mut bucket = self.into_bucket(); @@ -384,7 +384,7 @@ impl<K, V, M: Deref<RawTable<K, V>>> FullBucket<K, V, M> { } } -impl<K, V, M: DerefMut<RawTable<K, V>>> FullBucket<K, V, M> { +impl<K, V, M: Deref<Target=RawTable<K, V>> + DerefMut> FullBucket<K, V, M> { /// Removes this bucket's key and value from the hashtable. /// /// This works similarly to `put`, building an `EmptyBucket` out of the @@ -428,7 +428,7 @@ impl<K, V, M: DerefMut<RawTable<K, V>>> FullBucket<K, V, M> { } } -impl<'t, K, V, M: Deref<RawTable<K, V>> + 't> FullBucket<K, V, M> { +impl<'t, K, V, M: Deref<Target=RawTable<K, V>> + 't> FullBucket<K, V, M> { /// Exchange a bucket state for immutable references into the table. /// Because the underlying reference to the table is also consumed, /// no further changes to the structure of the table are possible; @@ -442,7 +442,7 @@ impl<'t, K, V, M: Deref<RawTable<K, V>> + 't> FullBucket<K, V, M> { } } -impl<'t, K, V, M: DerefMut<RawTable<K, V>> + 't> FullBucket<K, V, M> { +impl<'t, K, V, M: Deref<Target=RawTable<K, V>> + DerefMut + 't> FullBucket<K, V, M> { /// This works similarly to `into_refs`, exchanging a bucket state /// for mutable references into the table. pub fn into_mut_refs(self) -> (&'t mut K, &'t mut V) { @@ -463,7 +463,7 @@ impl<K, V, M> BucketState<K, V, M> { } } -impl<K, V, M: Deref<RawTable<K, V>>> GapThenFull<K, V, M> { +impl<K, V, M: Deref<Target=RawTable<K, V>>> GapThenFull<K, V, M> { #[inline] pub fn full(&self) -> &FullBucket<K, V, M> { &self.full diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs index 368abe7cb12..ecfe2d15ae1 100644 --- a/src/libstd/dynamic_lib.rs +++ b/src/libstd/dynamic_lib.rs @@ -15,7 +15,9 @@ #![experimental] #![allow(missing_docs)] -use prelude::*; +use prelude::v1::*; + +use c_str::ToCStr; use mem; use os; use str; @@ -146,7 +148,7 @@ impl DynamicLibrary { #[cfg(all(test, not(target_os = "ios")))] mod test { use super::*; - use prelude::*; + use prelude::v1::*; use libc; use mem; @@ -202,8 +204,8 @@ mod test { pub mod dl { use self::Rtld::*; - use prelude::*; - use c_str::CString; + use prelude::v1::*; + use c_str::{CString, ToCStr}; use libc; use ptr; diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 9a46a500a4b..32e1922ae74 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -78,7 +78,7 @@ //! } //! ``` -use prelude::*; +use prelude::v1::*; use str::Utf8Error; use string::{FromUtf8Error, FromUtf16Error}; diff --git a/src/libstd/failure.rs b/src/libstd/failure.rs index 7010eae6dba..d3bcdbf1a53 100644 --- a/src/libstd/failure.rs +++ b/src/libstd/failure.rs @@ -10,11 +10,10 @@ #![experimental] -use prelude::*; +use prelude::v1::*; use any::{Any, AnyRefExt}; use cell::RefCell; -use fmt; use io::IoResult; use rt::{backtrace, unwind}; use rt::util::{Stderr, Stdio}; @@ -29,10 +28,7 @@ thread_local! { impl Writer for Stdio { fn write(&mut self, bytes: &[u8]) -> IoResult<()> { - fn fmt_write<F: fmt::FormatWriter>(f: &mut F, bytes: &[u8]) { - let _ = f.write(bytes); - } - fmt_write(self, bytes); + let _ = self.write_bytes(bytes); Ok(()) } } diff --git a/src/libstd/fmt.rs b/src/libstd/fmt.rs index 957dd54a037..32f5f2d4536 100644 --- a/src/libstd/fmt.rs +++ b/src/libstd/fmt.rs @@ -201,7 +201,7 @@ //! // for details, and the function `pad` can be used to pad strings. //! let decimals = f.precision().unwrap_or(3); //! let string = f64::to_str_exact(magnitude, decimals); -//! f.pad_integral(true, "", string.as_bytes()) +//! f.pad_integral(true, "", string.as_slice()) //! } //! } //! @@ -390,13 +390,9 @@ #![experimental] -use io::Writer; -use io; -use result::Result::{Ok, Err}; use string; -use vec::Vec; -pub use core::fmt::{Formatter, Result, FormatWriter, rt}; +pub use core::fmt::{Formatter, Result, Writer, rt}; pub use core::fmt::{Show, Octal, Binary}; pub use core::fmt::{LowerHex, UpperHex, Pointer}; pub use core::fmt::{LowerExp, UpperExp}; @@ -424,16 +420,7 @@ pub use core::fmt::{argument, argumentuint}; #[experimental = "this is an implementation detail of format! and should not \ be called directly"] pub fn format(args: Arguments) -> string::String { - let mut output = Vec::new(); - let _ = write!(&mut output as &mut Writer, "{}", args); - string::String::from_utf8(output).unwrap() -} - -impl<'a> Writer for Formatter<'a> { - fn write(&mut self, b: &[u8]) -> io::IoResult<()> { - match (*self).write(b) { - Ok(()) => Ok(()), - Err(Error) => Err(io::standard_error(io::OtherIoError)) - } - } + let mut output = string::String::new(); + let _ = write!(&mut output, "{}", args); + output } diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index c5405601048..852cab500f6 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -22,7 +22,6 @@ use result::Result::{Ok, Err}; use slice::{SliceExt}; use slice; use vec::Vec; -use kinds::{Send,Sync}; /// Wraps a Reader and buffers input from it /// @@ -52,11 +51,6 @@ pub struct BufferedReader<R> { cap: uint, } - -unsafe impl<R: Send> Send for BufferedReader<R> {} -unsafe impl<R: Send+Sync> Sync for BufferedReader<R> {} - - impl<R: Reader> BufferedReader<R> { /// Creates a new `BufferedReader` with the specified buffer capacity pub fn with_capacity(cap: uint, inner: R) -> BufferedReader<R> { @@ -410,7 +404,7 @@ impl<S: Stream> Writer for BufferedStream<S> { mod test { extern crate test; use io; - use prelude::*; + use prelude::v1::*; use super::*; use super::super::{IoResult, EndOfFile}; use super::super::mem::MemReader; @@ -534,7 +528,7 @@ mod test { w.write(&[0, 1]).unwrap(); let a: &[_] = &[]; assert_eq!(a, w.get_ref()[]); - let w = w.unwrap(); + let w = w.into_inner(); let a: &[_] = &[0, 1]; assert_eq!(a, w[]); } diff --git a/src/libstd/io/comm_adapters.rs b/src/libstd/io/comm_adapters.rs index 077f75e2edd..f47f6237b72 100644 --- a/src/libstd/io/comm_adapters.rs +++ b/src/libstd/io/comm_adapters.rs @@ -10,11 +10,11 @@ use clone::Clone; use cmp; -use comm::{Sender, Receiver}; +use sync::mpsc::{Sender, Receiver}; use io; use option::Option::{None, Some}; use result::Result::{Ok, Err}; -use slice::{bytes, CloneSliceExt, SliceExt}; +use slice::{bytes, SliceExt}; use super::{Buffer, Reader, Writer, IoResult}; use vec::Vec; @@ -23,6 +23,7 @@ use vec::Vec; /// # Example /// /// ``` +/// use std::sync::mpsc::channel; /// use std::io::ChanReader; /// /// let (tx, rx) = channel(); @@ -58,11 +59,11 @@ impl Buffer for ChanReader { fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]> { if self.pos >= self.buf.len() { self.pos = 0; - match self.rx.recv_opt() { + match self.rx.recv() { Ok(bytes) => { self.buf = bytes; }, - Err(()) => { + Err(..) => { self.closed = true; self.buf = Vec::new(); } @@ -114,6 +115,7 @@ impl Reader for ChanReader { /// /// ``` /// # #![allow(unused_must_use)] +/// use std::sync::mpsc::channel; /// use std::io::ChanWriter; /// /// let (tx, rx) = channel(); @@ -141,7 +143,7 @@ impl Clone for ChanWriter { impl Writer for ChanWriter { fn write(&mut self, buf: &[u8]) -> IoResult<()> { - self.tx.send_opt(buf.to_vec()).map_err(|_| { + self.tx.send(buf.to_vec()).map_err(|_| { io::IoError { kind: io::BrokenPipe, desc: "Pipe closed", @@ -154,7 +156,9 @@ impl Writer for ChanWriter { #[cfg(test)] mod test { - use prelude::*; + use prelude::v1::*; + + use sync::mpsc::channel; use super::*; use io; use thread::Thread; @@ -163,11 +167,11 @@ mod test { fn test_rx_reader() { let (tx, rx) = channel(); Thread::spawn(move|| { - tx.send(vec![1u8, 2u8]); - tx.send(vec![]); - tx.send(vec![3u8, 4u8]); - tx.send(vec![5u8, 6u8]); - tx.send(vec![7u8, 8u8]); + tx.send(vec![1u8, 2u8]).unwrap(); + tx.send(vec![]).unwrap(); + tx.send(vec![3u8, 4u8]).unwrap(); + tx.send(vec![5u8, 6u8]).unwrap(); + tx.send(vec![7u8, 8u8]).unwrap(); }).detach(); let mut reader = ChanReader::new(rx); @@ -205,12 +209,12 @@ mod test { fn test_rx_buffer() { let (tx, rx) = channel(); Thread::spawn(move|| { - tx.send(b"he".to_vec()); - tx.send(b"llo wo".to_vec()); - tx.send(b"".to_vec()); - tx.send(b"rld\nhow ".to_vec()); - tx.send(b"are you?".to_vec()); - tx.send(b"".to_vec()); + tx.send(b"he".to_vec()).unwrap(); + tx.send(b"llo wo".to_vec()).unwrap(); + tx.send(b"".to_vec()).unwrap(); + tx.send(b"rld\nhow ".to_vec()).unwrap(); + tx.send(b"are you?".to_vec()).unwrap(); + tx.send(b"".to_vec()).unwrap(); }).detach(); let mut reader = ChanReader::new(rx); @@ -230,7 +234,7 @@ mod test { writer.write_be_u32(42).unwrap(); let wanted = vec![0u8, 0u8, 0u8, 42u8]; - let got = match Thread::spawn(move|| { rx.recv() }).join() { + let got = match Thread::spawn(move|| { rx.recv().unwrap() }).join() { Ok(got) => got, Err(_) => panic!(), }; diff --git a/src/libstd/io/extensions.rs b/src/libstd/io/extensions.rs index 51e09e547e3..94dba1f7cc7 100644 --- a/src/libstd/io/extensions.rs +++ b/src/libstd/io/extensions.rs @@ -175,7 +175,7 @@ pub fn u64_from_be_bytes(data: &[u8], start: uint, size: uint) -> u64 { #[cfg(test)] mod test { - use prelude::*; + use prelude::v1::*; use io; use io::{MemReader, BytesReader}; @@ -507,7 +507,7 @@ mod test { mod bench { extern crate test; - use prelude::*; + use prelude::v1::*; use self::test::Bencher; // why is this a macro? wouldn't an inlined function work just as well? diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs index 7fa6ebc6e3b..7fa5b3cfac7 100644 --- a/src/libstd/io/fs.rs +++ b/src/libstd/io/fs.rs @@ -819,7 +819,7 @@ fn access_string(access: FileAccess) -> &'static str { #[allow(unused_variables)] #[allow(unused_mut)] mod test { - use prelude::*; + use prelude::v1::*; use io::{SeekSet, SeekCur, SeekEnd, Read, Open, ReadWrite, FileType}; use io; use str; diff --git a/src/libstd/io/mem.rs b/src/libstd/io/mem.rs index f8ea373f8f4..ad921e43c0c 100644 --- a/src/libstd/io/mem.rs +++ b/src/libstd/io/mem.rs @@ -399,9 +399,10 @@ impl<'a> Buffer for BufReader<'a> { #[cfg(test)] mod test { extern crate "test" as test_crate; + use prelude::v1::*; + use super::*; - use io::{SeekSet, SeekCur, SeekEnd, Reader, Writer, Seek}; - use prelude::{Ok, Err, range, Vec, Buffer, AsSlice, SliceExt, IteratorExt, CloneSliceExt}; + use io::{SeekSet, SeekCur, SeekEnd}; use io; use self::test_crate::Bencher; diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index e8b852ee492..0a7815aeb53 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -232,8 +232,9 @@ use error::{FromError, Error}; use fmt; use int; use iter::{Iterator, IteratorExt}; +use kinds::Sized; use mem::transmute; -use ops::{BitOr, BitXor, BitAnd, Sub, Not, FnOnce}; +use ops::FnOnce; use option::Option; use option::Option::{Some, None}; use os; @@ -1028,16 +1029,30 @@ pub trait Writer { /// /// This function will return any I/O error reported while formatting. fn write_fmt(&mut self, fmt: fmt::Arguments) -> IoResult<()> { - // Create a shim which translates a Writer to a FormatWriter and saves + // Create a shim which translates a Writer to a fmt::Writer and saves // off I/O errors. instead of discarding them - struct Adaptor<'a, T:'a> { + struct Adaptor<'a, Sized? T:'a> { inner: &'a mut T, error: IoResult<()>, } - impl<'a, T: Writer> fmt::FormatWriter for Adaptor<'a, T> { - fn write(&mut self, bytes: &[u8]) -> fmt::Result { - match self.inner.write(bytes) { + #[cfg(not(stage0))] + impl<'a, Sized? T: Writer> fmt::Writer for Adaptor<'a, T> { + fn write_str(&mut self, s: &str) -> fmt::Result { + match self.inner.write(s.as_bytes()) { + Ok(()) => Ok(()), + Err(e) => { + self.error = Err(e); + Err(fmt::Error) + } + } + } + } + + #[cfg(stage0)] + impl<'a, T: Writer> fmt::Writer for Adaptor<'a, T> { + fn write_str(&mut self, s: &str) -> fmt::Result { + match self.inner.write(s.as_bytes()) { Ok(()) => Ok(()), Err(e) => { self.error = Err(e); @@ -1629,16 +1644,24 @@ pub trait Acceptor<T> { /// `Some`. The `Some` contains the `IoResult` representing whether the /// connection attempt was successful. A successful connection will be wrapped /// in `Ok`. A failed connection is represented as an `Err`. -pub struct IncomingConnections<'a, A:'a> { +pub struct IncomingConnections<'a, Sized? A:'a> { inc: &'a mut A, } +#[cfg(stage0)] impl<'a, T, A: Acceptor<T>> Iterator<IoResult<T>> for IncomingConnections<'a, A> { fn next(&mut self) -> Option<IoResult<T>> { Some(self.inc.accept()) } } +#[cfg(not(stage0))] +impl<'a, T, Sized? A: Acceptor<T>> Iterator<IoResult<T>> for IncomingConnections<'a, A> { + fn next(&mut self) -> Option<IoResult<T>> { + Some(self.inc.accept()) + } +} + /// Creates a standard error for a commonly used flavor of error. The `detail` /// field of the returned error will always be `None`. /// @@ -1919,7 +1942,7 @@ impl fmt::Show for FilePermission { mod tests { use self::BadReaderBehavior::*; use super::{IoResult, Reader, MemReader, NoProgress, InvalidInput, Writer}; - use prelude::{Ok, Vec, Buffer, CloneSliceExt}; + use prelude::v1::{Ok, Vec, Buffer, SliceExt}; use uint; #[deriving(Clone, PartialEq, Show)] diff --git a/src/libstd/io/net/addrinfo.rs b/src/libstd/io/net/addrinfo.rs index e8fbb121181..d86cb841f96 100644 --- a/src/libstd/io/net/addrinfo.rs +++ b/src/libstd/io/net/addrinfo.rs @@ -112,7 +112,7 @@ fn lookup(hostname: Option<&str>, servname: Option<&str>, hint: Option<Hint>) // permission without help of apk #[cfg(all(test, not(target_os = "android")))] mod test { - use prelude::*; + use prelude::v1::*; use super::*; use io::net::ip::*; diff --git a/src/libstd/io/net/ip.rs b/src/libstd/io/net/ip.rs index 49ab9ddb924..2a18b839778 100644 --- a/src/libstd/io/net/ip.rs +++ b/src/libstd/io/net/ip.rs @@ -25,7 +25,7 @@ use ops::FnOnce; use option::Option; use option::Option::{None, Some}; use result::Result::{Ok, Err}; -use slice::{CloneSliceExt, SliceExt}; +use slice::SliceExt; use str::{FromStr, StrExt}; use vec::Vec; @@ -544,7 +544,7 @@ impl<'a> ToSocketAddr for &'a str { #[cfg(test)] mod test { - use prelude::*; + use prelude::v1::*; use super::*; use str::FromStr; diff --git a/src/libstd/io/net/pipe.rs b/src/libstd/io/net/pipe.rs index 6ce66c3273b..daefdd28b30 100644 --- a/src/libstd/io/net/pipe.rs +++ b/src/libstd/io/net/pipe.rs @@ -20,14 +20,14 @@ #![allow(missing_docs)] -use prelude::*; +use prelude::v1::*; +use c_str::ToCStr; use io::{Listener, Acceptor, IoResult, TimedOut, standard_error}; -use time::Duration; - -use sys::pipe::UnixStream as UnixStreamImp; -use sys::pipe::UnixListener as UnixListenerImp; use sys::pipe::UnixAcceptor as UnixAcceptorImp; +use sys::pipe::UnixListener as UnixListenerImp; +use sys::pipe::UnixStream as UnixStreamImp; +use time::Duration; use sys_common; @@ -264,13 +264,17 @@ impl sys_common::AsInner<UnixAcceptorImp> for UnixAcceptor { } #[cfg(test)] -#[allow(experimental)] mod tests { - use super::*; - use io::*; - use io::test::*; - use prelude::{Ok, Err, spawn, range, drop, Some, None, channel, Send, FnOnce, Clone}; + use prelude::v1::*; + use io::fs::PathExtensions; + use io::{EndOfFile, TimedOut, ShortWrite, IoError, ConnectionReset}; + use io::{NotConnected, BrokenPipe, FileNotFound, InvalidInput, OtherIoError}; + use io::{PermissionDenied, Acceptor, Listener}; + use io::test::*; + use super::*; + use sync::mpsc::channel; + use thread::Thread; use time::Duration; pub fn smalltest<F,G>(server: F, client: G) @@ -282,7 +286,7 @@ mod tests { let mut acceptor = UnixListener::bind(&path1).listen(); - spawn(move|| { + let _t = Thread::spawn(move|| { match UnixStream::connect(&path2) { Ok(c) => client(c), Err(e) => panic!("failed connect: {}", e), @@ -377,7 +381,7 @@ mod tests { Err(e) => panic!("failed listen: {}", e), }; - spawn(move|| { + let _t = Thread::spawn(move|| { for _ in range(0u, times) { let mut stream = UnixStream::connect(&path2); match stream.write(&[100]) { @@ -411,7 +415,7 @@ mod tests { let addr = next_test_unix(); let mut acceptor = UnixListener::bind(&addr).listen(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut s = UnixStream::connect(&addr); let mut buf = [0, 0]; debug!("client reading"); @@ -427,20 +431,20 @@ mod tests { let (tx1, rx1) = channel(); let (tx2, rx2) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut s2 = s2; - rx1.recv(); + rx1.recv().unwrap(); debug!("writer writing"); s2.write(&[1]).unwrap(); debug!("writer done"); - tx2.send(()); + tx2.send(()).unwrap(); }); - tx1.send(()); + tx1.send(()).unwrap(); let mut buf = [0, 0]; debug!("reader reading"); assert_eq!(s1.read(&mut buf), Ok(1)); debug!("reader done"); - rx2.recv(); + rx2.recv().unwrap(); } #[test] @@ -450,30 +454,30 @@ mod tests { let (tx1, rx) = channel(); let tx2 = tx1.clone(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut s = UnixStream::connect(&addr); s.write(&[1]).unwrap(); - rx.recv(); + rx.recv().unwrap(); s.write(&[2]).unwrap(); - rx.recv(); + rx.recv().unwrap(); }); let mut s1 = acceptor.accept().unwrap(); let s2 = s1.clone(); let (done, rx) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut s2 = s2; let mut buf = [0, 0]; s2.read(&mut buf).unwrap(); - tx2.send(()); - done.send(()); + tx2.send(()).unwrap(); + done.send(()).unwrap(); }); let mut buf = [0, 0]; s1.read(&mut buf).unwrap(); - tx1.send(()); + tx1.send(()).unwrap(); - rx.recv(); + rx.recv().unwrap(); } #[test] @@ -481,7 +485,7 @@ mod tests { let addr = next_test_unix(); let mut acceptor = UnixListener::bind(&addr).listen(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut s = UnixStream::connect(&addr); let buf = &mut [0, 1]; s.read(buf).unwrap(); @@ -492,14 +496,14 @@ mod tests { let s2 = s1.clone(); let (tx, rx) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut s2 = s2; s2.write(&[1]).unwrap(); - tx.send(()); + tx.send(()).unwrap(); }); s1.write(&[2]).unwrap(); - rx.recv(); + rx.recv().unwrap(); } #[cfg(not(windows))] @@ -539,10 +543,10 @@ mod tests { // continue to receive any pending connections. let (tx, rx) = channel(); let addr2 = addr.clone(); - spawn(move|| { - tx.send(UnixStream::connect(&addr2).unwrap()); + let _t = Thread::spawn(move|| { + tx.send(UnixStream::connect(&addr2).unwrap()).unwrap(); }); - let l = rx.recv(); + let l = rx.recv().unwrap(); for i in range(0u, 1001) { match a.accept() { Ok(..) => break, @@ -557,7 +561,7 @@ mod tests { // Unset the timeout and make sure that this always blocks. a.set_timeout(None); let addr2 = addr.clone(); - spawn(move|| { + let _t = Thread::spawn(move|| { drop(UnixStream::connect(&addr2).unwrap()); }); a.accept().unwrap(); @@ -595,11 +599,11 @@ mod tests { let addr = next_test_unix(); let a = UnixListener::bind(&addr).listen().unwrap(); let (_tx, rx) = channel::<()>(); - spawn(move|| { + Thread::spawn(move|| { let mut a = a; let _s = a.accept().unwrap(); - let _ = rx.recv_opt(); - }); + let _ = rx.recv(); + }).detach(); let mut b = [0]; let mut s = UnixStream::connect(&addr).unwrap(); @@ -632,25 +636,25 @@ mod tests { let addr = next_test_unix(); let a = UnixListener::bind(&addr).listen().unwrap(); let (_tx, rx) = channel::<()>(); - spawn(move|| { + Thread::spawn(move|| { let mut a = a; let _s = a.accept().unwrap(); - let _ = rx.recv_opt(); - }); + let _ = rx.recv(); + }).detach(); let mut s = UnixStream::connect(&addr).unwrap(); let s2 = s.clone(); let (tx, rx) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut s2 = s2; assert!(s2.read(&mut [0]).is_err()); - tx.send(()); + tx.send(()).unwrap(); }); // this should wake up the child task s.close_read().unwrap(); // this test will never finish if the child doesn't wake up - rx.recv(); + rx.recv().unwrap(); } #[test] @@ -658,12 +662,12 @@ mod tests { let addr = next_test_unix(); let mut a = UnixListener::bind(&addr).listen().unwrap(); let (tx, rx) = channel::<()>(); - spawn(move|| { + Thread::spawn(move|| { let mut s = UnixStream::connect(&addr).unwrap(); - rx.recv(); + rx.recv().unwrap(); assert!(s.write(&[0]).is_ok()); - let _ = rx.recv_opt(); - }); + let _ = rx.recv(); + }).detach(); let mut s = a.accept().unwrap(); s.set_timeout(Some(20)); @@ -686,7 +690,7 @@ mod tests { assert_eq!(s.write(&[0]).err().unwrap().kind, TimedOut); } - tx.send(()); + tx.send(()).unwrap(); s.set_timeout(None); assert_eq!(s.read(&mut [0, 0]), Ok(1)); } @@ -696,9 +700,9 @@ mod tests { let addr = next_test_unix(); let mut a = UnixListener::bind(&addr).listen().unwrap(); let (tx, rx) = channel::<()>(); - spawn(move|| { + Thread::spawn(move|| { let mut s = UnixStream::connect(&addr).unwrap(); - rx.recv(); + rx.recv().unwrap(); let mut amt = 0; while amt < 100 * 128 * 1024 { match s.read(&mut [0;128 * 1024]) { @@ -706,15 +710,15 @@ mod tests { Err(e) => panic!("{}", e), } } - let _ = rx.recv_opt(); - }); + let _ = rx.recv(); + }).detach(); let mut s = a.accept().unwrap(); s.set_read_timeout(Some(20)); assert_eq!(s.read(&mut [0]).err().unwrap().kind, TimedOut); assert_eq!(s.read(&mut [0]).err().unwrap().kind, TimedOut); - tx.send(()); + tx.send(()).unwrap(); for _ in range(0u, 100) { assert!(s.write(&[0;128 * 1024]).is_ok()); } @@ -725,12 +729,12 @@ mod tests { let addr = next_test_unix(); let mut a = UnixListener::bind(&addr).listen().unwrap(); let (tx, rx) = channel::<()>(); - spawn(move|| { + Thread::spawn(move|| { let mut s = UnixStream::connect(&addr).unwrap(); - rx.recv(); + rx.recv().unwrap(); assert!(s.write(&[0]).is_ok()); - let _ = rx.recv_opt(); - }); + let _ = rx.recv(); + }).detach(); let mut s = a.accept().unwrap(); s.set_write_timeout(Some(20)); @@ -743,7 +747,7 @@ mod tests { if i == 1000 { panic!("should have filled up?!"); } } - tx.send(()); + tx.send(()).unwrap(); assert!(s.read(&mut [0]).is_ok()); } @@ -752,27 +756,27 @@ mod tests { let addr = next_test_unix(); let mut a = UnixListener::bind(&addr).listen().unwrap(); let (tx, rx) = channel::<()>(); - spawn(move|| { + Thread::spawn(move|| { let mut s = UnixStream::connect(&addr).unwrap(); - rx.recv(); + rx.recv().unwrap(); assert!(s.write(&[0]).is_ok()); - let _ = rx.recv_opt(); - }); + let _ = rx.recv(); + }).detach(); let mut s = a.accept().unwrap(); let s2 = s.clone(); let (tx2, rx2) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut s2 = s2; assert!(s2.read(&mut [0]).is_ok()); - tx2.send(()); + tx2.send(()).unwrap(); }); s.set_read_timeout(Some(20)); assert_eq!(s.read(&mut [0]).err().unwrap().kind, TimedOut); - tx.send(()); + tx.send(()).unwrap(); - rx2.recv(); + rx2.recv().unwrap(); } #[cfg(not(windows))] @@ -784,10 +788,10 @@ mod tests { let mut a2 = a.clone(); let addr2 = addr.clone(); - spawn(move|| { + let _t = Thread::spawn(move|| { let _ = UnixStream::connect(&addr2); }); - spawn(move|| { + let _t = Thread::spawn(move|| { let _ = UnixStream::connect(&addr); }); @@ -807,19 +811,25 @@ mod tests { let (tx, rx) = channel(); let tx2 = tx.clone(); - spawn(move|| { let mut a = a; tx.send(a.accept()) }); - spawn(move|| { let mut a = a2; tx2.send(a.accept()) }); + let _t = Thread::spawn(move|| { + let mut a = a; + tx.send(a.accept()).unwrap() + }); + let _t = Thread::spawn(move|| { + let mut a = a2; + tx2.send(a.accept()).unwrap() + }); let addr2 = addr.clone(); - spawn(move|| { + let _t = Thread::spawn(move|| { let _ = UnixStream::connect(&addr2); }); - spawn(move|| { + let _t = Thread::spawn(move|| { let _ = UnixStream::connect(&addr); }); - assert!(rx.recv().is_ok()); - assert!(rx.recv().is_ok()); + assert!(rx.recv().unwrap().is_ok()); + assert!(rx.recv().unwrap().is_ok()); } #[test] @@ -840,12 +850,12 @@ mod tests { let mut a2 = a.clone(); let (tx, rx) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut a = a; - tx.send(a.accept()); + tx.send(a.accept()).unwrap(); }); a2.close_accept().unwrap(); - assert_eq!(rx.recv().err().unwrap().kind, EndOfFile); + assert_eq!(rx.recv().unwrap().err().unwrap().kind, EndOfFile); } } diff --git a/src/libstd/io/net/tcp.rs b/src/libstd/io/net/tcp.rs index 826f492d85d..3e59aaa05ef 100644 --- a/src/libstd/io/net/tcp.rs +++ b/src/libstd/io/net/tcp.rs @@ -141,7 +141,7 @@ impl TcpStream { /// let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap(); /// let stream2 = stream.clone(); /// - /// Thread::spawn(move|| { + /// let _t = Thread::spawn(move|| { /// // close this stream after one second /// timer::sleep(Duration::seconds(1)); /// let mut stream = stream2; @@ -282,10 +282,10 @@ impl sys_common::AsInner<TcpStreamImp> for TcpStream { /// use std::io::{Acceptor, Listener}; /// use std::thread::Thread; /// -/// let listener = TcpListener::bind("127.0.0.1:80"); +/// let listener = TcpListener::bind("127.0.0.1:80").unwrap(); /// /// // bind the listener to the specified address -/// let mut acceptor = listener.listen(); +/// let mut acceptor = listener.listen().unwrap(); /// /// fn handle_client(mut stream: TcpStream) { /// // ... @@ -423,7 +423,7 @@ impl TcpAcceptor { /// let mut a = TcpListener::bind("127.0.0.1:8482").listen().unwrap(); /// let a2 = a.clone(); /// - /// Thread::spawn(move|| { + /// let _t = Thread::spawn(move|| { /// let mut a2 = a2; /// for socket in a2.incoming() { /// match socket { @@ -482,14 +482,17 @@ impl sys_common::AsInner<TcpAcceptorImp> for TcpAcceptor { #[cfg(test)] #[allow(experimental)] mod test { + use prelude::v1::*; + + use sync::mpsc::channel; + use thread::Thread; use io::net::tcp::*; use io::net::ip::*; - use io::{EndOfFile, TimedOut, IoError, ShortWrite, OtherIoError, ConnectionAborted}; - use io::{ConnectionRefused, ConnectionReset, BrokenPipe, NotConnected}; - use io::{PermissionDenied, Listener, Acceptor}; use io::test::*; - use prelude::{Ok, Err, spawn, range, drop, Some, None, channel, Clone}; - use prelude::{Reader, Writer, IteratorExt}; + use io::{EndOfFile, TimedOut, ShortWrite, IoError}; + use io::{ConnectionRefused, BrokenPipe, ConnectionAborted}; + use io::{ConnectionReset, NotConnected, PermissionDenied, OtherIoError}; + use io::{Acceptor, Listener}; // FIXME #11530 this fails on android because tests are run as root #[cfg_attr(any(windows, target_os = "android"), ignore)] @@ -515,7 +518,7 @@ mod test { let listener = TcpListener::bind(socket_addr); let mut acceptor = listener.listen(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut stream = TcpStream::connect(("localhost", socket_addr.port)); stream.write(&[144]).unwrap(); }); @@ -531,7 +534,7 @@ mod test { let addr = next_test_ip4(); let mut acceptor = TcpListener::bind(addr).listen(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut stream = TcpStream::connect(("localhost", addr.port)); stream.write(&[64]).unwrap(); }); @@ -547,7 +550,7 @@ mod test { let addr = next_test_ip4(); let mut acceptor = TcpListener::bind(addr).listen(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut stream = TcpStream::connect(("127.0.0.1", addr.port)); stream.write(&[44]).unwrap(); }); @@ -563,7 +566,7 @@ mod test { let addr = next_test_ip6(); let mut acceptor = TcpListener::bind(addr).listen(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut stream = TcpStream::connect(("::1", addr.port)); stream.write(&[66]).unwrap(); }); @@ -579,7 +582,7 @@ mod test { let addr = next_test_ip4(); let mut acceptor = TcpListener::bind(addr).listen(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut stream = TcpStream::connect(addr); stream.write(&[99]).unwrap(); }); @@ -595,7 +598,7 @@ mod test { let addr = next_test_ip6(); let mut acceptor = TcpListener::bind(addr).listen(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut stream = TcpStream::connect(addr); stream.write(&[99]).unwrap(); }); @@ -611,7 +614,7 @@ mod test { let addr = next_test_ip4(); let mut acceptor = TcpListener::bind(addr).listen(); - spawn(move|| { + let _t = Thread::spawn(move|| { let _stream = TcpStream::connect(addr); // Close }); @@ -627,7 +630,7 @@ mod test { let addr = next_test_ip6(); let mut acceptor = TcpListener::bind(addr).listen(); - spawn(move|| { + let _t = Thread::spawn(move|| { let _stream = TcpStream::connect(addr); // Close }); @@ -643,7 +646,7 @@ mod test { let addr = next_test_ip4(); let mut acceptor = TcpListener::bind(addr).listen(); - spawn(move|| { + let _t = Thread::spawn(move|| { let _stream = TcpStream::connect(addr); // Close }); @@ -667,7 +670,7 @@ mod test { let addr = next_test_ip6(); let mut acceptor = TcpListener::bind(addr).listen(); - spawn(move|| { + let _t = Thread::spawn(move|| { let _stream = TcpStream::connect(addr); // Close }); @@ -692,13 +695,13 @@ mod test { let mut acceptor = TcpListener::bind(addr).listen(); let (tx, rx) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { drop(TcpStream::connect(addr)); - tx.send(()); + tx.send(()).unwrap(); }); let mut stream = acceptor.accept(); - rx.recv(); + rx.recv().unwrap(); let buf = [0]; match stream.write(&buf) { Ok(..) => {} @@ -717,13 +720,13 @@ mod test { let mut acceptor = TcpListener::bind(addr).listen(); let (tx, rx) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { drop(TcpStream::connect(addr)); - tx.send(()); + tx.send(()).unwrap(); }); let mut stream = acceptor.accept(); - rx.recv(); + rx.recv().unwrap(); let buf = [0]; match stream.write(&buf) { Ok(..) => {} @@ -742,7 +745,7 @@ mod test { let max = 10u; let mut acceptor = TcpListener::bind(addr).listen(); - spawn(move|| { + let _t = Thread::spawn(move|| { for _ in range(0, max) { let mut stream = TcpStream::connect(addr); stream.write(&[99]).unwrap(); @@ -762,7 +765,7 @@ mod test { let max = 10u; let mut acceptor = TcpListener::bind(addr).listen(); - spawn(move|| { + let _t = Thread::spawn(move|| { for _ in range(0, max) { let mut stream = TcpStream::connect(addr); stream.write(&[99]).unwrap(); @@ -782,11 +785,11 @@ mod test { static MAX: int = 10; let acceptor = TcpListener::bind(addr).listen(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut acceptor = acceptor; for (i, stream) in acceptor.incoming().enumerate().take(MAX as uint) { // Start another task to handle the connection - spawn(move|| { + let _t = Thread::spawn(move|| { let mut stream = stream; let mut buf = [0]; stream.read(&mut buf).unwrap(); @@ -801,7 +804,7 @@ mod test { fn connect(i: int, addr: SocketAddr) { if i == MAX { return } - spawn(move|| { + let _t = Thread::spawn(move|| { debug!("connecting"); let mut stream = TcpStream::connect(addr); // Connect again before writing @@ -818,11 +821,11 @@ mod test { static MAX: int = 10; let acceptor = TcpListener::bind(addr).listen(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut acceptor = acceptor; for (i, stream) in acceptor.incoming().enumerate().take(MAX as uint) { // Start another task to handle the connection - spawn(move|| { + let _t = Thread::spawn(move|| { let mut stream = stream; let mut buf = [0]; stream.read(&mut buf).unwrap(); @@ -837,7 +840,7 @@ mod test { fn connect(i: int, addr: SocketAddr) { if i == MAX { return } - spawn(move|| { + let _t = Thread::spawn(move|| { debug!("connecting"); let mut stream = TcpStream::connect(addr); // Connect again before writing @@ -854,11 +857,11 @@ mod test { let addr = next_test_ip4(); let acceptor = TcpListener::bind(addr).listen(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut acceptor = acceptor; for stream in acceptor.incoming().take(MAX as uint) { // Start another task to handle the connection - spawn(move|| { + let _t = Thread::spawn(move|| { let mut stream = stream; let mut buf = [0]; stream.read(&mut buf).unwrap(); @@ -873,7 +876,7 @@ mod test { fn connect(i: int, addr: SocketAddr) { if i == MAX { return } - spawn(move|| { + let _t = Thread::spawn(move|| { debug!("connecting"); let mut stream = TcpStream::connect(addr); // Connect again before writing @@ -890,11 +893,11 @@ mod test { let addr = next_test_ip6(); let acceptor = TcpListener::bind(addr).listen(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut acceptor = acceptor; for stream in acceptor.incoming().take(MAX as uint) { // Start another task to handle the connection - spawn(move|| { + let _t = Thread::spawn(move|| { let mut stream = stream; let mut buf = [0]; stream.read(&mut buf).unwrap(); @@ -909,7 +912,7 @@ mod test { fn connect(i: int, addr: SocketAddr) { if i == MAX { return } - spawn(move|| { + let _t = Thread::spawn(move|| { debug!("connecting"); let mut stream = TcpStream::connect(addr); // Connect again before writing @@ -932,7 +935,7 @@ mod test { pub fn peer_name(addr: SocketAddr) { let acceptor = TcpListener::bind(addr).listen(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut acceptor = acceptor; acceptor.accept().unwrap(); }); @@ -967,22 +970,22 @@ mod test { fn partial_read() { let addr = next_test_ip4(); let (tx, rx) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut srv = TcpListener::bind(addr).listen().unwrap(); - tx.send(()); + tx.send(()).unwrap(); let mut cl = srv.accept().unwrap(); cl.write(&[10]).unwrap(); let mut b = [0]; cl.read(&mut b).unwrap(); - tx.send(()); + tx.send(()).unwrap(); }); - rx.recv(); + rx.recv().unwrap(); let mut c = TcpStream::connect(addr).unwrap(); let mut b = [0; 10]; assert_eq!(c.read(&mut b), Ok(1)); c.write(&[1]).unwrap(); - rx.recv(); + rx.recv().unwrap(); } #[test] @@ -1004,20 +1007,20 @@ mod test { let addr = next_test_ip4(); let (tx, rx) = channel(); - spawn(move|| { - rx.recv(); + let _t = Thread::spawn(move|| { + rx.recv().unwrap(); let _stream = TcpStream::connect(addr).unwrap(); // Close - rx.recv(); + rx.recv().unwrap(); }); { let mut acceptor = TcpListener::bind(addr).listen(); - tx.send(()); + tx.send(()).unwrap(); { let _stream = acceptor.accept().unwrap(); // Close client - tx.send(()); + tx.send(()).unwrap(); } // Close listener } @@ -1029,7 +1032,7 @@ mod test { let addr = next_test_ip4(); let mut acceptor = TcpListener::bind(addr).listen(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut s = TcpStream::connect(addr); let mut buf = [0, 0]; assert_eq!(s.read(&mut buf), Ok(1)); @@ -1042,16 +1045,16 @@ mod test { let (tx1, rx1) = channel(); let (tx2, rx2) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut s2 = s2; - rx1.recv(); + rx1.recv().unwrap(); s2.write(&[1]).unwrap(); - tx2.send(()); + tx2.send(()).unwrap(); }); - tx1.send(()); + tx1.send(()).unwrap(); let mut buf = [0, 0]; assert_eq!(s1.read(&mut buf), Ok(1)); - rx2.recv(); + rx2.recv().unwrap(); } #[test] @@ -1061,30 +1064,30 @@ mod test { let (tx1, rx) = channel(); let tx2 = tx1.clone(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut s = TcpStream::connect(addr); s.write(&[1]).unwrap(); - rx.recv(); + rx.recv().unwrap(); s.write(&[2]).unwrap(); - rx.recv(); + rx.recv().unwrap(); }); let mut s1 = acceptor.accept().unwrap(); let s2 = s1.clone(); let (done, rx) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut s2 = s2; let mut buf = [0, 0]; s2.read(&mut buf).unwrap(); - tx2.send(()); - done.send(()); + tx2.send(()).unwrap(); + done.send(()).unwrap(); }); let mut buf = [0, 0]; s1.read(&mut buf).unwrap(); - tx1.send(()); + tx1.send(()).unwrap(); - rx.recv(); + rx.recv().unwrap(); } #[test] @@ -1092,7 +1095,7 @@ mod test { let addr = next_test_ip4(); let mut acceptor = TcpListener::bind(addr).listen(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut s = TcpStream::connect(addr); let mut buf = [0, 1]; s.read(&mut buf).unwrap(); @@ -1103,21 +1106,21 @@ mod test { let s2 = s1.clone(); let (done, rx) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut s2 = s2; s2.write(&[1]).unwrap(); - done.send(()); + done.send(()).unwrap(); }); s1.write(&[2]).unwrap(); - rx.recv(); + rx.recv().unwrap(); } #[test] fn shutdown_smoke() { let addr = next_test_ip4(); let a = TcpListener::bind(addr).unwrap().listen(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut a = a; let mut c = a.accept().unwrap(); assert_eq!(c.read_to_end(), Ok(vec!())); @@ -1151,10 +1154,10 @@ mod test { // flakiness. if !cfg!(target_os = "freebsd") { let (tx, rx) = channel(); - spawn(move|| { - tx.send(TcpStream::connect(addr).unwrap()); + let _t = Thread::spawn(move|| { + tx.send(TcpStream::connect(addr).unwrap()).unwrap(); }); - let _l = rx.recv(); + let _l = rx.recv().unwrap(); for i in range(0i, 1001) { match a.accept() { Ok(..) => break, @@ -1168,7 +1171,7 @@ mod test { // Unset the timeout and make sure that this always blocks. a.set_timeout(None); - spawn(move|| { + let _t = Thread::spawn(move|| { drop(TcpStream::connect(addr).unwrap()); }); a.accept().unwrap(); @@ -1179,11 +1182,11 @@ mod test { let addr = next_test_ip4(); let a = TcpListener::bind(addr).listen().unwrap(); let (_tx, rx) = channel::<()>(); - spawn(move|| { + Thread::spawn(move|| { let mut a = a; let _s = a.accept().unwrap(); - let _ = rx.recv_opt(); - }); + let _ = rx.recv().unwrap(); + }).detach(); let mut b = [0]; let mut s = TcpStream::connect(addr).unwrap(); @@ -1216,25 +1219,25 @@ mod test { let addr = next_test_ip4(); let a = TcpListener::bind(addr).listen().unwrap(); let (_tx, rx) = channel::<()>(); - spawn(move|| { + Thread::spawn(move|| { let mut a = a; let _s = a.accept().unwrap(); - let _ = rx.recv_opt(); - }); + let _ = rx.recv().unwrap(); + }).detach(); let mut s = TcpStream::connect(addr).unwrap(); let s2 = s.clone(); let (tx, rx) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut s2 = s2; assert!(s2.read(&mut [0]).is_err()); - tx.send(()); + tx.send(()).unwrap(); }); // this should wake up the child task s.close_read().unwrap(); // this test will never finish if the child doesn't wake up - rx.recv(); + rx.recv().unwrap(); } #[test] @@ -1242,12 +1245,12 @@ mod test { let addr = next_test_ip6(); let mut a = TcpListener::bind(addr).listen().unwrap(); let (tx, rx) = channel::<()>(); - spawn(move|| { + Thread::spawn(move|| { let mut s = TcpStream::connect(addr).unwrap(); - rx.recv(); + rx.recv().unwrap(); assert!(s.write(&[0]).is_ok()); - let _ = rx.recv_opt(); - }); + let _ = rx.recv(); + }).detach(); let mut s = a.accept().unwrap(); s.set_timeout(Some(20)); @@ -1265,7 +1268,7 @@ mod test { } assert_eq!(s.write(&[0]).err().unwrap().kind, TimedOut); - tx.send(()); + tx.send(()).unwrap(); s.set_timeout(None); assert_eq!(s.read(&mut [0, 0]), Ok(1)); } @@ -1275,9 +1278,9 @@ mod test { let addr = next_test_ip6(); let mut a = TcpListener::bind(addr).listen().unwrap(); let (tx, rx) = channel::<()>(); - spawn(move|| { + Thread::spawn(move|| { let mut s = TcpStream::connect(addr).unwrap(); - rx.recv(); + rx.recv().unwrap(); let mut amt = 0; while amt < 100 * 128 * 1024 { match s.read(&mut [0;128 * 1024]) { @@ -1285,15 +1288,15 @@ mod test { Err(e) => panic!("{}", e), } } - let _ = rx.recv_opt(); - }); + let _ = rx.recv(); + }).detach(); let mut s = a.accept().unwrap(); s.set_read_timeout(Some(20)); assert_eq!(s.read(&mut [0]).err().unwrap().kind, TimedOut); assert_eq!(s.read(&mut [0]).err().unwrap().kind, TimedOut); - tx.send(()); + tx.send(()).unwrap(); for _ in range(0i, 100) { assert!(s.write(&[0;128 * 1024]).is_ok()); } @@ -1304,12 +1307,12 @@ mod test { let addr = next_test_ip6(); let mut a = TcpListener::bind(addr).listen().unwrap(); let (tx, rx) = channel::<()>(); - spawn(move|| { + Thread::spawn(move|| { let mut s = TcpStream::connect(addr).unwrap(); - rx.recv(); + rx.recv().unwrap(); assert!(s.write(&[0]).is_ok()); - let _ = rx.recv_opt(); - }); + let _ = rx.recv(); + }).detach(); let mut s = a.accept().unwrap(); s.set_write_timeout(Some(20)); @@ -1323,7 +1326,7 @@ mod test { } assert_eq!(s.write(&[0]).err().unwrap().kind, TimedOut); - tx.send(()); + tx.send(()).unwrap(); assert!(s.read(&mut [0]).is_ok()); } @@ -1332,27 +1335,27 @@ mod test { let addr = next_test_ip6(); let mut a = TcpListener::bind(addr).listen().unwrap(); let (tx, rx) = channel::<()>(); - spawn(move|| { + Thread::spawn(move|| { let mut s = TcpStream::connect(addr).unwrap(); - rx.recv(); + rx.recv().unwrap(); assert_eq!(s.write(&[0]), Ok(())); - let _ = rx.recv_opt(); - }); + let _ = rx.recv(); + }).detach(); let mut s = a.accept().unwrap(); let s2 = s.clone(); let (tx2, rx2) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut s2 = s2; assert_eq!(s2.read(&mut [0]), Ok(1)); - tx2.send(()); + tx2.send(()).unwrap(); }); s.set_read_timeout(Some(20)); assert_eq!(s.read(&mut [0]).err().unwrap().kind, TimedOut); - tx.send(()); + tx.send(()).unwrap(); - rx2.recv(); + rx2.recv().unwrap(); } #[test] @@ -1365,21 +1368,21 @@ mod test { let (tx, rx) = channel(); let (txdone, rxdone) = channel(); let txdone2 = txdone.clone(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut tcp = TcpStream::connect(addr).unwrap(); - rx.recv(); + rx.recv().unwrap(); tcp.write_u8(0).unwrap(); - txdone2.send(()); + txdone2.send(()).unwrap(); }); // Spawn off a reading clone let tcp = accept.accept().unwrap(); let tcp2 = tcp.clone(); let txdone3 = txdone.clone(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut tcp2 = tcp2; tcp2.read_u8().unwrap(); - txdone3.send(()); + txdone3.send(()).unwrap(); }); // Try to ensure that the reading clone is indeed reading @@ -1390,9 +1393,9 @@ mod test { // clone the handle again while it's reading, then let it finish the // read. let _ = tcp.clone(); - tx.send(()); - rxdone.recv(); - rxdone.recv(); + tx.send(()).unwrap(); + rxdone.recv().unwrap(); + rxdone.recv().unwrap(); } #[test] @@ -1402,10 +1405,10 @@ mod test { let mut a = l.listen().unwrap(); let mut a2 = a.clone(); - spawn(move|| { + let _t = Thread::spawn(move|| { let _ = TcpStream::connect(addr); }); - spawn(move|| { + let _t = Thread::spawn(move|| { let _ = TcpStream::connect(addr); }); @@ -1423,18 +1426,24 @@ mod test { let (tx, rx) = channel(); let tx2 = tx.clone(); - spawn(move|| { let mut a = a; tx.send(a.accept()) }); - spawn(move|| { let mut a = a2; tx2.send(a.accept()) }); + let _t = Thread::spawn(move|| { + let mut a = a; + tx.send(a.accept()).unwrap(); + }); + let _t = Thread::spawn(move|| { + let mut a = a2; + tx2.send(a.accept()).unwrap(); + }); - spawn(move|| { + let _t = Thread::spawn(move|| { let _ = TcpStream::connect(addr); }); - spawn(move|| { + let _t = Thread::spawn(move|| { let _ = TcpStream::connect(addr); }); - assert!(rx.recv().is_ok()); - assert!(rx.recv().is_ok()); + assert!(rx.recv().unwrap().is_ok()); + assert!(rx.recv().unwrap().is_ok()); } #[test] @@ -1455,12 +1464,12 @@ mod test { let mut a2 = a.clone(); let (tx, rx) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut a = a; - tx.send(a.accept()); + tx.send(a.accept()).unwrap(); }); a2.close_accept().unwrap(); - assert_eq!(rx.recv().err().unwrap().kind, EndOfFile); + assert_eq!(rx.recv().unwrap().err().unwrap().kind, EndOfFile); } } diff --git a/src/libstd/io/net/udp.rs b/src/libstd/io/net/udp.rs index 11c2f956c35..6c167359966 100644 --- a/src/libstd/io/net/udp.rs +++ b/src/libstd/io/net/udp.rs @@ -248,11 +248,14 @@ impl Writer for UdpStream { #[cfg(test)] #[allow(experimental)] mod test { - use super::*; + use prelude::v1::*; + + use sync::mpsc::channel; use io::net::ip::*; - use io::{ShortWrite, IoError, TimedOut, PermissionDenied}; use io::test::*; - use prelude::{Ok, Err, spawn, range, drop, Some, None, channel, Clone, Reader, Writer}; + use io::{IoError, TimedOut, PermissionDenied, ShortWrite}; + use super::*; + use thread::Thread; // FIXME #11530 this fails on android because tests are run as root #[cfg_attr(any(windows, target_os = "android"), ignore)] @@ -272,20 +275,20 @@ mod test { let (tx1, rx1) = channel(); let (tx2, rx2) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { match UdpSocket::bind(client_ip) { Ok(ref mut client) => { - rx1.recv(); + rx1.recv().unwrap(); client.send_to(&[99], server_ip).unwrap() } Err(..) => panic!() } - tx2.send(()); + tx2.send(()).unwrap(); }); match UdpSocket::bind(server_ip) { Ok(ref mut server) => { - tx1.send(()); + tx1.send(()).unwrap(); let mut buf = [0]; match server.recv_from(&mut buf) { Ok((nread, src)) => { @@ -298,7 +301,7 @@ mod test { } Err(..) => panic!() } - rx2.recv(); + rx2.recv().unwrap(); } #[test] @@ -307,10 +310,10 @@ mod test { let client_ip = next_test_ip6(); let (tx, rx) = channel::<()>(); - spawn(move|| { + let _t = Thread::spawn(move|| { match UdpSocket::bind(client_ip) { Ok(ref mut client) => { - rx.recv(); + rx.recv().unwrap(); client.send_to(&[99], server_ip).unwrap() } Err(..) => panic!() @@ -319,7 +322,7 @@ mod test { match UdpSocket::bind(server_ip) { Ok(ref mut server) => { - tx.send(()); + tx.send(()).unwrap(); let mut buf = [0]; match server.recv_from(&mut buf) { Ok((nread, src)) => { @@ -343,8 +346,8 @@ mod test { let (tx1, rx1) = channel(); let (tx2, rx2) = channel(); - spawn(move|| { - let send_as = |&: ip, val: &[u8]| { + let _t = Thread::spawn(move|| { + let send_as = |&:ip, val: &[u8]| { match UdpSocket::bind(ip) { Ok(client) => { let client = box client; @@ -354,17 +357,17 @@ mod test { Err(..) => panic!() } }; - rx1.recv(); + rx1.recv().unwrap(); send_as(dummy_ip, &[98]); send_as(client_ip, &[99]); - tx2.send(()); + tx2.send(()).unwrap(); }); match UdpSocket::bind(server_ip) { Ok(server) => { let server = box server; let mut stream = server.connect(client_ip); - tx1.send(()); + tx1.send(()).unwrap(); let mut buf = [0]; match stream.read(&mut buf) { Ok(nread) => { @@ -376,7 +379,7 @@ mod test { } Err(..) => panic!() } - rx2.recv(); + rx2.recv().unwrap(); } #[test] @@ -387,24 +390,24 @@ mod test { let (tx1, rx1) = channel(); let (tx2, rx2) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { match UdpSocket::bind(client_ip) { Ok(client) => { let client = box client; let mut stream = client.connect(server_ip); - rx1.recv(); + rx1.recv().unwrap(); stream.write(&[99]).unwrap(); } Err(..) => panic!() } - tx2.send(()); + tx2.send(()).unwrap(); }); match UdpSocket::bind(server_ip) { Ok(server) => { let server = box server; let mut stream = server.connect(client_ip); - tx1.send(()); + tx1.send(()).unwrap(); let mut buf = [0]; match stream.read(&mut buf) { Ok(nread) => { @@ -416,7 +419,7 @@ mod test { } Err(..) => panic!() } - rx2.recv(); + rx2.recv().unwrap(); } pub fn socket_name(addr: SocketAddr) { @@ -449,7 +452,7 @@ mod test { let mut sock1 = UdpSocket::bind(addr1).unwrap(); let sock2 = UdpSocket::bind(addr2).unwrap(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut sock2 = sock2; let mut buf = [0, 0]; assert_eq!(sock2.recv_from(&mut buf), Ok((1, addr1))); @@ -461,16 +464,16 @@ mod test { let (tx1, rx1) = channel(); let (tx2, rx2) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut sock3 = sock3; - rx1.recv(); + rx1.recv().unwrap(); sock3.send_to(&[1], addr2).unwrap(); - tx2.send(()); + tx2.send(()).unwrap(); }); - tx1.send(()); + tx1.send(()).unwrap(); let mut buf = [0, 0]; assert_eq!(sock1.recv_from(&mut buf), Ok((1, addr2))); - rx2.recv(); + rx2.recv().unwrap(); } #[test] @@ -482,29 +485,29 @@ mod test { let (tx1, rx) = channel(); let tx2 = tx1.clone(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut sock2 = sock2; sock2.send_to(&[1], addr1).unwrap(); - rx.recv(); + rx.recv().unwrap(); sock2.send_to(&[2], addr1).unwrap(); - rx.recv(); + rx.recv().unwrap(); }); let sock3 = sock1.clone(); let (done, rx) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut sock3 = sock3; let mut buf = [0, 0]; sock3.recv_from(&mut buf).unwrap(); - tx2.send(()); - done.send(()); + tx2.send(()).unwrap(); + done.send(()).unwrap(); }); let mut buf = [0, 0]; sock1.recv_from(&mut buf).unwrap(); - tx1.send(()); + tx1.send(()).unwrap(); - rx.recv(); + rx.recv().unwrap(); } #[test] @@ -517,38 +520,38 @@ mod test { let (tx, rx) = channel(); let (serv_tx, serv_rx) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut sock2 = sock2; let mut buf = [0, 1]; - rx.recv(); + rx.recv().unwrap(); match sock2.recv_from(&mut buf) { Ok(..) => {} Err(e) => panic!("failed receive: {}", e), } - serv_tx.send(()); + serv_tx.send(()).unwrap(); }); let sock3 = sock1.clone(); let (done, rx) = channel(); let tx2 = tx.clone(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut sock3 = sock3; match sock3.send_to(&[1], addr2) { - Ok(..) => { let _ = tx2.send_opt(()); } + Ok(..) => { let _ = tx2.send(()); } Err(..) => {} } - done.send(()); + done.send(()).unwrap(); }); match sock1.send_to(&[2], addr2) { - Ok(..) => { let _ = tx.send_opt(()); } + Ok(..) => { let _ = tx.send(()); } Err(..) => {} } drop(tx); - rx.recv(); - serv_rx.recv(); + rx.recv().unwrap(); + serv_rx.recv().unwrap(); } #[cfg(not(windows))] // FIXME #17553 @@ -561,14 +564,14 @@ mod test { let (tx, rx) = channel(); let (tx2, rx2) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut a = a2; assert_eq!(a.recv_from(&mut [0]), Ok((1, addr1))); assert_eq!(a.send_to(&[0], addr1), Ok(())); - rx.recv(); + rx.recv().unwrap(); assert_eq!(a.send_to(&[0], addr1), Ok(())); - tx2.send(()); + tx2.send(()).unwrap(); }); // Make sure that reads time out, but writes can continue @@ -583,11 +586,11 @@ mod test { // Clearing the timeout should allow for receiving a.set_timeout(None); - tx.send(()); + tx.send(()).unwrap(); assert_eq!(a2.recv_from(&mut [0]), Ok((1, addr2))); // Make sure the child didn't die - rx2.recv(); + rx2.recv().unwrap(); } #[test] diff --git a/src/libstd/io/pipe.rs b/src/libstd/io/pipe.rs index 93465d5510b..09dcafb0218 100644 --- a/src/libstd/io/pipe.rs +++ b/src/libstd/io/pipe.rs @@ -15,7 +15,7 @@ #![allow(missing_docs)] -use prelude::*; +use prelude::v1::*; use io::IoResult; use libc; @@ -112,7 +112,10 @@ impl Writer for PipeStream { #[cfg(test)] mod test { - use prelude::*; + use prelude::v1::*; + + use sync::mpsc::channel; + use thread::Thread; #[test] fn partial_read() { @@ -123,14 +126,14 @@ mod test { let out = PipeStream::open(writer); let mut input = PipeStream::open(reader); let (tx, rx) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut out = out; out.write(&[10]).unwrap(); - rx.recv(); // don't close the pipe until the other read has finished + rx.recv().unwrap(); // don't close the pipe until the other read has finished }); let mut buf = [0; 10]; input.read(&mut buf).unwrap(); - tx.send(()); + tx.send(()).unwrap(); } } diff --git a/src/libstd/io/process.rs b/src/libstd/io/process.rs index b127507f048..fedc102e45d 100644 --- a/src/libstd/io/process.rs +++ b/src/libstd/io/process.rs @@ -16,25 +16,25 @@ pub use self::StdioContainer::*; pub use self::ProcessExit::*; -use prelude::*; +use prelude::v1::*; +use c_str::{CString, ToCStr}; +use collections::HashMap; use fmt; -use os; +use hash::Hash; +use io::pipe::{PipeStream, PipePair}; use io::{IoResult, IoError}; use io; use libc; -use c_str::CString; -use collections::HashMap; -use hash::Hash; -#[cfg(windows)] -use std::hash::sip::SipState; -use io::pipe::{PipeStream, PipePair}; +use os; use path::BytesContainer; -use thread::Thread; - -use sys; +use sync::mpsc::{channel, Receiver}; use sys::fs::FileDesc; use sys::process::Process as ProcessImp; +use sys; +use thread::Thread; + +#[cfg(windows)] use std::hash::sip::SipState; /// Signal a process to exit, without forcibly killing it. Corresponds to /// SIGTERM on unix platforms. @@ -693,10 +693,10 @@ impl Process { Some(stream) => { Thread::spawn(move |:| { let mut stream = stream; - tx.send(stream.read_to_end()) + tx.send(stream.read_to_end()).unwrap(); }).detach(); } - None => tx.send(Ok(Vec::new())) + None => tx.send(Ok(Vec::new())).unwrap() } rx } @@ -707,8 +707,8 @@ impl Process { Ok(ProcessOutput { status: status, - output: stdout.recv().ok().unwrap_or(Vec::new()), - error: stderr.recv().ok().unwrap_or(Vec::new()), + output: stdout.recv().unwrap().unwrap_or(Vec::new()), + error: stderr.recv().unwrap().unwrap_or(Vec::new()), }) } @@ -741,18 +741,19 @@ impl Drop for Process { #[cfg(test)] mod tests { - #![allow(unused_imports)] + use prelude::v1::*; - use super::*; - use io::timer::*; - use io::{Truncate, Write, TimedOut, timer, process, FileNotFound}; - use prelude::{Ok, Err, spawn, range, drop, Box, Some, None, Option, Vec, Buffer}; - use prelude::{from_str, Path, String, channel, Reader, Writer, Clone, Slice}; - use prelude::{SliceExt, Str, StrExt, AsSlice, ToString, GenericPath}; use io::fs::PathExtensions; - use time::Duration; - use str; + use io::process; + use io::timer::*; + use io::{Truncate, Write, TimedOut, timer, FileNotFound}; use rt::running_on_valgrind; + use str; + use super::{CreatePipe}; + use super::{InheritFd, Process, PleaseExitSignal, Command, ProcessOutput}; + use sync::mpsc::channel; + use thread::Thread; + use time::Duration; // FIXME(#10380) these tests should not all be ignored on android. @@ -1156,22 +1157,22 @@ mod tests { fn wait_timeout2() { let (tx, rx) = channel(); let tx2 = tx.clone(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut p = sleeper(); p.set_timeout(Some(10)); assert_eq!(p.wait().err().unwrap().kind, TimedOut); p.signal_kill().unwrap(); - tx.send(()); + tx.send(()).unwrap(); }); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut p = sleeper(); p.set_timeout(Some(10)); assert_eq!(p.wait().err().unwrap().kind, TimedOut); p.signal_kill().unwrap(); - tx2.send(()); + tx2.send(()).unwrap(); }); - rx.recv(); - rx.recv(); + rx.recv().unwrap(); + rx.recv().unwrap(); } #[test] diff --git a/src/libstd/io/result.rs b/src/libstd/io/result.rs index 32965d23971..c1474650f1e 100644 --- a/src/libstd/io/result.rs +++ b/src/libstd/io/result.rs @@ -78,7 +78,7 @@ impl<T, A: Acceptor<T>> Acceptor<T> for IoResult<A> { #[cfg(test)] mod test { - use prelude::*; + use prelude::v1::*; use super::super::mem::*; use io; diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index b7d069eb19e..cd991c5f884 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -117,13 +117,15 @@ pub struct StdinReaderGuard<'a> { inner: MutexGuard<'a, RaceBox>, } -impl<'a> Deref<BufferedReader<StdReader>> for StdinReaderGuard<'a> { +impl<'a> Deref for StdinReaderGuard<'a> { + type Target = BufferedReader<StdReader>; + fn deref(&self) -> &BufferedReader<StdReader> { &self.inner.0 } } -impl<'a> DerefMut<BufferedReader<StdReader>> for StdinReaderGuard<'a> { +impl<'a> DerefMut for StdinReaderGuard<'a> { fn deref_mut(&mut self) -> &mut BufferedReader<StdReader> { &mut self.inner.0 } @@ -218,7 +220,7 @@ pub fn stdin() -> StdinReader { static ONCE: Once = ONCE_INIT; unsafe { - ONCE.doit(|| { + ONCE.call_once(|| { // The default buffer capacity is 64k, but apparently windows doesn't like // 64k reads on stdin. See #13304 for details, but the idea is that on // windows we use a slightly smaller buffer that's been seen to be @@ -520,8 +522,11 @@ impl Writer for StdWriter { #[cfg(test)] mod tests { + use prelude::v1::*; + use super::*; - use prelude::*; + use sync::mpsc::channel; + use thread::Thread; #[test] fn smoke() { @@ -537,7 +542,7 @@ mod tests { let (tx, rx) = channel(); let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx)); - spawn(move|| { + let _t = Thread::spawn(move|| { set_stdout(box w); println!("hello!"); }); @@ -550,7 +555,7 @@ mod tests { let (tx, rx) = channel(); let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx)); - spawn(move|| { + let _t = Thread::spawn(move || -> () { set_stderr(box w); panic!("my special message"); }); diff --git a/src/libstd/io/tempfile.rs b/src/libstd/io/tempfile.rs index c2b4d5a1fa9..5cf86676651 100644 --- a/src/libstd/io/tempfile.rs +++ b/src/libstd/io/tempfile.rs @@ -90,7 +90,7 @@ impl TempDir { return TempDir::new_in(&abs_tmpdir, suffix); } - static CNT: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT; + static CNT: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT; let mut attempts = 0u; loop { diff --git a/src/libstd/io/test.rs b/src/libstd/io/test.rs index 40941fda79c..2f87abd0ee2 100644 --- a/src/libstd/io/test.rs +++ b/src/libstd/io/test.rs @@ -12,21 +12,22 @@ #![macro_escape] +use prelude::v1::*; + use libc; use os; -use prelude::*; use std::io::net::ip::*; -use sync::atomic::{AtomicUint, INIT_ATOMIC_UINT, Relaxed}; +use sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Relaxed}; /// Get a port number, starting at 9600, for use in tests pub fn next_test_port() -> u16 { - static NEXT_OFFSET: AtomicUint = INIT_ATOMIC_UINT; + static NEXT_OFFSET: AtomicUint = ATOMIC_UINT_INIT; base_port() + NEXT_OFFSET.fetch_add(1, Relaxed) as u16 } /// Get a temporary path which could be the location of a unix socket pub fn next_test_unix() -> Path { - static COUNT: AtomicUint = INIT_ATOMIC_UINT; + static COUNT: AtomicUint = ATOMIC_UINT_INIT; // base port and pid are an attempt to be unique between multiple // test-runners of different configurations running on one // buildbot, the count is to be unique within this executable. diff --git a/src/libstd/io/timer.rs b/src/libstd/io/timer.rs index 953effe4345..e073f76af82 100644 --- a/src/libstd/io/timer.rs +++ b/src/libstd/io/timer.rs @@ -15,7 +15,7 @@ // FIXME: These functions take Durations but only pass ms to the backend impls. -use comm::{Receiver, Sender, channel}; +use sync::mpsc::{Receiver, Sender, channel}; use time::Duration; use io::IoResult; use sys::timer::Callback; @@ -40,11 +40,11 @@ use sys::timer::Timer as TimerImp; /// /// let timeout = timer.oneshot(Duration::milliseconds(10)); /// // do some work -/// timeout.recv(); // wait for the timeout to expire +/// timeout.recv().unwrap(); // wait for the timeout to expire /// /// let periodic = timer.periodic(Duration::milliseconds(10)); /// loop { -/// periodic.recv(); +/// periodic.recv().unwrap(); /// // this loop is only executed once every 10ms /// } /// # } @@ -126,7 +126,7 @@ impl Timer { /// for _ in range(0u, 100) { /* do work */ } /// /// // blocks until 10 ms after the `oneshot` call - /// ten_milliseconds.recv(); + /// ten_milliseconds.recv().unwrap(); /// ``` /// /// ```rust @@ -136,7 +136,7 @@ impl Timer { /// // Incorrect, method chaining-style: /// let mut five_ms = Timer::new().unwrap().oneshot(Duration::milliseconds(5)); /// // The timer object was destroyed, so this will always fail: - /// // five_ms.recv() + /// // five_ms.recv().unwrap() /// ``` /// /// When provided a zero or negative `duration`, the message will @@ -147,7 +147,7 @@ impl Timer { if in_ms_u64(duration) != 0 { self.inner.oneshot(in_ms_u64(duration), box TimerCallback { tx: tx }); } else { - tx.send(()); + tx.send(()).unwrap(); } return rx } @@ -178,13 +178,13 @@ impl Timer { /// for _ in range(0u, 100) { /* do work */ } /// /// // blocks until 10 ms after the `periodic` call - /// ten_milliseconds.recv(); + /// ten_milliseconds.recv().unwrap(); /// /// for _ in range(0u, 100) { /* do work */ } /// /// // blocks until 20 ms after the `periodic` call (*not* 10ms after the /// // previous `recv`) - /// ten_milliseconds.recv(); + /// ten_milliseconds.recv().unwrap(); /// ``` /// /// ```rust @@ -194,7 +194,7 @@ impl Timer { /// // Incorrect, method chaining-style. /// let mut five_ms = Timer::new().unwrap().periodic(Duration::milliseconds(5)); /// // The timer object was destroyed, so this will always fail: - /// // five_ms.recv() + /// // five_ms.recv().unwrap() /// ``` /// /// When provided a zero or negative `duration`, the messages will @@ -213,7 +213,7 @@ impl Timer { impl Callback for TimerCallback { fn call(&mut self) { - let _ = self.tx.send_opt(()); + let _ = self.tx.send(()); } } @@ -225,9 +225,8 @@ fn in_ms_u64(d: Duration) -> u64 { #[cfg(test)] mod test { - use prelude::*; - use super::Timer; + use thread::Thread; use time::Duration; #[test] @@ -239,7 +238,7 @@ mod test { #[test] fn test_io_timer_sleep_oneshot() { let mut timer = Timer::new().unwrap(); - timer.oneshot(Duration::milliseconds(1)).recv(); + timer.oneshot(Duration::milliseconds(1)).recv().unwrap(); } #[test] @@ -253,8 +252,8 @@ mod test { let mut timer = Timer::new().unwrap(); let rx1 = timer.oneshot(Duration::milliseconds(10000)); let rx = timer.oneshot(Duration::milliseconds(1)); - rx.recv(); - assert_eq!(rx1.recv_opt(), Err(())); + rx.recv().unwrap(); + assert!(rx1.recv().is_err()); } #[test] @@ -263,16 +262,16 @@ mod test { let rx = timer.oneshot(Duration::milliseconds(100000000)); timer.sleep(Duration::milliseconds(1)); // this should invalidate rx - assert_eq!(rx.recv_opt(), Err(())); + assert!(rx.recv().is_err()); } #[test] fn test_io_timer_sleep_periodic() { let mut timer = Timer::new().unwrap(); let rx = timer.periodic(Duration::milliseconds(1)); - rx.recv(); - rx.recv(); - rx.recv(); + rx.recv().unwrap(); + rx.recv().unwrap(); + rx.recv().unwrap(); } #[test] @@ -291,12 +290,12 @@ mod test { let mut timer = Timer::new().unwrap(); let rx = timer.oneshot(Duration::milliseconds(1)); - rx.recv(); - assert!(rx.recv_opt().is_err()); + rx.recv().unwrap(); + assert!(rx.recv().is_err()); let rx = timer.oneshot(Duration::milliseconds(1)); - rx.recv(); - assert!(rx.recv_opt().is_err()); + rx.recv().unwrap(); + assert!(rx.recv().is_err()); } #[test] @@ -305,20 +304,20 @@ mod test { let orx = timer.oneshot(Duration::milliseconds(100)); let prx = timer.periodic(Duration::milliseconds(100)); timer.sleep(Duration::milliseconds(1)); - assert_eq!(orx.recv_opt(), Err(())); - assert_eq!(prx.recv_opt(), Err(())); - timer.oneshot(Duration::milliseconds(1)).recv(); + assert!(orx.recv().is_err()); + assert!(prx.recv().is_err()); + timer.oneshot(Duration::milliseconds(1)).recv().unwrap(); } #[test] fn period() { let mut timer = Timer::new().unwrap(); let rx = timer.periodic(Duration::milliseconds(1)); - rx.recv(); - rx.recv(); + rx.recv().unwrap(); + rx.recv().unwrap(); let rx2 = timer.periodic(Duration::milliseconds(1)); - rx2.recv(); - rx2.recv(); + rx2.recv().unwrap(); + rx2.recv().unwrap(); } #[test] @@ -357,9 +356,9 @@ mod test { let mut timer = Timer::new().unwrap(); let timer_rx = timer.periodic(Duration::milliseconds(1000)); - spawn(move|| { - let _ = timer_rx.recv_opt(); - }); + Thread::spawn(move|| { + let _ = timer_rx.recv(); + }).detach(); // when we drop the TimerWatcher we're going to destroy the channel, // which must wake up the task on the other end @@ -371,9 +370,9 @@ mod test { let mut timer = Timer::new().unwrap(); let timer_rx = timer.periodic(Duration::milliseconds(1000)); - spawn(move|| { - let _ = timer_rx.recv_opt(); - }); + Thread::spawn(move|| { + let _ = timer_rx.recv(); + }).detach(); timer.oneshot(Duration::milliseconds(1)); } @@ -384,9 +383,9 @@ mod test { let mut timer = Timer::new().unwrap(); let timer_rx = timer.periodic(Duration::milliseconds(1000)); - spawn(move|| { - let _ = timer_rx.recv_opt(); - }); + Thread::spawn(move|| { + let _ = timer_rx.recv(); + }).detach(); timer.sleep(Duration::milliseconds(1)); } @@ -397,7 +396,7 @@ mod test { let mut timer = Timer::new().unwrap(); timer.oneshot(Duration::milliseconds(1000)) }; - assert_eq!(rx.recv_opt(), Err(())); + assert!(rx.recv().is_err()); } #[test] @@ -406,7 +405,7 @@ mod test { let mut timer = Timer::new().unwrap(); timer.periodic(Duration::milliseconds(1000)) }; - assert_eq!(rx.recv_opt(), Err(())); + assert!(rx.recv().is_err()); } #[test] @@ -445,34 +444,34 @@ mod test { fn oneshot_zero() { let mut timer = Timer::new().unwrap(); let rx = timer.oneshot(Duration::milliseconds(0)); - rx.recv(); + rx.recv().unwrap(); } #[test] fn oneshot_negative() { let mut timer = Timer::new().unwrap(); let rx = timer.oneshot(Duration::milliseconds(-1000000)); - rx.recv(); + rx.recv().unwrap(); } #[test] fn periodic_zero() { let mut timer = Timer::new().unwrap(); let rx = timer.periodic(Duration::milliseconds(0)); - rx.recv(); - rx.recv(); - rx.recv(); - rx.recv(); + rx.recv().unwrap(); + rx.recv().unwrap(); + rx.recv().unwrap(); + rx.recv().unwrap(); } #[test] fn periodic_negative() { let mut timer = Timer::new().unwrap(); let rx = timer.periodic(Duration::milliseconds(-1000000)); - rx.recv(); - rx.recv(); - rx.recv(); - rx.recv(); + rx.recv().unwrap(); + rx.recv().unwrap(); + rx.recv().unwrap(); + rx.recv().unwrap(); } } diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index 9840412160d..38ab71c172c 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -10,7 +10,7 @@ //! Utility implementations of Reader and Writer -use prelude::*; +use prelude::v1::*; use cmp; use io; use slice::bytes::MutableByteVector; @@ -278,11 +278,11 @@ impl<T: Iterator<u8>> Reader for IterReader<T> { #[cfg(test)] mod test { + use prelude::v1::*; + use io::{MemReader, ByRefReader}; use io; - use boxed::Box; use super::*; - use prelude::{Ok, range, Vec, Buffer, Writer, Reader, ToString, AsSlice}; #[test] fn test_limit_reader_unlimited() { @@ -386,7 +386,7 @@ mod test { let mut r = TeeReader::new(MemReader::new(vec!(0, 1, 2)), Vec::new()); assert_eq!(vec!(0, 1, 2), r.read_to_end().unwrap()); - let (_, w) = r.unwrap(); + let (_, w) = r.into_inner(); assert_eq!(vec!(0, 1, 2), w); } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 74c387c5eea..7c8aab2b31d 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -107,6 +107,8 @@ #![feature(macro_rules, globs, linkage, thread_local, asm)] #![feature(default_type_params, phase, lang_items, unsafe_destructor)] #![feature(slicing_syntax, unboxed_closures)] +#![feature(old_orphan_check)] +#![feature(associated_types)] // Don't link to std. We are std. #![no_std] @@ -227,7 +229,6 @@ pub mod hash; pub mod task; pub mod thread; pub mod sync; -pub mod comm; #[cfg(unix)] #[path = "sys/unix/mod.rs"] mod sys; @@ -255,7 +256,7 @@ mod std { pub use cmp; pub use hash; - pub use comm; // used for select!() + pub use sync; // used for select!() pub use error; // used for try!() pub use fmt; // used for any formatting strings pub use io; // used for println!() @@ -265,6 +266,7 @@ mod std { pub use cell; // used for tls! pub use thread_local; // used for thread_local! pub use kinds; // used for tls! + pub use ops; // used for bitflags! // The test runner calls ::std::os::args() but really wants realstd #[cfg(test)] pub use realstd::os as os; diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index ebb64bc2f2d..63fd3209cc0 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -317,9 +317,8 @@ macro_rules! try { #[macro_export] macro_rules! vec { ($($x:expr),*) => ({ - use std::slice::BoxedSliceExt; let xs: ::std::boxed::Box<[_]> = box [$($x),*]; - xs.into_vec() + ::std::slice::SliceExt::into_vec(xs) }); ($($x:expr,)*) => (vec![$($x),*]) } @@ -334,6 +333,7 @@ macro_rules! vec { /// /// ``` /// use std::thread::Thread; +/// use std::sync::mpsc::channel; /// /// let (tx1, rx1) = channel(); /// let (tx2, rx2) = channel(); @@ -344,21 +344,21 @@ macro_rules! vec { /// Thread::spawn(move|| { tx2.send(calculate_the_answer()) }).detach(); /// /// select! ( -/// () = rx1.recv() => println!("the long running task finished first"), +/// _ = rx1.recv() => println!("the long running task finished first"), /// answer = rx2.recv() => { -/// println!("the answer was: {}", answer); +/// println!("the answer was: {}", answer.unwrap()); /// } /// ) /// ``` /// -/// For more information about select, see the `std::comm::Select` structure. +/// For more information about select, see the `std::sync::mpsc::Select` structure. #[macro_export] #[experimental] macro_rules! select { ( $($name:pat = $rx:ident.$meth:ident() => $code:expr),+ ) => ({ - use std::comm::Select; + use std::sync::mpsc::Select; let sel = Select::new(); $( let mut $rx = sel.handle(&$rx); )+ unsafe { diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index 1f76382ce8a..f2a0419e391 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -15,7 +15,7 @@ #![allow(unsigned_negation)] #![doc(primitive = "f32")] -use prelude::*; +use prelude::v1::*; use intrinsics; use libc::c_int; @@ -496,23 +496,25 @@ mod tests { #[test] fn test_real_consts() { - let pi: f32 = Float::pi(); - let two_pi: f32 = Float::two_pi(); - let frac_pi_2: f32 = Float::frac_pi_2(); - let frac_pi_3: f32 = Float::frac_pi_3(); - let frac_pi_4: f32 = Float::frac_pi_4(); - let frac_pi_6: f32 = Float::frac_pi_6(); - let frac_pi_8: f32 = Float::frac_pi_8(); - let frac_1_pi: f32 = Float::frac_1_pi(); - let frac_2_pi: f32 = Float::frac_2_pi(); - let frac_2_sqrtpi: f32 = Float::frac_2_sqrtpi(); - let sqrt2: f32 = Float::sqrt2(); - let frac_1_sqrt2: f32 = Float::frac_1_sqrt2(); - let e: f32 = Float::e(); - let log2_e: f32 = Float::log2_e(); - let log10_e: f32 = Float::log10_e(); - let ln_2: f32 = Float::ln_2(); - let ln_10: f32 = Float::ln_10(); + use super::consts; + + let pi: f32 = consts::PI; + let two_pi: f32 = consts::PI_2; + let frac_pi_2: f32 = consts::FRAC_PI_2; + let frac_pi_3: f32 = consts::FRAC_PI_3; + let frac_pi_4: f32 = consts::FRAC_PI_4; + let frac_pi_6: f32 = consts::FRAC_PI_6; + let frac_pi_8: f32 = consts::FRAC_PI_8; + let frac_1_pi: f32 = consts::FRAC_1_PI; + let frac_2_pi: f32 = consts::FRAC_2_PI; + let frac_2_sqrtpi: f32 = consts::FRAC_2_SQRTPI; + let sqrt2: f32 = consts::SQRT2; + let frac_1_sqrt2: f32 = consts::FRAC_1_SQRT2; + let e: f32 = consts::E; + let log2_e: f32 = consts::LOG2_E; + let log10_e: f32 = consts::LOG10_E; + let ln_2: f32 = consts::LN_2; + let ln_10: f32 = consts::LN_10; assert_approx_eq!(two_pi, 2f32 * pi); assert_approx_eq!(frac_pi_2, pi / 2f32); diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index 221ecf62c05..105a8a23bd1 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -14,7 +14,7 @@ #![allow(missing_docs)] #![doc(primitive = "f64")] -use prelude::*; +use prelude::v1::*; use intrinsics; use libc::c_int; @@ -499,23 +499,24 @@ mod tests { #[test] fn test_real_consts() { - let pi: f64 = Float::pi(); - let two_pi: f64 = Float::two_pi(); - let frac_pi_2: f64 = Float::frac_pi_2(); - let frac_pi_3: f64 = Float::frac_pi_3(); - let frac_pi_4: f64 = Float::frac_pi_4(); - let frac_pi_6: f64 = Float::frac_pi_6(); - let frac_pi_8: f64 = Float::frac_pi_8(); - let frac_1_pi: f64 = Float::frac_1_pi(); - let frac_2_pi: f64 = Float::frac_2_pi(); - let frac_2_sqrtpi: f64 = Float::frac_2_sqrtpi(); - let sqrt2: f64 = Float::sqrt2(); - let frac_1_sqrt2: f64 = Float::frac_1_sqrt2(); - let e: f64 = Float::e(); - let log2_e: f64 = Float::log2_e(); - let log10_e: f64 = Float::log10_e(); - let ln_2: f64 = Float::ln_2(); - let ln_10: f64 = Float::ln_10(); + use super::consts; + let pi: f64 = consts::PI; + let two_pi: f64 = consts::PI_2; + let frac_pi_2: f64 = consts::FRAC_PI_2; + let frac_pi_3: f64 = consts::FRAC_PI_3; + let frac_pi_4: f64 = consts::FRAC_PI_4; + let frac_pi_6: f64 = consts::FRAC_PI_6; + let frac_pi_8: f64 = consts::FRAC_PI_8; + let frac_1_pi: f64 = consts::FRAC_1_PI; + let frac_2_pi: f64 = consts::FRAC_2_PI; + let frac_2_sqrtpi: f64 = consts::FRAC_2_SQRTPI; + let sqrt2: f64 = consts::SQRT2; + let frac_1_sqrt2: f64 = consts::FRAC_1_SQRT2; + let e: f64 = consts::E; + let log2_e: f64 = consts::LOG2_E; + let log10_e: f64 = consts::LOG10_E; + let ln_2: f64 = consts::LN_2; + let ln_10: f64 = consts::LN_10; assert_approx_eq!(two_pi, 2.0 * pi); assert_approx_eq!(frac_pi_2, pi / 2f64); diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index 48ff1a364e9..01aa21c692b 100644 --- a/src/libstd/num/mod.rs +++ b/src/libstd/num/mod.rs @@ -147,10 +147,8 @@ pub fn test_num<T>(ten: T, two: T) where #[cfg(test)] mod tests { - use prelude::{range, Some, None, Option, IteratorExt}; - use super::{from_int, from_uint, from_i32, from_i64, from_u64, from_u32}; - use super::{from_f64, from_f32, from_u16, from_i16, from_u8, from_i8, Int}; - use super::{cast, NumCast, ToPrimitive, FromPrimitive, UnsignedInt}; + use prelude::v1::*; + use super::*; use i8; use i16; use i32; @@ -802,7 +800,7 @@ mod bench { extern crate test; use self::test::Bencher; use num::Int; - use prelude::*; + use prelude::v1::*; #[bench] fn bench_pow_function(b: &mut Bencher) { diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index febdf5f6118..6c64251091a 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -20,7 +20,7 @@ use char::{mod, Char}; use num::{mod, Int, Float, ToPrimitive}; use num::FpCategory as Fp; use ops::FnMut; -use slice::{SliceExt, CloneSliceExt}; +use slice::SliceExt; use str::StrExt; use string::String; use vec::Vec; diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs index e74f45f8f0a..b52e4fda7af 100644 --- a/src/libstd/num/uint_macros.rs +++ b/src/libstd/num/uint_macros.rs @@ -49,8 +49,9 @@ pub fn to_str_bytes<U, F>(n: $T, radix: uint, f: F) -> U where #[cfg(test)] mod tests { - use prelude::*; + use prelude::v1::*; use num::FromStrRadix; + use str::from_str; #[test] pub fn test_from_str() { diff --git a/src/libstd/os.rs b/src/libstd/os.rs index df50b7f81af..615a20baf89 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -52,10 +52,9 @@ use ptr; use result::Result; use result::Result::{Err, Ok}; use slice::{AsSlice, SliceExt}; -use slice::CloneSliceExt; use str::{Str, StrExt}; use string::{String, ToString}; -use sync::atomic::{AtomicInt, INIT_ATOMIC_INT, SeqCst}; +use sync::atomic::{AtomicInt, ATOMIC_INT_INIT, SeqCst}; use vec::Vec; #[cfg(unix)] use c_str::ToCStr; @@ -596,7 +595,7 @@ pub fn last_os_error() -> String { error_string(errno() as uint) } -static EXIT_STATUS: AtomicInt = INIT_ATOMIC_INT; +static EXIT_STATUS: AtomicInt = ATOMIC_INT_INIT; /// Sets the process exit code /// @@ -1427,8 +1426,9 @@ mod arch_consts { #[cfg(test)] mod tests { - use prelude::*; - use option; + use prelude::v1::*; + + use iter::repeat; use os::{env, getcwd, getenv, make_absolute}; use os::{split_paths, join_paths, setenv, unsetenv}; use os; @@ -1457,7 +1457,7 @@ mod tests { fn test_setenv() { let n = make_rand_name(); setenv(n.as_slice(), "VALUE"); - assert_eq!(getenv(n.as_slice()), option::Option::Some("VALUE".to_string())); + assert_eq!(getenv(n.as_slice()), Some("VALUE".to_string())); } #[test] @@ -1465,7 +1465,7 @@ mod tests { let n = make_rand_name(); setenv(n.as_slice(), "VALUE"); unsetenv(n.as_slice()); - assert_eq!(getenv(n.as_slice()), option::Option::None); + assert_eq!(getenv(n.as_slice()), None); } #[test] @@ -1474,9 +1474,9 @@ mod tests { let n = make_rand_name(); setenv(n.as_slice(), "1"); setenv(n.as_slice(), "2"); - assert_eq!(getenv(n.as_slice()), option::Option::Some("2".to_string())); + assert_eq!(getenv(n.as_slice()), Some("2".to_string())); setenv(n.as_slice(), ""); - assert_eq!(getenv(n.as_slice()), option::Option::Some("".to_string())); + assert_eq!(getenv(n.as_slice()), Some("".to_string())); } // Windows GetEnvironmentVariable requires some extra work to make sure @@ -1493,7 +1493,7 @@ mod tests { let n = make_rand_name(); setenv(n.as_slice(), s.as_slice()); debug!("{}", s.clone()); - assert_eq!(getenv(n.as_slice()), option::Option::Some(s)); + assert_eq!(getenv(n.as_slice()), Some(s)); } #[test] @@ -1530,14 +1530,14 @@ mod tests { // MingW seems to set some funky environment variables like // "=C:=C:\MinGW\msys\1.0\bin" and "!::=::\" that are returned // from env() but not visible from getenv(). - assert!(v2.is_none() || v2 == option::Option::Some(v)); + assert!(v2.is_none() || v2 == Some(v)); } } #[test] fn test_env_set_get_huge() { let n = make_rand_name(); - let s = "x".repeat(10000).to_string(); + let s = repeat("x").take(10000).collect::<String>(); setenv(n.as_slice(), s.as_slice()); assert_eq!(getenv(n.as_slice()), Some(s)); unsetenv(n.as_slice()); @@ -1659,8 +1659,8 @@ mod tests { path.push("mmap_file.tmp"); let size = MemoryMap::granularity() * 2; let mut file = File::open_mode(&path, Open, ReadWrite).unwrap(); - file.seek(size as i64, SeekSet); - file.write_u8(0); + file.seek(size as i64, SeekSet).unwrap(); + file.write_u8(0).unwrap(); let chunk = MemoryMap::new(size / 2, &[ MapOption::MapReadable, diff --git a/src/libstd/path/mod.rs b/src/libstd/path/mod.rs index 30f3f56bc1c..731c3bbe427 100644 --- a/src/libstd/path/mod.rs +++ b/src/libstd/path/mod.rs @@ -71,8 +71,7 @@ use option::Option::{None, Some}; use str; use str::{CowString, MaybeOwned, Str, StrExt}; use string::String; -use slice::{AsSlice, CloneSliceExt}; -use slice::{PartialEqSliceExt, SliceExt}; +use slice::{AsSlice, SliceExt}; use vec::Vec; /// Typedef for POSIX file paths. @@ -931,7 +930,9 @@ fn contains_nul<T: BytesContainer>(v: &T) -> bool { #[cfg(test)] mod tests { - use prelude::*; + use prelude::v1::*; + use c_str::ToCStr; + use path::{WindowsPath, PosixPath}; #[test] fn test_cstring() { diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs index bd4031e6230..6075010f3b5 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -22,8 +22,7 @@ use option::Option::{None, Some}; use kinds::Sized; use str::{FromStr, Str}; use str; -use slice::{CloneSliceExt, Split, AsSlice, SliceConcatExt, - PartialEqSliceExt, SliceExt}; +use slice::{Split, AsSlice, SliceConcatExt, SliceExt}; use vec::Vec; use super::{BytesContainer, GenericPath, GenericPathUnsafe}; @@ -448,10 +447,15 @@ static dot_dot_static: &'static [u8] = b".."; #[cfg(test)] mod tests { use super::*; - use prelude::Option::{mod, Some, None}; - use prelude::{Vec, Clone, AsSlice, SliceExt, CloneSliceExt, IteratorExt}; - use prelude::{DoubleEndedIteratorExt, Str, StrExt, ToString, GenericPath}; - use str; + + use clone::Clone; + use iter::{IteratorExt, DoubleEndedIteratorExt}; + use option::Option::{mod, Some, None}; + use path::GenericPath; + use slice::{AsSlice, SliceExt}; + use str::{mod, Str, StrExt}; + use string::ToString; + use vec::Vec; macro_rules! t { (s: $path:expr, $exp:expr) => ( @@ -1239,7 +1243,7 @@ mod bench { extern crate test; use self::test::Bencher; use super::*; - use prelude::{Clone, GenericPath}; + use prelude::v1::{Clone, GenericPath}; #[bench] fn join_home_dir(b: &mut Bencher) { diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index 751ed4b70fb..55086ad3a23 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -1119,12 +1119,18 @@ fn prefix_len(p: Option<PathPrefix>) -> uint { #[cfg(test)] mod tests { - use super::*; - use prelude::Option::{mod, Some, None}; - use prelude::{Vec, Clone, AsSlice, SliceExt, CloneSliceExt, IteratorExt}; - use prelude::{DoubleEndedIteratorExt, Str, ToString, GenericPath}; use super::PathPrefix::*; use super::parse_prefix; + use super::*; + + use clone::Clone; + use iter::{IteratorExt, DoubleEndedIteratorExt}; + use option::Option::{mod, Some, None}; + use path::GenericPath; + use slice::{AsSlice, SliceExt}; + use str::Str; + use string::ToString; + use vec::Vec; macro_rules! t { (s: $path:expr, $exp:expr) => ( diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs deleted file mode 100644 index f016683e3d0..00000000000 --- a/src/libstd/prelude.rs +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2013 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. - -//! The Rust prelude -//! -//! Because `std` is required by most serious Rust software, it is -//! imported at the topmost level of every crate by default, as if the -//! first line of each crate was -//! -//! ```ignore -//! extern crate std; -//! ``` -//! -//! This means that the contents of std can be accessed from any context -//! with the `std::` path prefix, as in `use std::vec`, `use std::task::spawn`, -//! etc. -//! -//! Additionally, `std` contains a `prelude` module that reexports many of the -//! most common traits, types and functions. The contents of the prelude are -//! imported into every *module* by default. Implicitly, all modules behave as if -//! they contained the following prologue: -//! -//! ```ignore -//! use std::prelude::*; -//! ``` -//! -//! The prelude is primarily concerned with exporting *traits* that are so -//! pervasive that it would be obnoxious to import for every use, particularly -//! those that define methods on primitive types. It does include a few -//! particularly useful standalone functions, like `from_str`, `range`, and -//! `drop`, `spawn`, and `channel`. - -#![experimental] - -// Reexported core operators -#[doc(no_inline)] pub use kinds::{Copy, Send, Sized, Sync}; -#[doc(no_inline)] pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not}; -#[doc(no_inline)] pub use ops::{BitAnd, BitOr, BitXor}; -#[doc(no_inline)] pub use ops::{Drop, Deref, DerefMut}; -#[doc(no_inline)] pub use ops::{Shl, Shr}; -#[doc(no_inline)] pub use ops::{Index, IndexMut}; -#[doc(no_inline)] pub use ops::{Slice, SliceMut}; -#[doc(no_inline)] pub use ops::{Fn, FnMut, FnOnce}; - -// Reexported functions -#[doc(no_inline)] pub use iter::range; -#[doc(no_inline)] pub use mem::drop; -#[doc(no_inline)] pub use str::from_str; - -// Reexported types and traits - -#[doc(no_inline)] pub use borrow::IntoCow; -#[doc(no_inline)] pub use c_str::ToCStr; -#[doc(no_inline)] pub use char::{Char, UnicodeChar}; -#[doc(no_inline)] pub use clone::Clone; -#[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord}; -#[doc(no_inline)] pub use cmp::{Ordering, Equiv}; -#[doc(no_inline)] pub use cmp::Ordering::{Less, Equal, Greater}; -#[doc(no_inline)] pub use iter::{FromIterator, Extend, ExactSizeIterator}; -#[doc(no_inline)] pub use iter::{Iterator, IteratorExt, DoubleEndedIterator}; -#[doc(no_inline)] pub use iter::{DoubleEndedIteratorExt, CloneIteratorExt}; -#[doc(no_inline)] pub use iter::{RandomAccessIterator, IteratorCloneExt, IteratorPairExt}; -#[doc(no_inline)] pub use iter::{IteratorOrdExt, MutableDoubleEndedIterator}; -#[doc(no_inline)] pub use num::{ToPrimitive, FromPrimitive}; -#[doc(no_inline)] pub use boxed::Box; -#[doc(no_inline)] pub use option::Option; -#[doc(no_inline)] pub use option::Option::{Some, None}; -#[doc(no_inline)] pub use path::{GenericPath, Path, PosixPath, WindowsPath}; -#[doc(no_inline)] pub use ptr::{PtrExt, MutPtrExt}; -#[doc(no_inline)] pub use result::Result; -#[doc(no_inline)] pub use result::Result::{Ok, Err}; -#[doc(no_inline)] pub use io::{Buffer, Writer, Reader, Seek, BufferPrelude}; -#[doc(no_inline)] pub use core::prelude::{Tuple1, Tuple2, Tuple3, Tuple4}; -#[doc(no_inline)] pub use core::prelude::{Tuple5, Tuple6, Tuple7, Tuple8}; -#[doc(no_inline)] pub use core::prelude::{Tuple9, Tuple10, Tuple11, Tuple12}; -#[doc(no_inline)] pub use str::{Str, StrExt}; -#[doc(no_inline)] pub use slice::AsSlice; -#[doc(no_inline)] pub use slice::{SliceConcatExt, PartialEqSliceExt}; -#[doc(no_inline)] pub use slice::{CloneSliceExt, OrdSliceExt, SliceExt}; -#[doc(no_inline)] pub use slice::{BoxedSliceExt}; -#[doc(no_inline)] pub use string::{IntoString, String, ToString}; -#[doc(no_inline)] pub use vec::Vec; - -// Reexported runtime types -#[doc(no_inline)] pub use comm::{sync_channel, channel}; -#[doc(no_inline)] pub use comm::{SyncSender, Sender, Receiver}; -#[doc(no_inline)] pub use task::spawn; diff --git a/src/libstd/prelude/mod.rs b/src/libstd/prelude/mod.rs new file mode 100644 index 00000000000..da945b4c9fa --- /dev/null +++ b/src/libstd/prelude/mod.rs @@ -0,0 +1,42 @@ +// Copyright 2014 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. + +//! The Rust prelude +//! +//! Because `std` is required by most serious Rust software, it is +//! imported at the topmost level of every crate by default, as if the +//! first line of each crate was +//! +//! ```ignore +//! extern crate std; +//! ``` +//! +//! This means that the contents of std can be accessed from any context +//! with the `std::` path prefix, as in `use std::vec`, `use std::task::spawn`, +//! etc. +//! +//! Additionally, `std` contains a `prelude` module that reexports many of the +//! most common traits, types and functions. The contents of the prelude are +//! imported into every *module* by default. Implicitly, all modules behave as if +//! they contained the following prologue: +//! +//! ```ignore +//! use std::prelude::v1::*; +//! ``` +//! +//! The prelude is primarily concerned with exporting *traits* that are so +//! pervasive that it would be obnoxious to import for every use, particularly +//! those that define methods on primitive types. + +#[cfg(stage0)] +pub use self::v1::*; + +#[stable] +pub mod v1; diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs new file mode 100644 index 00000000000..cb5dfafb4a1 --- /dev/null +++ b/src/libstd/prelude/v1.rs @@ -0,0 +1,49 @@ +// Copyright 2013 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. + +//! The first version of the prelude of the standard library. + +#![stable] + +// Reexported core operators +#[stable] #[doc(no_inline)] pub use kinds::{Copy, Send, Sized, Sync}; +#[stable] #[doc(no_inline)] pub use ops::{Drop, Fn, FnMut, FnOnce}; + +// Reexported functions +#[stable] #[doc(no_inline)] pub use mem::drop; + +// Reexported types and traits + +#[stable] #[doc(no_inline)] pub use boxed::Box; +#[stable] #[doc(no_inline)] pub use char::{Char, UnicodeChar}; +#[stable] #[doc(no_inline)] pub use clone::Clone; +#[stable] #[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord}; +#[stable] #[doc(no_inline)] pub use iter::CloneIteratorExt; +#[stable] #[doc(no_inline)] pub use iter::DoubleEndedIterator; +#[stable] #[doc(no_inline)] pub use iter::DoubleEndedIteratorExt; +#[stable] #[doc(no_inline)] pub use iter::ExactSizeIterator; +#[stable] #[doc(no_inline)] pub use iter::{Iterator, IteratorExt, Extend}; +#[stable] #[doc(no_inline)] pub use iter::{IteratorCloneExt, IteratorOrdExt}; +#[stable] #[doc(no_inline)] pub use iter::IteratorPairExt; +#[stable] #[doc(no_inline)] pub use option::Option::{mod, Some, None}; +#[stable] #[doc(no_inline)] pub use ptr::{PtrExt, MutPtrExt}; +#[stable] #[doc(no_inline)] pub use result::Result::{mod, Ok, Err}; +#[stable] #[doc(no_inline)] pub use slice::AsSlice; +#[stable] #[doc(no_inline)] pub use slice::{SliceExt, SliceConcatExt}; +#[stable] #[doc(no_inline)] pub use str::{Str, StrExt}; +#[stable] #[doc(no_inline)] pub use string::{String, ToString}; +#[stable] #[doc(no_inline)] pub use vec::Vec; + +// NB: remove when path reform lands +#[doc(no_inline)] pub use path::{Path, GenericPath}; +// NB: remove when I/O reform lands +#[doc(no_inline)] pub use io::{Buffer, Writer, Reader, Seek, BufferPrelude}; +// NB: remove when range syntax lands +#[doc(no_inline)] pub use iter::range; diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs index f665d150f38..86b8bfc7370 100644 --- a/src/libstd/rand/mod.rs +++ b/src/libstd/rand/mod.rs @@ -419,7 +419,7 @@ pub fn sample<T, I: Iterator<T>, R: Rng>(rng: &mut R, #[cfg(test)] mod test { - use prelude::*; + use prelude::v1::*; use super::{Rng, thread_rng, random, SeedableRng, StdRng, sample}; use iter::order; @@ -615,7 +615,7 @@ static RAND_BENCH_N: u64 = 100; #[cfg(test)] mod bench { extern crate test; - use prelude::*; + use prelude::v1::*; use self::test::Bencher; use super::{XorShiftRng, StdRng, IsaacRng, Isaac64Rng, Rng, RAND_BENCH_N}; diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs index ca36f2d8997..9f3ac84afff 100644 --- a/src/libstd/rand/os.rs +++ b/src/libstd/rand/os.rs @@ -84,10 +84,10 @@ mod imp { #[cfg(all(target_os = "linux", any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm")))] fn is_getrandom_available() -> bool { - use sync::atomic::{AtomicBool, INIT_ATOMIC_BOOL, Relaxed}; + use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Relaxed}; - static GETRANDOM_CHECKED: AtomicBool = INIT_ATOMIC_BOOL; - static GETRANDOM_AVAILABLE: AtomicBool = INIT_ATOMIC_BOOL; + static GETRANDOM_CHECKED: AtomicBool = ATOMIC_BOOL_INIT; + static GETRANDOM_AVAILABLE: AtomicBool = ATOMIC_BOOL_INIT; if !GETRANDOM_CHECKED.load(Relaxed) { let mut buf: [u8; 0] = []; @@ -338,10 +338,11 @@ mod imp { #[cfg(test)] mod test { - use prelude::*; + use prelude::v1::*; - use super::OsRng; + use sync::mpsc::channel; use rand::Rng; + use super::OsRng; use thread::Thread; #[test] @@ -365,7 +366,7 @@ mod test { Thread::spawn(move|| { // wait until all the tasks are ready to go. - rx.recv(); + rx.recv().unwrap(); // deschedule to attempt to interleave things as much // as possible (XXX: is this a good test?) @@ -386,7 +387,7 @@ mod test { // start all the tasks for tx in txs.iter() { - tx.send(()) + tx.send(()).unwrap(); } } } diff --git a/src/libstd/rand/reader.rs b/src/libstd/rand/reader.rs index 15e63aa19ea..48d7f2e7854 100644 --- a/src/libstd/rand/reader.rs +++ b/src/libstd/rand/reader.rs @@ -74,7 +74,7 @@ impl<R: Reader> Rng for ReaderRng<R> { #[cfg(test)] mod test { - use prelude::*; + use prelude::v1::*; use super::ReaderRng; use io::MemReader; diff --git a/src/libstd/rt/args.rs b/src/libstd/rt/args.rs index 98eff621ce0..4734a39c835 100644 --- a/src/libstd/rt/args.rs +++ b/src/libstd/rt/args.rs @@ -44,7 +44,7 @@ pub fn clone() -> Option<Vec<Vec<u8>>> { imp::clone() } target_os = "freebsd", target_os = "dragonfly"))] mod imp { - use prelude::*; + use prelude::v1::*; use mem; use slice; @@ -107,7 +107,7 @@ mod imp { #[cfg(test)] mod tests { - use prelude::*; + use prelude::v1::*; use finally::Finally; use super::*; diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs index 3eeb0ad3968..ae405e9400b 100644 --- a/src/libstd/rt/backtrace.rs +++ b/src/libstd/rt/backtrace.rs @@ -12,7 +12,7 @@ #![allow(non_camel_case_types)] -use prelude::*; +use prelude::v1::*; use os; use sync::atomic; @@ -22,7 +22,7 @@ pub use sys::backtrace::write; // For now logging is turned off by default, and this function checks to see // whether the magical environment variable is present to see if it's turned on. pub fn log_enabled() -> bool { - static ENABLED: atomic::AtomicInt = atomic::INIT_ATOMIC_INT; + static ENABLED: atomic::AtomicInt = atomic::ATOMIC_INT_INIT; match ENABLED.load(atomic::SeqCst) { 1 => return false, 2 => return true, @@ -39,7 +39,7 @@ pub fn log_enabled() -> bool { #[cfg(test)] mod test { - use prelude::*; + use prelude::v1::*; use sys_common; macro_rules! t { ($a:expr, $b:expr) => ({ let mut m = Vec::new(); diff --git a/src/libstd/rt/exclusive.rs b/src/libstd/rt/exclusive.rs deleted file mode 100644 index 88bdb29caec..00000000000 --- a/src/libstd/rt/exclusive.rs +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2013 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. - -use core::prelude::*; - -use cell::UnsafeCell; -use rt::mutex; - -/// An OS mutex over some data. -/// -/// This is not a safe primitive to use, it is unaware of the libgreen -/// scheduler, as well as being easily susceptible to misuse due to the usage of -/// the inner NativeMutex. -/// -/// > **Note**: This type is not recommended for general use. The mutex provided -/// > as part of `libsync` should almost always be favored. -pub struct Exclusive<T> { - lock: mutex::NativeMutex, - data: UnsafeCell<T>, -} - -unsafe impl<T:Send> Send for Exclusive<T> { } - -unsafe impl<T:Send> Sync for Exclusive<T> { } - -/// An RAII guard returned via `lock` -pub struct ExclusiveGuard<'a, T:'a> { - // FIXME #12808: strange name to try to avoid interfering with - // field accesses of the contained type via Deref - _data: &'a mut T, - _guard: mutex::LockGuard<'a>, -} - -impl<T: Send> Exclusive<T> { - /// Creates a new `Exclusive` which will protect the data provided. - pub fn new(user_data: T) -> Exclusive<T> { - Exclusive { - lock: unsafe { mutex::NativeMutex::new() }, - data: UnsafeCell::new(user_data), - } - } - - /// Acquires this lock, returning a guard which the data is accessed through - /// and from which that lock will be unlocked. - /// - /// This method is unsafe due to many of the same reasons that the - /// NativeMutex itself is unsafe. - pub unsafe fn lock<'a>(&'a self) -> ExclusiveGuard<'a, T> { - let guard = self.lock.lock(); - let data = &mut *self.data.get(); - - ExclusiveGuard { - _data: data, - _guard: guard, - } - } -} - -impl<'a, T: Send> ExclusiveGuard<'a, T> { - // The unsafety here should be ok because our loan guarantees that the lock - // itself is not moving - pub fn signal(&self) { - unsafe { self._guard.signal() } - } - pub fn wait(&self) { - unsafe { self._guard.wait() } - } -} - -impl<'a, T: Send> Deref<T> for ExclusiveGuard<'a, T> { - fn deref(&self) -> &T { &*self._data } -} -impl<'a, T: Send> DerefMut<T> for ExclusiveGuard<'a, T> { - fn deref_mut(&mut self) -> &mut T { &mut *self._data } -} - -#[cfg(test)] -mod tests { - use prelude::*; - use sync::Arc; - use super::Exclusive; - use task; - - #[test] - fn exclusive_new_arc() { - unsafe { - let mut futures = Vec::new(); - - let num_tasks = 10; - let count = 10; - - let total = Arc::new(Exclusive::new(box 0)); - - for _ in range(0u, num_tasks) { - let total = total.clone(); - let (tx, rx) = channel(); - futures.push(rx); - - task::spawn(move || { - for _ in range(0u, count) { - **total.lock() += 1; - } - tx.send(()); - }); - }; - - for f in futures.iter_mut() { f.recv() } - - assert_eq!(**total.lock(), num_tasks * count); - } - } -} diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index e877dd5c6aa..68aaa1b3ae5 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -23,14 +23,10 @@ #![allow(dead_code)] -use os; -use thunk::Thunk; use kinds::Send; -use thread::Thread; use ops::FnOnce; use sys; -use sys_common; -use sys_common::thread_info::{mod, NewThread}; +use thunk::Thunk; // Reexport some of our utilities which are expected by other crates. pub use self::util::{default_sched_threads, min_stack, running_on_valgrind}; @@ -65,9 +61,14 @@ const OS_DEFAULT_STACK_ESTIMATE: uint = 2 * (1 << 20); #[cfg(not(test))] #[lang = "start"] fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int { + use prelude::v1::*; + use mem; - use prelude::*; + use os; use rt; + use sys_common::thread_info::{mod, NewThread}; + use sys_common; + use thread::Thread; let something_around_the_top_of_the_stack = 1; let addr = &something_around_the_top_of_the_stack as *const int; diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs deleted file mode 100644 index 41e91d1b6ef..00000000000 --- a/src/libstd/rt/task.rs +++ /dev/null @@ -1,554 +0,0 @@ -// Copyright 2013-2014 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. - -//! Language-level runtime services that should reasonably expected -//! to be available 'everywhere'. Unwinding, local storage, and logging. -//! Even a 'freestanding' Rust would likely want to implement this. - -pub use self::BlockedTask::*; -use self::TaskState::*; - -use any::Any; -use boxed::Box; -use sync::Arc; -use sync::atomic::{AtomicUint, SeqCst}; -use iter::{IteratorExt, Take}; -use kinds::marker; -use mem; -use ops::FnMut; -use core::prelude::{Clone, Drop, Err, Iterator, None, Ok, Option, Send, Some}; -use core::prelude::{drop}; -use str::SendStr; -use thunk::Thunk; - -use rt; -use rt::mutex::NativeMutex; -use rt::local::Local; -use rt::thread::{mod, Thread}; -use sys_common::stack; -use rt::unwind; -use rt::unwind::Unwinder; - -/// State associated with Rust threads -/// -/// This structure is currently undergoing major changes, and is -/// likely to be move/be merged with a `Thread` structure. -pub struct Task { - pub unwinder: Unwinder, - pub death: Death, - pub name: Option<SendStr>, - - state: TaskState, - lock: NativeMutex, // native synchronization - awoken: bool, // used to prevent spurious wakeups - - // This field holds the known bounds of the stack in (lo, hi) form. Not all - // native threads necessarily know their precise bounds, hence this is - // optional. - stack_bounds: (uint, uint), - - stack_guard: uint -} - -// Once a thread has entered the `Armed` state it must be destroyed via `drop`, -// and no other method. This state is used to track this transition. -#[deriving(PartialEq)] -enum TaskState { - New, - Armed, - Destroyed, -} - -pub struct TaskOpts { - /// Invoke this procedure with the result of the thread when it finishes. - pub on_exit: Option<Thunk<Result>>, - /// A name for the thread-to-be, for identification in panic messages - pub name: Option<SendStr>, - /// The size of the stack for the spawned thread - pub stack_size: Option<uint>, -} - -/// Indicates the manner in which a thread exited. -/// -/// A thread that completes without panicking is considered to exit successfully. -/// -/// If you wish for this result's delivery to block until all -/// children threads complete, recommend using a result future. -pub type Result = ::core::result::Result<(), Box<Any + Send>>; - -/// A handle to a blocked thread. Usually this means having the Box<Task> -/// pointer by ownership, but if the thread is killable, a killer can steal it -/// at any time. -pub enum BlockedTask { - Owned(Box<Task>), - Shared(Arc<AtomicUint>), -} - -/// Per-thread state related to thread death, killing, panic, etc. -pub struct Death { - pub on_exit: Option<Thunk<Result>>, -} - -pub struct BlockedTasks { - inner: Arc<AtomicUint>, -} - -impl Task { - /// Creates a new uninitialized thread. - pub fn new(stack_bounds: Option<(uint, uint)>, stack_guard: Option<uint>) -> Task { - Task { - unwinder: Unwinder::new(), - death: Death::new(), - state: New, - name: None, - lock: unsafe { NativeMutex::new() }, - awoken: false, - // these *should* get overwritten - stack_bounds: stack_bounds.unwrap_or((0, 0)), - stack_guard: stack_guard.unwrap_or(0) - } - } - - pub fn spawn<F>(opts: TaskOpts, f: F) - where F : FnOnce(), F : Send - { - Task::spawn_thunk(opts, Thunk::new(f)) - } - - fn spawn_thunk(opts: TaskOpts, f: Thunk) { - let TaskOpts { name, stack_size, on_exit } = opts; - - let mut task = box Task::new(None, None); - task.name = name; - task.death.on_exit = on_exit; - - let stack = stack_size.unwrap_or(rt::min_stack()); - - // Spawning a new OS thread guarantees that __morestack will never get - // triggered, but we must manually set up the actual stack bounds once - // this function starts executing. This raises the lower limit by a bit - // because by the time that this function is executing we've already - // consumed at least a little bit of stack (we don't know the exact byte - // address at which our stack started). - Thread::spawn_stack(stack, move|| { - let something_around_the_top_of_the_stack = 1; - let addr = &something_around_the_top_of_the_stack as *const int; - let my_stack = addr as uint; - unsafe { - stack::record_os_managed_stack_bounds(my_stack - stack + 1024, - my_stack); - } - task.stack_guard = thread::current_guard_page(); - task.stack_bounds = (my_stack - stack + 1024, my_stack); - - let mut f = Some(f); - drop(task.run(|| { f.take().unwrap().invoke(()) }).destroy()); - }) - } - - /// Consumes ownership of a thread, runs some code, and returns the thread back. - /// - /// This function can be used as an emulated "try/catch" to interoperate - /// with the rust runtime at the outermost boundary. It is not possible to - /// use this function in a nested fashion (a try/catch inside of another - /// try/catch). Invoking this function is quite cheap. - /// - /// If the closure `f` succeeds, then the returned thread can be used again - /// for another invocation of `run`. If the closure `f` panics then `self` - /// will be internally destroyed along with all of the other associated - /// resources of this thread. The `on_exit` callback is invoked with the - /// cause of panic (not returned here). This can be discovered by querying - /// `is_destroyed()`. - /// - /// Note that it is possible to view partial execution of the closure `f` - /// because it is not guaranteed to run to completion, but this function is - /// guaranteed to return if it panicks. Care should be taken to ensure that - /// stack references made by `f` are handled appropriately. - /// - /// It is invalid to call this function with a thread that has been previously - /// destroyed via a failed call to `run`. - pub fn run<F>(mut self: Box<Task>, f: F) -> Box<Task> where F: FnOnce() { - assert!(!self.is_destroyed(), "cannot re-use a destroyed thread"); - - // First, make sure that no one else is in TLS. This does not allow - // recursive invocations of run(). If there's no one else, then - // relinquish ownership of ourselves back into TLS. - if Local::exists(None::<Task>) { - panic!("cannot run a thread recursively inside another"); - } - self.state = Armed; - Local::put(self); - - // There are two primary reasons that general try/catch is unsafe. The - // first is that we do not support nested try/catch. The above check for - // an existing thread in TLS is sufficient for this invariant to be - // upheld. The second is that unwinding while unwinding is not defined. - // We take care of that by having an 'unwinding' flag in the thread - // itself. For these reasons, this unsafety should be ok. - let result = unsafe { unwind::try(f) }; - - // After running the closure given return the thread back out if it ran - // successfully, or clean up the thread if it panicked. - let task: Box<Task> = Local::take(); - match result { - Ok(()) => task, - Err(cause) => { task.cleanup(Err(cause)) } - } - } - - /// Destroy all associated resources of this thread. - /// - /// This function will perform any necessary clean up to prepare the thread - /// for destruction. It is required that this is called before a `Task` - /// falls out of scope. - /// - /// The returned thread cannot be used for running any more code, but it may - /// be used to extract the runtime as necessary. - pub fn destroy(self: Box<Task>) -> Box<Task> { - if self.is_destroyed() { - self - } else { - self.cleanup(Ok(())) - } - } - - /// Cleans up a thread, processing the result of the thread as appropriate. - /// - /// This function consumes ownership of the thread, deallocating it once it's - /// done being processed. It is assumed that TLD and the local heap have - /// already been destroyed and/or annihilated. - fn cleanup(mut self: Box<Task>, result: Result) -> Box<Task> { - // After taking care of the data above, we need to transmit the result - // of this thread. - let what_to_do = self.death.on_exit.take(); - Local::put(self); - - // FIXME: this is running in a seriously constrained context. If this - // allocates TLD then it will likely abort the runtime. Similarly, - // if this panics, this will also likely abort the runtime. - // - // This closure is currently limited to a channel send via the - // standard library's thread interface, but this needs - // reconsideration to whether it's a reasonable thing to let a - // thread to do or not. - match what_to_do { - Some(f) => { f.invoke(result) } - None => { drop(result) } - } - - // Now that we're done, we remove the thread from TLS and flag it for - // destruction. - let mut task: Box<Task> = Local::take(); - task.state = Destroyed; - return task; - } - - /// Queries whether this can be destroyed or not. - pub fn is_destroyed(&self) -> bool { self.state == Destroyed } - - /// Deschedules the current thread, invoking `f` `amt` times. It is not - /// recommended to use this function directly, but rather communication - /// primitives in `std::comm` should be used. - // - // This function gets a little interesting. There are a few safety and - // ownership violations going on here, but this is all done in the name of - // shared state. Additionally, all of the violations are protected with a - // mutex, so in theory there are no races. - // - // The first thing we need to do is to get a pointer to the thread's internal - // mutex. This address will not be changing (because the thread is allocated - // on the heap). We must have this handle separately because the thread will - // have its ownership transferred to the given closure. We're guaranteed, - // however, that this memory will remain valid because *this* is the current - // thread's execution thread. - // - // The next weird part is where ownership of the thread actually goes. We - // relinquish it to the `f` blocking function, but upon returning this - // function needs to replace the thread back in TLS. There is no communication - // from the wakeup thread back to this thread about the thread pointer, and - // there's really no need to. In order to get around this, we cast the thread - // to a `uint` which is then used at the end of this function to cast back - // to a `Box<Task>` object. Naturally, this looks like it violates - // ownership semantics in that there may be two `Box<Task>` objects. - // - // The fun part is that the wakeup half of this implementation knows to - // "forget" the thread on the other end. This means that the awakening half of - // things silently relinquishes ownership back to this thread, but not in a - // way that the compiler can understand. The thread's memory is always valid - // for both threads because these operations are all done inside of a mutex. - // - // You'll also find that if blocking fails (the `f` function hands the - // BlockedTask back to us), we will `mem::forget` the handles. The - // reasoning for this is the same logic as above in that the thread silently - // transfers ownership via the `uint`, not through normal compiler - // semantics. - // - // On a mildly unrelated note, it should also be pointed out that OS - // condition variables are susceptible to spurious wakeups, which we need to - // be ready for. In order to accommodate for this fact, we have an extra - // `awoken` field which indicates whether we were actually woken up via some - // invocation of `reawaken`. This flag is only ever accessed inside the - // lock, so there's no need to make it atomic. - pub fn deschedule<F>(mut self: Box<Task>, times: uint, mut f: F) where - F: FnMut(BlockedTask) -> ::core::result::Result<(), BlockedTask>, - { - unsafe { - let me = &mut *self as *mut Task; - let task = BlockedTask::block(self); - - if times == 1 { - let guard = (*me).lock.lock(); - (*me).awoken = false; - match f(task) { - Ok(()) => { - while !(*me).awoken { - guard.wait(); - } - } - Err(task) => { mem::forget(task.wake()); } - } - } else { - let iter = task.make_selectable(times); - let guard = (*me).lock.lock(); - (*me).awoken = false; - - // Apply the given closure to all of the "selectable threads", - // bailing on the first one that produces an error. Note that - // care must be taken such that when an error is occurred, we - // may not own the thread, so we may still have to wait for the - // thread to become available. In other words, if thread.wake() - // returns `None`, then someone else has ownership and we must - // wait for their signal. - match iter.map(f).filter_map(|a| a.err()).next() { - None => {} - Some(task) => { - match task.wake() { - Some(task) => { - mem::forget(task); - (*me).awoken = true; - } - None => {} - } - } - } - while !(*me).awoken { - guard.wait(); - } - } - // put the thread back in TLS, and everything is as it once was. - Local::put(mem::transmute(me)); - } - } - - /// Wakes up a previously blocked thread. This function can only be - /// called on threads that were previously blocked in `deschedule`. - // - // See the comments on `deschedule` for why the thread is forgotten here, and - // why it's valid to do so. - pub fn reawaken(mut self: Box<Task>) { - unsafe { - let me = &mut *self as *mut Task; - mem::forget(self); - let guard = (*me).lock.lock(); - (*me).awoken = true; - guard.signal(); - } - } - - /// Yields control of this thread to another thread. This function will - /// eventually return, but possibly not immediately. This is used as an - /// opportunity to allow other threads a chance to run. - pub fn yield_now() { - Thread::yield_now(); - } - - /// Returns the stack bounds for this thread in (lo, hi) format. The stack - /// bounds may not be known for all threads, so the return value may be - /// `None`. - pub fn stack_bounds(&self) -> (uint, uint) { - self.stack_bounds - } - - /// Returns the stack guard for this thread, if known. - pub fn stack_guard(&self) -> Option<uint> { - if self.stack_guard != 0 { - Some(self.stack_guard) - } else { - None - } - } - - /// Consume this thread, flagging it as a candidate for destruction. - /// - /// This function is required to be invoked to destroy a thread. A thread - /// destroyed through a normal drop will abort. - pub fn drop(mut self) { - self.state = Destroyed; - } -} - -impl Drop for Task { - fn drop(&mut self) { - rtdebug!("called drop for a thread: {}", self as *mut Task as uint); - rtassert!(self.state != Armed); - } -} - -impl TaskOpts { - pub fn new() -> TaskOpts { - TaskOpts { on_exit: None, name: None, stack_size: None } - } -} - -impl Iterator<BlockedTask> for BlockedTasks { - fn next(&mut self) -> Option<BlockedTask> { - Some(Shared(self.inner.clone())) - } -} - -impl BlockedTask { - /// Returns Some if the thread was successfully woken; None if already killed. - pub fn wake(self) -> Option<Box<Task>> { - match self { - Owned(task) => Some(task), - Shared(arc) => { - match arc.swap(0, SeqCst) { - 0 => None, - n => Some(unsafe { mem::transmute(n) }), - } - } - } - } - - /// Reawakens this thread if ownership is acquired. If finer-grained control - /// is desired, use `wake` instead. - pub fn reawaken(self) { - self.wake().map(|t| t.reawaken()); - } - - // This assertion has two flavours because the wake involves an atomic op. - // In the faster version, destructors will panic dramatically instead. - #[cfg(not(test))] pub fn trash(self) { } - #[cfg(test)] pub fn trash(self) { assert!(self.wake().is_none()); } - - /// Create a blocked thread, unless the thread was already killed. - pub fn block(task: Box<Task>) -> BlockedTask { - Owned(task) - } - - /// Converts one blocked thread handle to a list of many handles to the same. - pub fn make_selectable(self, num_handles: uint) -> Take<BlockedTasks> { - let arc = match self { - Owned(task) => { - let flag = unsafe { AtomicUint::new(mem::transmute(task)) }; - Arc::new(flag) - } - Shared(arc) => arc.clone(), - }; - BlockedTasks{ inner: arc }.take(num_handles) - } - - /// Convert to an unsafe uint value. Useful for storing in a pipe's state - /// flag. - #[inline] - pub unsafe fn cast_to_uint(self) -> uint { - match self { - Owned(task) => { - let blocked_task_ptr: uint = mem::transmute(task); - rtassert!(blocked_task_ptr & 0x1 == 0); - blocked_task_ptr - } - Shared(arc) => { - let blocked_task_ptr: uint = mem::transmute(box arc); - rtassert!(blocked_task_ptr & 0x1 == 0); - blocked_task_ptr | 0x1 - } - } - } - - /// Convert from an unsafe uint value. Useful for retrieving a pipe's state - /// flag. - #[inline] - pub unsafe fn cast_from_uint(blocked_task_ptr: uint) -> BlockedTask { - if blocked_task_ptr & 0x1 == 0 { - Owned(mem::transmute(blocked_task_ptr)) - } else { - let ptr: Box<Arc<AtomicUint>> = - mem::transmute(blocked_task_ptr & !1); - Shared(*ptr) - } - } -} - -impl Death { - pub fn new() -> Death { - Death { on_exit: None } - } -} - -#[cfg(test)] -mod test { - use super::*; - use prelude::*; - use task; - use rt::unwind; - - #[test] - fn unwind() { - let result = task::try(move|| ()); - rtdebug!("trying first assert"); - assert!(result.is_ok()); - let result = task::try(move|| -> () panic!()); - rtdebug!("trying second assert"); - assert!(result.is_err()); - } - - #[test] - fn rng() { - use rand::{StdRng, Rng}; - let mut r = StdRng::new().ok().unwrap(); - let _ = r.next_u32(); - } - - #[test] - fn comm_stream() { - let (tx, rx) = channel(); - tx.send(10i); - assert!(rx.recv() == 10); - } - - #[test] - fn comm_shared_chan() { - let (tx, rx) = channel(); - tx.send(10i); - assert!(rx.recv() == 10); - } - - #[test] - #[should_fail] - fn test_begin_unwind() { - use rt::unwind::begin_unwind; - begin_unwind("cause", &(file!(), line!())) - } - - #[test] - fn drop_new_task_ok() { - drop(Task::new(None, None)); - } - - // Thread blocking tests - - #[test] - fn block_and_wake() { - let task = box Task::new(None, None); - let task = BlockedTask::block(task).wake().unwrap(); - task.drop(); - } -} diff --git a/src/libstd/rt/unwind.rs b/src/libstd/rt/unwind.rs index e0c512706e6..6f6be2e111d 100644 --- a/src/libstd/rt/unwind.rs +++ b/src/libstd/rt/unwind.rs @@ -57,7 +57,7 @@ //! //! Currently Rust uses unwind runtime provided by libgcc. -use prelude::*; +use prelude::v1::*; use any::Any; use cell::Cell; @@ -84,15 +84,15 @@ pub type Callback = fn(msg: &(Any + Send), file: &'static str, line: uint); // For more information, see below. const MAX_CALLBACKS: uint = 16; static CALLBACKS: [atomic::AtomicUint; MAX_CALLBACKS] = - [atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT, - atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT, - atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT, - atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT, - atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT, - atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT, - atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT, - atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT]; -static CALLBACK_CNT: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT; + [atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT, + atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT, + atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT, + atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT, + atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT, + atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT, + atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT, + atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT]; +static CALLBACK_CNT: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT; thread_local! { static PANICKING: Cell<bool> = Cell::new(false) } @@ -493,27 +493,16 @@ pub extern fn rust_begin_unwind(msg: fmt::Arguments, /// the actual formatting into this shared place. #[inline(never)] #[cold] pub fn begin_unwind_fmt(msg: fmt::Arguments, file_line: &(&'static str, uint)) -> ! { - use fmt::FormatWriter; + use fmt::Writer; // We do two allocations here, unfortunately. But (a) they're // required with the current scheme, and (b) we don't handle // panic + OOM properly anyway (see comment in begin_unwind // below). - struct VecWriter<'a> { v: &'a mut Vec<u8> } - - impl<'a> fmt::FormatWriter for VecWriter<'a> { - fn write(&mut self, buf: &[u8]) -> fmt::Result { - self.v.push_all(buf); - Ok(()) - } - } - - let mut v = Vec::new(); - let _ = write!(&mut VecWriter { v: &mut v }, "{}", msg); - - let msg = box String::from_utf8_lossy(v.as_slice()).into_owned(); - begin_unwind_inner(msg, file_line) + let mut s = String::new(); + let _ = write!(&mut s, "{}", msg); + begin_unwind_inner(box s, file_line) } /// This is the entry point of unwinding for panic!() and assert!(). @@ -544,7 +533,7 @@ fn begin_unwind_inner(msg: Box<Any + Send>, file_line: &(&'static str, uint)) -> // Make sure the default failure handler is registered before we look at the // callbacks. static INIT: Once = ONCE_INIT; - INIT.doit(|| unsafe { register(failure::on_fail); }); + INIT.call_once(|| unsafe { register(failure::on_fail); }); // First, invoke call the user-defined callbacks triggered on thread panic. // diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs index fee86e33455..09859cab536 100644 --- a/src/libstd/rt/util.rs +++ b/src/libstd/rt/util.rs @@ -10,13 +10,12 @@ // // ignore-lexer-test FIXME #15677 -use prelude::*; +use prelude::v1::*; use cmp; use fmt; use intrinsics; -use libc::uintptr_t; -use libc; +use libc::{mod, uintptr_t}; use os; use slice; use str; @@ -47,7 +46,7 @@ pub fn limit_thread_creation_due_to_osx_and_valgrind() -> bool { } pub fn min_stack() -> uint { - static MIN: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT; + static MIN: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT; match MIN.load(atomic::SeqCst) { 0 => {} n => return n - 1, @@ -96,8 +95,8 @@ pub const Stdout: Stdio = Stdio(libc::STDOUT_FILENO); #[allow(non_upper_case_globals)] pub const Stderr: Stdio = Stdio(libc::STDERR_FILENO); -impl fmt::FormatWriter for Stdio { - fn write(&mut self, data: &[u8]) -> fmt::Result { +impl Stdio { + pub fn write_bytes(&mut self, data: &[u8]) { #[cfg(unix)] type WriteLen = libc::size_t; #[cfg(windows)] @@ -108,6 +107,12 @@ impl fmt::FormatWriter for Stdio { data.as_ptr() as *const libc::c_void, data.len() as WriteLen); } + } +} + +impl fmt::Writer for Stdio { + fn write_str(&mut self, data: &str) -> fmt::Result { + self.write_bytes(data.as_bytes()); Ok(()) // yes, we're lying } } @@ -117,16 +122,16 @@ pub fn dumb_print(args: fmt::Arguments) { } pub fn abort(args: fmt::Arguments) -> ! { - use fmt::FormatWriter; + use fmt::Writer; struct BufWriter<'a> { buf: &'a mut [u8], pos: uint, } - impl<'a> FormatWriter for BufWriter<'a> { - fn write(&mut self, bytes: &[u8]) -> fmt::Result { + impl<'a> fmt::Writer for BufWriter<'a> { + fn write_str(&mut self, bytes: &str) -> fmt::Result { let left = self.buf.slice_from_mut(self.pos); - let to_write = bytes[..cmp::min(bytes.len(), left.len())]; + let to_write = bytes.as_bytes()[..cmp::min(bytes.len(), left.len())]; slice::bytes::copy_memory(left, to_write); self.pos += to_write.len(); Ok(()) diff --git a/src/libstd/sync/atomic.rs b/src/libstd/sync/atomic.rs index 18c917aca8a..d4d7607bde3 100644 --- a/src/libstd/sync/atomic.rs +++ b/src/libstd/sync/atomic.rs @@ -86,15 +86,15 @@ //! Keep a global count of live tasks: //! //! ``` -//! use std::sync::atomic::{AtomicUint, SeqCst, INIT_ATOMIC_UINT}; +//! use std::sync::atomic::{AtomicUint, SeqCst, ATOMIC_UINT_INIT}; //! -//! static GLOBAL_TASK_COUNT: AtomicUint = INIT_ATOMIC_UINT; +//! static GLOBAL_TASK_COUNT: AtomicUint = ATOMIC_UINT_INIT; //! //! let old_task_count = GLOBAL_TASK_COUNT.fetch_add(1, SeqCst); //! println!("live tasks: {}", old_task_count + 1); //! ``` -#![allow(deprecated)] +#![stable] use alloc::boxed::Box; use core::mem; @@ -102,6 +102,7 @@ use core::prelude::{Send, Drop, None, Option, Some}; pub use core::atomic::{AtomicBool, AtomicInt, AtomicUint, AtomicPtr}; pub use core::atomic::{INIT_ATOMIC_BOOL, INIT_ATOMIC_INT, INIT_ATOMIC_UINT}; +pub use core::atomic::{ATOMIC_BOOL_INIT, ATOMIC_INT_INIT, ATOMIC_UINT_INIT}; pub use core::atomic::fence; pub use core::atomic::Ordering::{mod, Relaxed, Release, Acquire, AcqRel, SeqCst}; @@ -116,6 +117,7 @@ pub struct AtomicOption<T> { p: AtomicUint, } +#[allow(deprecated)] impl<T: Send> AtomicOption<T> { /// Create a new `AtomicOption` pub fn new(p: Box<T>) -> AtomicOption<T> { @@ -180,7 +182,7 @@ impl<T: Send> Drop for AtomicOption<T> { #[cfg(test)] mod test { - use prelude::{Some, None}; + use prelude::v1::*; use super::*; #[test] diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs index 4091f0df395..bf5da3e7cba 100644 --- a/src/libstd/sync/barrier.rs +++ b/src/libstd/sync/barrier.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use kinds::{Send, Sync}; use sync::{Mutex, Condvar}; /// A barrier enables multiple tasks to synchronize the beginning @@ -30,29 +29,32 @@ use sync::{Mutex, Condvar}; /// }).detach(); /// } /// ``` +#[stable] pub struct Barrier { lock: Mutex<BarrierState>, cvar: Condvar, num_threads: uint, } -unsafe impl Send for Barrier {} -unsafe impl Sync for Barrier {} - // The inner state of a double barrier struct BarrierState { count: uint, generation_id: uint, } -unsafe impl Send for BarrierState {} -unsafe impl Sync for BarrierState {} +/// A result returned from wait. +/// +/// Currently this opaque structure only has one method, `.is_leader()`. Only +/// one thread will receive a result that will return `true` from this function. +#[allow(missing_copy_implementations)] +pub struct BarrierWaitResult(bool); impl Barrier { /// Create a new barrier that can block a given number of threads. /// /// A barrier will block `n`-1 threads which call `wait` and then wake up /// all threads at once when the `n`th thread calls `wait`. + #[stable] pub fn new(n: uint) -> Barrier { Barrier { lock: Mutex::new(BarrierState { @@ -68,7 +70,13 @@ impl Barrier { /// /// Barriers are re-usable after all threads have rendezvoused once, and can /// be used continuously. - pub fn wait(&self) { + /// + /// A single (arbitrary) thread will receive a `BarrierWaitResult` that + /// returns `true` from `is_leader` when returning from this function, and + /// all other threads will receive a result that will return `false` from + /// `is_leader` + #[stable] + pub fn wait(&self) -> BarrierWaitResult { let mut lock = self.lock.lock().unwrap(); let local_gen = lock.generation_id; lock.count += 1; @@ -79,46 +87,64 @@ impl Barrier { lock.count < self.num_threads { lock = self.cvar.wait(lock).unwrap(); } + BarrierWaitResult(false) } else { lock.count = 0; lock.generation_id += 1; self.cvar.notify_all(); + BarrierWaitResult(true) } } } +impl BarrierWaitResult { + /// Return whether this thread from `wait` is the "leader thread". + /// + /// Only one thread will have `true` returned from their result, all other + /// threads will have `false` returned. + #[stable] + pub fn is_leader(&self) -> bool { self.0 } +} + #[cfg(test)] mod tests { - use prelude::*; + use prelude::v1::*; use sync::{Arc, Barrier}; - use comm::Empty; + use sync::mpsc::{channel, TryRecvError}; + use thread::Thread; #[test] fn test_barrier() { - let barrier = Arc::new(Barrier::new(10)); + const N: uint = 10; + + let barrier = Arc::new(Barrier::new(N)); let (tx, rx) = channel(); - for _ in range(0u, 9) { + for _ in range(0u, N - 1) { let c = barrier.clone(); let tx = tx.clone(); - spawn(move|| { - c.wait(); - tx.send(true); - }); + Thread::spawn(move|| { + tx.send(c.wait().is_leader()).unwrap(); + }).detach(); } // At this point, all spawned tasks should be blocked, // so we shouldn't get anything from the port assert!(match rx.try_recv() { - Err(Empty) => true, + Err(TryRecvError::Empty) => true, _ => false, }); - barrier.wait(); + let mut leader_found = barrier.wait().is_leader(); + // Now, the barrier is cleared and we should get data. - for _ in range(0u, 9) { - rx.recv(); + for _ in range(0u, N - 1) { + if rx.recv().unwrap() { + assert!(!leader_found); + leader_found = true; + } } + assert!(leader_found); } } diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index 15faf5be258..19b8f5e62cf 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use prelude::*; +use prelude::v1::*; use sync::atomic::{mod, AtomicUint}; use sync::poison::{mod, LockResult}; @@ -88,7 +88,7 @@ unsafe impl Sync for StaticCondvar {} #[unstable = "may be merged with Condvar in the future"] pub const CONDVAR_INIT: StaticCondvar = StaticCondvar { inner: sys::CONDVAR_INIT, - mutex: atomic::INIT_ATOMIC_UINT, + mutex: atomic::ATOMIC_UINT_INIT, }; impl Condvar { @@ -279,11 +279,13 @@ impl StaticCondvar { #[cfg(test)] mod tests { - use prelude::*; + use prelude::v1::*; - use time::Duration; use super::{StaticCondvar, CONDVAR_INIT}; + use sync::mpsc::channel; use sync::{StaticMutex, MUTEX_INIT, Condvar, Mutex, Arc}; + use thread::Thread; + use time::Duration; #[test] fn smoke() { @@ -306,7 +308,7 @@ mod tests { static M: StaticMutex = MUTEX_INIT; let g = M.lock().unwrap(); - spawn(move|| { + let _t = Thread::spawn(move|| { let _g = M.lock().unwrap(); C.notify_one(); }); @@ -324,30 +326,30 @@ mod tests { for _ in range(0, N) { let data = data.clone(); let tx = tx.clone(); - spawn(move|| { + Thread::spawn(move|| { let &(ref lock, ref cond) = &*data; let mut cnt = lock.lock().unwrap(); *cnt += 1; if *cnt == N { - tx.send(()); + tx.send(()).unwrap(); } while *cnt != 0 { cnt = cond.wait(cnt).unwrap(); } - tx.send(()); - }); + tx.send(()).unwrap(); + }).detach(); } drop(tx); let &(ref lock, ref cond) = &*data; - rx.recv(); + rx.recv().unwrap(); let mut cnt = lock.lock().unwrap(); *cnt = 0; cond.notify_all(); drop(cnt); for _ in range(0, N) { - rx.recv(); + rx.recv().unwrap(); } } @@ -359,7 +361,7 @@ mod tests { let g = M.lock().unwrap(); let (g, success) = C.wait_timeout(g, Duration::nanoseconds(1000)).unwrap(); assert!(!success); - spawn(move|| { + let _t = Thread::spawn(move || { let _g = M.lock().unwrap(); C.notify_one(); }); @@ -377,14 +379,13 @@ mod tests { static C: StaticCondvar = CONDVAR_INIT; let mut g = M1.lock().unwrap(); - spawn(move|| { + let _t = Thread::spawn(move|| { let _g = M1.lock().unwrap(); C.notify_one(); }); g = C.wait(g).unwrap(); drop(g); - C.wait(M2.lock().unwrap()).unwrap(); - + let _ = C.wait(M2.lock().unwrap()).unwrap(); } } diff --git a/src/libstd/sync/future.rs b/src/libstd/sync/future.rs index 51899a87a32..e5245251ea8 100644 --- a/src/libstd/sync/future.rs +++ b/src/libstd/sync/future.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! A type representing values that may be computed concurrently and operations for working with -//! them. +//! A type representing values that may be computed concurrently and operations +//! for working with them. //! //! # Example //! @@ -23,12 +23,15 @@ //! ``` #![allow(missing_docs)] +#![unstable = "futures as-is have yet to be deeply reevaluated with recent \ + core changes to Rust's synchronization story, and will likely \ + become stable in the future but are unstable until that time"] use core::prelude::*; use core::mem::replace; use self::FutureState::*; -use comm::{Receiver, channel}; +use sync::mpsc::{Receiver, channel}; use thunk::{Thunk}; use thread::Thread; @@ -122,8 +125,8 @@ impl<A:Send> Future<A> { * waiting for the result to be received on the port. */ - Future::from_fn(move|:| { - rx.recv() + Future::from_fn(move |:| { + rx.recv().unwrap() }) } @@ -141,7 +144,7 @@ impl<A:Send> Future<A> { Thread::spawn(move |:| { // Don't panic if the other end has hung up - let _ = tx.send_opt(blk()); + let _ = tx.send(blk()); }).detach(); Future::from_receiver(rx) @@ -150,9 +153,10 @@ impl<A:Send> Future<A> { #[cfg(test)] mod test { - use prelude::*; + use prelude::v1::*; + use sync::mpsc::channel; use sync::Future; - use task; + use thread::Thread; #[test] fn test_from_value() { @@ -163,7 +167,7 @@ mod test { #[test] fn test_from_receiver() { let (tx, rx) = channel(); - tx.send("whale".to_string()); + tx.send("whale".to_string()).unwrap(); let mut f = Future::from_receiver(rx); assert_eq!(f.get(), "whale"); } @@ -183,7 +187,7 @@ mod test { #[test] fn test_interface_unwrap() { let f = Future::from_value("fail".to_string()); - assert_eq!(f.unwrap(), "fail"); + assert_eq!(f.into_inner(), "fail"); } #[test] @@ -210,10 +214,10 @@ mod test { let expected = "schlorf"; let (tx, rx) = channel(); let f = Future::spawn(move|| { expected }); - task::spawn(move|| { + let _t = Thread::spawn(move|| { let mut f = f; - tx.send(f.get()); + tx.send(f.get()).unwrap(); }); - assert_eq!(rx.recv(), expected); + assert_eq!(rx.recv().unwrap(), expected); } } diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index 092acc7ff25..c09c3b45d3e 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -26,13 +26,15 @@ pub use self::rwlock::{RWLockReadGuard, RWLockWriteGuard}; pub use self::condvar::{Condvar, StaticCondvar, CONDVAR_INIT}; pub use self::once::{Once, ONCE_INIT}; pub use self::semaphore::{Semaphore, SemaphoreGuard}; -pub use self::barrier::Barrier; +pub use self::barrier::{Barrier, BarrierWaitResult}; pub use self::poison::{PoisonError, TryLockError, TryLockResult, LockResult}; pub use self::future::Future; pub use self::task_pool::TaskPool; pub mod atomic; +pub mod mpsc; + mod barrier; mod condvar; mod future; diff --git a/src/libstd/comm/blocking.rs b/src/libstd/sync/mpsc/blocking.rs index 412b7161305..a5299012723 100644 --- a/src/libstd/comm/blocking.rs +++ b/src/libstd/sync/mpsc/blocking.rs @@ -11,7 +11,7 @@ //! Generic support for building blocking abstractions. use thread::Thread; -use sync::atomic::{AtomicBool, INIT_ATOMIC_BOOL, Ordering}; +use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering}; use sync::Arc; use kinds::{Sync, Send}; use kinds::marker::{NoSend, NoSync}; @@ -40,7 +40,7 @@ pub struct WaitToken { pub fn tokens() -> (WaitToken, SignalToken) { let inner = Arc::new(Inner { thread: Thread::current(), - woken: INIT_ATOMIC_BOOL, + woken: ATOMIC_BOOL_INIT, }); let wait_token = WaitToken { inner: inner.clone(), diff --git a/src/libstd/comm/mod.rs b/src/libstd/sync/mpsc/mod.rs index a405627aecc..413675f26d5 100644 --- a/src/libstd/comm/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -8,12 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Communication primitives for concurrent tasks -//! -//! Rust makes it very difficult to share data among tasks to prevent race -//! conditions and to improve parallelism, but there is often a need for -//! communication between concurrent tasks. The primitives defined in this -//! module are the building blocks for synchronization in rust. +//! Multi-producer, single-consumer communication primitives threads //! //! This module provides message-based communication over channels, concretely //! defined among three types: @@ -23,12 +18,10 @@ //! * `Receiver` //! //! A `Sender` or `SyncSender` is used to send data to a `Receiver`. Both -//! senders are clone-able such that many tasks can send simultaneously to one -//! receiver. These channels are *task blocking*, not *thread blocking*. This -//! means that if one task is blocked on a channel, other tasks can continue to -//! make progress. +//! senders are clone-able (multi-producer) such that many threads can send +//! simultaneously to one receiver (single-consumer). These channels are //! -//! Rust channels come in one of two flavors: +//! These channels come in two flavors: //! //! 1. An asynchronous, infinitely buffered channel. The `channel()` function //! will return a `(Sender, Receiver)` tuple where all sends will be @@ -43,36 +36,39 @@ //! "rendezvous" channel where each sender atomically hands off a message to //! a receiver. //! -//! ## Panic Propagation +//! ## Disconnection //! -//! In addition to being a core primitive for communicating in rust, channels -//! are the points at which panics are propagated among tasks. Whenever the one -//! half of channel is closed, the other half will have its next operation -//! `panic!`. The purpose of this is to allow propagation of panics among tasks -//! that are linked to one another via channels. +//! The send and receive operations on channels will all return a `Result` +//! indicating whether the operation succeeded or not. An unsuccessful operation +//! is normally indicative of the other half of a channel having "hung up" by +//! being dropped in its corresponding thread. //! -//! There are methods on both of senders and receivers to perform their -//! respective operations without panicking, however. +//! Once half of a channel has been deallocated, most operations can no longer +//! continue to make progress, so `Err` will be returned. Many applications will +//! continue to `unwrap()` the results returned from this module, instigating a +//! propagation of failure among threads if one unexpectedly dies. //! -//! # Example +//! # Examples //! //! Simple usage: //! //! ``` //! use std::thread::Thread; +//! use std::sync::mpsc::channel; //! //! // Create a simple streaming channel //! let (tx, rx) = channel(); //! Thread::spawn(move|| { -//! tx.send(10i); +//! tx.send(10i).unwrap(); //! }).detach(); -//! assert_eq!(rx.recv(), 10i); +//! assert_eq!(rx.recv().unwrap(), 10i); //! ``` //! //! Shared usage: //! //! ``` //! use std::thread::Thread; +//! use std::sync::mpsc::channel; //! //! // Create a shared channel that can be sent along from many threads //! // where tx is the sending half (tx for transmission), and rx is the receiving @@ -81,37 +77,40 @@ //! for i in range(0i, 10i) { //! let tx = tx.clone(); //! Thread::spawn(move|| { -//! tx.send(i); +//! tx.send(i).unwrap(); //! }).detach() //! } //! //! for _ in range(0i, 10i) { -//! let j = rx.recv(); +//! let j = rx.recv().unwrap(); //! assert!(0 <= j && j < 10); //! } //! ``` //! //! Propagating panics: //! -//! ```should_fail -//! // The call to recv() will panic!() because the channel has already hung -//! // up (or been deallocated) +//! ``` +//! use std::sync::mpsc::channel; +//! +//! // The call to recv() will return an error because the channel has already +//! // hung up (or been deallocated) //! let (tx, rx) = channel::<int>(); //! drop(tx); -//! rx.recv(); +//! assert!(rx.recv().is_err()); //! ``` //! //! Synchronous channels: //! //! ``` //! use std::thread::Thread; +//! use std::sync::mpsc::sync_channel; //! //! let (tx, rx) = sync_channel::<int>(0); //! Thread::spawn(move|| { //! // This will wait for the parent task to start receiving -//! tx.send(53); +//! tx.send(53).unwrap(); //! }).detach(); -//! rx.recv(); +//! rx.recv().unwrap(); //! ``` //! //! Reading from a channel with a timeout requires to use a Timer together @@ -120,6 +119,7 @@ //! after 10 seconds no matter what: //! //! ```no_run +//! use std::sync::mpsc::channel; //! use std::io::timer::Timer; //! use std::time::Duration; //! @@ -129,8 +129,8 @@ //! //! loop { //! select! { -//! val = rx.recv() => println!("Received {}", val), -//! () = timeout.recv() => { +//! val = rx.recv() => println!("Received {}", val.unwrap()), +//! _ = timeout.recv() => { //! println!("timed out, total time was more than 10 seconds"); //! break; //! } @@ -143,6 +143,7 @@ //! has been inactive for 5 seconds: //! //! ```no_run +//! use std::sync::mpsc::channel; //! use std::io::timer::Timer; //! use std::time::Duration; //! @@ -153,8 +154,8 @@ //! let timeout = timer.oneshot(Duration::seconds(5)); //! //! select! { -//! val = rx.recv() => println!("Received {}", val), -//! () = timeout.recv() => { +//! val = rx.recv() => println!("Received {}", val.unwrap()), +//! _ = timeout.recv() => { //! println!("timed out, no message received in 5 seconds"); //! break; //! } @@ -312,38 +313,19 @@ // And now that you've seen all the races that I found and attempted to fix, // here's the code for you to find some more! -use core::prelude::*; +use prelude::v1::*; -pub use self::TryRecvError::*; -pub use self::TrySendError::*; - -use alloc::arc::Arc; -use core::kinds; -use core::kinds::marker; -use core::mem; -use core::cell::UnsafeCell; +use sync::Arc; +use fmt; +use kinds::marker; +use mem; +use cell::UnsafeCell; pub use self::select::{Select, Handle}; use self::select::StartResult; use self::select::StartResult::*; use self::blocking::SignalToken; -macro_rules! test { - { fn $name:ident() $b:block $(#[$a:meta])*} => ( - mod $name { - #![allow(unused_imports)] - - use super::*; - use comm::*; - use thread::Thread; - use prelude::{Ok, Err, spawn, range, drop, Box, Some, None, Option}; - use prelude::{Vec, Buffer, from_str, Clone}; - - $(#[$a])* #[test] fn f() { $b } - } - ) -} - mod blocking; mod oneshot; mod select; @@ -355,7 +337,7 @@ mod spsc_queue; /// The receiving-half of Rust's channel type. This half can only be owned by /// one task -#[unstable] +#[stable] pub struct Receiver<T> { inner: UnsafeCell<Flavor<T>>, } @@ -367,14 +349,14 @@ unsafe impl<T:Send> Send for Receiver<T> { } /// An 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. -#[unstable] -pub struct Messages<'a, T:'a> { +#[stable] +pub struct Iter<'a, T:'a> { rx: &'a 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. -#[unstable] +#[stable] pub struct Sender<T> { inner: UnsafeCell<Flavor<T>>, } @@ -385,30 +367,50 @@ unsafe impl<T:Send> Send for Sender<T> { } /// The sending-half of Rust's synchronous channel type. This half can only be /// owned by one task, but it can be cloned to send to other tasks. -#[unstable = "this type may be renamed, but it will always exist"] +#[stable] pub struct SyncSender<T> { inner: Arc<RacyCell<sync::Packet<T>>>, // can't share in an arc _marker: marker::NoSync, } +/// An error returned from the `send` function on channels. +/// +/// A `send` operation can only fail if the receiving end of a channel is +/// disconnected, implying that the data could never be received. The error +/// contains the data being sent as a payload so it can be recovered. +#[deriving(PartialEq, Eq)] +#[stable] +pub struct SendError<T>(pub T); + +/// An error returned from the `recv` function on a `Receiver`. +/// +/// The `recv` operation can only fail if the sending half of a channel is +/// disconnected, implying that no further messages will ever be received. +#[deriving(PartialEq, Eq, Clone, Copy)] +#[stable] +pub struct RecvError; + /// This enumeration is the list of the possible reasons that try_recv could not /// return data when called. -#[deriving(PartialEq, Clone, Copy, Show)] -#[experimental = "this is likely to be removed in changing try_recv()"] +#[deriving(PartialEq, Clone, Copy)] +#[stable] pub enum TryRecvError { /// This channel is currently empty, but the sender(s) have not yet /// disconnected, so data may yet become available. + #[stable] Empty, + /// This channel's sending half has become disconnected, and there will /// never be any more data received on this channel + #[stable] Disconnected, } /// This enumeration is the list of the possible error outcomes for the /// `SyncSender::try_send` method. -#[deriving(PartialEq, Clone, Show)] -#[experimental = "this is likely to be removed in changing try_send()"] +#[deriving(PartialEq, Clone)] +#[stable] pub enum TrySendError<T> { /// The data could not be sent on the channel because it would require that /// the callee block to send the data. @@ -416,10 +418,13 @@ pub enum TrySendError<T> { /// If this is a buffered channel, then the buffer is full at this time. If /// this is not a buffered channel, then there is no receiver available to /// acquire the data. + #[stable] Full(T), + /// This channel's receiving half has disconnected, so the data could not be /// sent. The data is returned back to the callee in this case. - RecvDisconnected(T), + #[stable] + Disconnected(T), } enum Flavor<T> { @@ -458,6 +463,7 @@ impl<T> UnsafeFlavor<T> for Receiver<T> { /// # Example /// /// ``` +/// use std::sync::mpsc::channel; /// use std::thread::Thread; /// /// // tx is is the sending half (tx for transmission), and rx is the receiving @@ -467,15 +473,15 @@ impl<T> UnsafeFlavor<T> for Receiver<T> { /// // Spawn off an expensive computation /// Thread::spawn(move|| { /// # fn expensive_computation() {} -/// tx.send(expensive_computation()); +/// tx.send(expensive_computation()).unwrap(); /// }).detach(); /// /// // Do some useful work for awhile /// /// // Let's see what that answer was -/// println!("{}", rx.recv()); +/// println!("{}", rx.recv().unwrap()); /// ``` -#[unstable] +#[stable] pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) { let a = Arc::new(RacyCell::new(oneshot::Packet::new())); (Sender::new(Flavor::Oneshot(a.clone())), Receiver::new(Flavor::Oneshot(a))) @@ -499,23 +505,23 @@ pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) { /// # Example /// /// ``` +/// use std::sync::mpsc::sync_channel; /// use std::thread::Thread; /// /// let (tx, rx) = sync_channel(1); /// /// // this returns immediately -/// tx.send(1i); +/// tx.send(1i).unwrap(); /// /// Thread::spawn(move|| { /// // this will block until the previous message has been received -/// tx.send(2i); +/// tx.send(2i).unwrap(); /// }).detach(); /// -/// assert_eq!(rx.recv(), 1i); -/// assert_eq!(rx.recv(), 2i); +/// assert_eq!(rx.recv().unwrap(), 1i); +/// assert_eq!(rx.recv().unwrap(), 2i); /// ``` -#[unstable = "this function may be renamed to more accurately reflect the type \ - of channel that is is creating"] +#[stable] pub fn sync_channel<T: Send>(bound: uint) -> (SyncSender<T>, Receiver<T>) { let a = Arc::new(RacyCell::new(sync::Packet::new(bound))); (SyncSender::new(a.clone()), Receiver::new(Flavor::Sync(a))) @@ -532,33 +538,6 @@ impl<T: Send> Sender<T> { } } - /// Sends a value along this channel to be received by the corresponding - /// receiver. - /// - /// Rust channels are infinitely buffered so this method will never block. - /// - /// # Panics - /// - /// This function will panic if the other end of the channel has hung up. - /// This means that if the corresponding receiver has fallen out of scope, - /// this function will trigger a panic message saying that a message is - /// being sent on a closed channel. - /// - /// Note that if this function does *not* panic, it does not mean that the - /// data will be successfully received. All sends are placed into a queue, - /// so it is possible for a send to succeed (the other end is alive), but - /// then the other end could immediately disconnect. - /// - /// The purpose of this functionality is to propagate panics among tasks. - /// If a panic is not desired, then consider using the `send_opt` method - #[experimental = "this function is being considered candidate for removal \ - to adhere to the general guidelines of rust"] - pub fn send(&self, t: T) { - if self.send_opt(t).is_err() { - panic!("sending on a closed channel"); - } - } - /// Attempts to send a value on this channel, returning it back if it could /// not be sent. /// @@ -570,37 +549,34 @@ impl<T: Send> Sender<T> { /// will be received. It is possible for the corresponding receiver to /// hang up immediately after this function returns `Ok`. /// - /// Like `send`, this method will never block. - /// - /// # Panics - /// - /// This method will never panic, it will return the message back to the - /// caller if the other end is disconnected + /// This method will never block the current thread. /// /// # Example /// /// ``` + /// use std::sync::mpsc::channel; + /// /// let (tx, rx) = channel(); /// /// // This send is always successful - /// assert_eq!(tx.send_opt(1i), Ok(())); + /// tx.send(1i).unwrap(); /// /// // This send will fail because the receiver is gone /// drop(rx); - /// assert_eq!(tx.send_opt(1i), Err(1)); + /// assert_eq!(tx.send(1i).err().unwrap().0, 1); /// ``` - #[unstable = "this function may be renamed to send() in the future"] - pub fn send_opt(&self, t: T) -> Result<(), T> { + pub fn send(&self, t: T) -> Result<(), SendError<T>> { let (new_inner, ret) = match *unsafe { self.inner() } { Flavor::Oneshot(ref p) => { unsafe { let p = p.get(); if !(*p).sent() { - return (*p).send(t); + return (*p).send(t).map_err(SendError); } else { let a = Arc::new(RacyCell::new(stream::Packet::new())); - match (*p).upgrade(Receiver::new(Flavor::Stream(a.clone()))) { + let rx = Receiver::new(Flavor::Stream(a.clone())); + match (*p).upgrade(rx) { oneshot::UpSuccess => { let ret = (*a.get()).send(t); (a, ret) @@ -618,8 +594,12 @@ impl<T: Send> Sender<T> { } } } - Flavor::Stream(ref p) => return unsafe { (*p.get()).send(t) }, - Flavor::Shared(ref p) => return unsafe { (*p.get()).send(t) }, + Flavor::Stream(ref p) => return unsafe { + (*p.get()).send(t).map_err(SendError) + }, + Flavor::Shared(ref p) => return unsafe { + (*p.get()).send(t).map_err(SendError) + }, Flavor::Sync(..) => unreachable!(), }; @@ -627,7 +607,7 @@ impl<T: Send> Sender<T> { let tmp = Sender::new(Flavor::Stream(new_inner)); mem::swap(self.inner_mut(), tmp.inner_mut()); } - return ret; + ret.map_err(SendError) } } @@ -639,7 +619,8 @@ impl<T: Send> Clone for Sender<T> { let a = Arc::new(RacyCell::new(shared::Packet::new())); unsafe { let guard = (*a.get()).postinit_lock(); - match (*p.get()).upgrade(Receiver::new(Flavor::Shared(a.clone()))) { + let rx = Receiver::new(Flavor::Shared(a.clone())); + match (*p.get()).upgrade(rx) { oneshot::UpSuccess | oneshot::UpDisconnected => (a, None, guard), oneshot::UpWoke(task) => (a, Some(task), guard) @@ -650,7 +631,8 @@ impl<T: Send> Clone for Sender<T> { let a = Arc::new(RacyCell::new(shared::Packet::new())); unsafe { let guard = (*a.get()).postinit_lock(); - match (*p.get()).upgrade(Receiver::new(Flavor::Shared(a.clone()))) { + let rx = Receiver::new(Flavor::Shared(a.clone())); + match (*p.get()).upgrade(rx) { stream::UpSuccess | stream::UpDisconnected => (a, None, guard), stream::UpWoke(task) => (a, Some(task), guard), @@ -701,59 +683,29 @@ impl<T: Send> SyncSender<T> { /// available or a receiver is available to hand off the message to. /// /// Note that a successful send does *not* guarantee that the receiver will - /// ever see the data if there is a buffer on this channel. Messages may be + /// ever see the data if there is a buffer on this channel. Items may be /// enqueued in the internal buffer for the receiver to receive at a later /// time. If the buffer size is 0, however, it can be guaranteed that the /// receiver has indeed received the data if this function returns success. /// - /// # Panics - /// - /// Similarly to `Sender::send`, this function will panic if the - /// corresponding `Receiver` for this channel has disconnected. This - /// behavior is used to propagate panics among tasks. - /// - /// If a panic is not desired, you can achieve the same semantics with the - /// `SyncSender::send_opt` method which will not panic if the receiver - /// disconnects. - #[experimental = "this function is being considered candidate for removal \ - to adhere to the general guidelines of rust"] - pub fn send(&self, t: T) { - if self.send_opt(t).is_err() { - panic!("sending on a closed channel"); - } - } - - /// Send a value on a channel, returning it back if the receiver - /// disconnected - /// - /// This method will *block* to send the value `t` on the channel, but if - /// the value could not be sent due to the receiver disconnecting, the value - /// is returned back to the callee. This function is similar to `try_send`, - /// except that it will block if the channel is currently full. - /// - /// # Panics - /// - /// This function cannot panic. - #[unstable = "this function may be renamed to send() in the future"] - pub fn send_opt(&self, t: T) -> Result<(), T> { - unsafe { (*self.inner.get()).send(t) } + /// This function will never panic, but it may return `Err` if the + /// `Receiver` has disconnected and is no longer able to receive + /// information. + #[stable] + pub fn send(&self, t: T) -> Result<(), SendError<T>> { + unsafe { (*self.inner.get()).send(t).map_err(SendError) } } /// Attempts to send a value on this channel without blocking. /// - /// This method differs from `send_opt` by returning immediately if the + /// This method differs from `send` by returning immediately if the /// channel's buffer is full or no receiver is waiting to acquire some - /// data. Compared with `send_opt`, this function has two failure cases + /// data. Compared with `send`, this function has two failure cases /// instead of one (one for disconnection, one for a full buffer). /// /// See `SyncSender::send` for notes about guarantees of whether the /// receiver has received the data or not if this function is successful. - /// - /// # Panics - /// - /// This function cannot panic - #[unstable = "the return type of this function is candidate for \ - modification"] + #[stable] pub fn try_send(&self, t: T) -> Result<(), TrySendError<T>> { unsafe { (*self.inner.get()).try_send(t) } } @@ -783,34 +735,6 @@ impl<T: Send> Receiver<T> { Receiver { inner: UnsafeCell::new(inner) } } - /// Blocks waiting for a value on this receiver - /// - /// This function will block if necessary to wait for a corresponding send - /// on the channel from its paired `Sender` structure. This receiver will - /// be woken up when data is ready, and the data will be returned. - /// - /// # Panics - /// - /// Similar to channels, this method will trigger a task panic if the - /// other end of the channel has hung up (been deallocated). The purpose of - /// this is to propagate panics among tasks. - /// - /// If a panic is not desired, then there are two options: - /// - /// * If blocking is still desired, the `recv_opt` method will return `None` - /// when the other end hangs up - /// - /// * If blocking is not desired, then the `try_recv` method will attempt to - /// peek at a value on this receiver. - #[experimental = "this function is being considered candidate for removal \ - to adhere to the general guidelines of rust"] - pub fn recv(&self) -> T { - match self.recv_opt() { - Ok(t) => t, - Err(()) => panic!("receiving on a closed channel"), - } - } - /// Attempts to return a pending value on this receiver without blocking /// /// This method will never block the caller in order to wait for data to @@ -819,42 +743,46 @@ impl<T: Send> Receiver<T> { /// /// This is useful for a flavor of "optimistic check" before deciding to /// block on a receiver. - /// - /// # Panics - /// - /// This function cannot panic. - #[unstable = "the return type of this function may be altered"] + #[stable] pub fn try_recv(&self) -> Result<T, TryRecvError> { loop { let new_port = match *unsafe { self.inner() } { Flavor::Oneshot(ref p) => { match unsafe { (*p.get()).try_recv() } { Ok(t) => return Ok(t), - Err(oneshot::Empty) => return Err(Empty), - Err(oneshot::Disconnected) => return Err(Disconnected), + Err(oneshot::Empty) => return Err(TryRecvError::Empty), + Err(oneshot::Disconnected) => { + return Err(TryRecvError::Disconnected) + } Err(oneshot::Upgraded(rx)) => rx, } } Flavor::Stream(ref p) => { match unsafe { (*p.get()).try_recv() } { Ok(t) => return Ok(t), - Err(stream::Empty) => return Err(Empty), - Err(stream::Disconnected) => return Err(Disconnected), + Err(stream::Empty) => return Err(TryRecvError::Empty), + Err(stream::Disconnected) => { + return Err(TryRecvError::Disconnected) + } Err(stream::Upgraded(rx)) => rx, } } Flavor::Shared(ref p) => { match unsafe { (*p.get()).try_recv() } { Ok(t) => return Ok(t), - Err(shared::Empty) => return Err(Empty), - Err(shared::Disconnected) => return Err(Disconnected), + Err(shared::Empty) => return Err(TryRecvError::Empty), + Err(shared::Disconnected) => { + return Err(TryRecvError::Disconnected) + } } } Flavor::Sync(ref p) => { match unsafe { (*p.get()).try_recv() } { Ok(t) => return Ok(t), - Err(sync::Empty) => return Err(Empty), - Err(sync::Disconnected) => return Err(Disconnected), + Err(sync::Empty) => return Err(TryRecvError::Empty), + Err(sync::Disconnected) => { + return Err(TryRecvError::Disconnected) + } } } }; @@ -865,27 +793,26 @@ impl<T: Send> Receiver<T> { } } - /// Attempt to wait for a value on this receiver, but does not panic if the + /// Attempt to wait for a value on this receiver, returning an error if the /// corresponding channel has hung up. /// - /// This implementation of iterators for ports will always block if there is - /// not data available on the receiver, but it will not panic in the case - /// that the channel has been deallocated. + /// This function will always block the current thread if there is no data + /// available and it's possible for more data to be sent. Once a message is + /// sent to the corresponding `Sender`, then this receiver will wake up and + /// return that message. /// - /// In other words, this function has the same semantics as the `recv` - /// method except for the panic aspect. - /// - /// If the channel has hung up, then `Err` is returned. Otherwise `Ok` of - /// the value found on the receiver is returned. - #[unstable = "this function may be renamed to recv()"] - pub fn recv_opt(&self) -> Result<T, ()> { + /// If the corresponding `Sender` has disconnected, or it disconnects while + /// this call is blocking, this call will wake up and return `Err` to + /// indicate that no more messages can ever be received on this channel. + #[stable] + pub fn recv(&self) -> Result<T, RecvError> { loop { let new_port = match *unsafe { self.inner() } { Flavor::Oneshot(ref p) => { match unsafe { (*p.get()).recv() } { Ok(t) => return Ok(t), Err(oneshot::Empty) => return unreachable!(), - Err(oneshot::Disconnected) => return Err(()), + Err(oneshot::Disconnected) => return Err(RecvError), Err(oneshot::Upgraded(rx)) => rx, } } @@ -893,7 +820,7 @@ impl<T: Send> Receiver<T> { match unsafe { (*p.get()).recv() } { Ok(t) => return Ok(t), Err(stream::Empty) => return unreachable!(), - Err(stream::Disconnected) => return Err(()), + Err(stream::Disconnected) => return Err(RecvError), Err(stream::Upgraded(rx)) => rx, } } @@ -901,10 +828,12 @@ impl<T: Send> Receiver<T> { match unsafe { (*p.get()).recv() } { Ok(t) => return Ok(t), Err(shared::Empty) => return unreachable!(), - Err(shared::Disconnected) => return Err(()), + Err(shared::Disconnected) => return Err(RecvError), } } - Flavor::Sync(ref p) => return unsafe { (*p.get()).recv() } + Flavor::Sync(ref p) => return unsafe { + (*p.get()).recv().map_err(|()| RecvError) + } }; unsafe { mem::swap(self.inner_mut(), new_port.inner_mut()); @@ -914,9 +843,9 @@ impl<T: Send> Receiver<T> { /// Returns an iterator that will block waiting for messages, but never /// `panic!`. It will return `None` when the channel has hung up. - #[unstable] - pub fn iter<'a>(&'a self) -> Messages<'a, T> { - Messages { rx: self } + #[stable] + pub fn iter(&self) -> Iter<T> { + Iter { rx: self } } } @@ -1007,8 +936,8 @@ impl<T: Send> select::Packet for Receiver<T> { } #[unstable] -impl<'a, T: Send> Iterator<T> for Messages<'a, T> { - fn next(&mut self) -> Option<T> { self.rx.recv_opt().ok() } +impl<'a, T: Send> Iterator<T> for Iter<'a, T> { + fn next(&mut self) -> Option<T> { self.rx.recv().ok() } } #[unsafe_destructor] @@ -1041,368 +970,425 @@ impl<T> RacyCell<T> { unsafe impl<T:Send> Send for RacyCell<T> { } -unsafe impl<T> kinds::Sync for RacyCell<T> { } // Oh dear +unsafe impl<T> Sync for RacyCell<T> { } // Oh dear + +impl<T> fmt::Show for SendError<T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + "sending on a closed channel".fmt(f) + } +} + +impl<T> fmt::Show for TrySendError<T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + TrySendError::Full(..) => { + "sending on a full channel".fmt(f) + } + TrySendError::Disconnected(..) => { + "sending on a closed channel".fmt(f) + } + } + } +} + +impl fmt::Show for RecvError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + "receiving on a closed channel".fmt(f) + } +} +impl fmt::Show for TryRecvError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + TryRecvError::Empty => { + "receiving on an empty channel".fmt(f) + } + TryRecvError::Disconnected => { + "receiving on a closed channel".fmt(f) + } + } + } +} #[cfg(test)] mod test { - use super::*; - use prelude::{spawn, range, Some, None, from_str, Clone, Str}; + use prelude::v1::*; + use os; + use super::*; + use thread::Thread; pub fn stress_factor() -> uint { match os::getenv("RUST_TEST_STRESS") { - Some(val) => from_str::<uint>(val.as_slice()).unwrap(), + Some(val) => val.parse().unwrap(), None => 1, } } - test! { fn smoke() { + #[test] + fn smoke() { let (tx, rx) = channel::<int>(); - tx.send(1); - assert_eq!(rx.recv(), 1); - } } + tx.send(1).unwrap(); + assert_eq!(rx.recv().unwrap(), 1); + } - test! { fn drop_full() { + #[test] + fn drop_full() { let (tx, _rx) = channel(); - tx.send(box 1i); - } } + tx.send(box 1i).unwrap(); + } - test! { fn drop_full_shared() { + #[test] + fn drop_full_shared() { let (tx, _rx) = channel(); drop(tx.clone()); drop(tx.clone()); - tx.send(box 1i); - } } + tx.send(box 1i).unwrap(); + } - test! { fn smoke_shared() { + #[test] + fn smoke_shared() { let (tx, rx) = channel::<int>(); - tx.send(1); - assert_eq!(rx.recv(), 1); + tx.send(1).unwrap(); + assert_eq!(rx.recv().unwrap(), 1); let tx = tx.clone(); - tx.send(1); - assert_eq!(rx.recv(), 1); - } } + tx.send(1).unwrap(); + assert_eq!(rx.recv().unwrap(), 1); + } - test! { fn smoke_threads() { + #[test] + fn smoke_threads() { let (tx, rx) = channel::<int>(); - spawn(move|| { - tx.send(1); + let _t = Thread::spawn(move|| { + tx.send(1).unwrap(); }); - assert_eq!(rx.recv(), 1); - } } + assert_eq!(rx.recv().unwrap(), 1); + } - test! { fn smoke_port_gone() { + #[test] + fn smoke_port_gone() { let (tx, rx) = channel::<int>(); drop(rx); - tx.send(1); - } #[should_fail] } + assert!(tx.send(1).is_err()); + } - test! { fn smoke_shared_port_gone() { + #[test] + fn smoke_shared_port_gone() { let (tx, rx) = channel::<int>(); drop(rx); - tx.send(1); - } #[should_fail] } + assert!(tx.send(1).is_err()) + } - test! { fn smoke_shared_port_gone2() { + #[test] + fn smoke_shared_port_gone2() { let (tx, rx) = channel::<int>(); drop(rx); let tx2 = tx.clone(); drop(tx); - tx2.send(1); - } #[should_fail] } + assert!(tx2.send(1).is_err()); + } - test! { fn port_gone_concurrent() { + #[test] + fn port_gone_concurrent() { let (tx, rx) = channel::<int>(); - spawn(move|| { - rx.recv(); + let _t = Thread::spawn(move|| { + rx.recv().unwrap(); }); - loop { tx.send(1) } - } #[should_fail] } + while tx.send(1).is_ok() {} + } - test! { fn port_gone_concurrent_shared() { + #[test] + fn port_gone_concurrent_shared() { let (tx, rx) = channel::<int>(); let tx2 = tx.clone(); - spawn(move|| { - rx.recv(); + let _t = Thread::spawn(move|| { + rx.recv().unwrap(); }); - loop { - tx.send(1); - tx2.send(1); - } - } #[should_fail] } + while tx.send(1).is_ok() && tx2.send(1).is_ok() {} + } - test! { fn smoke_chan_gone() { + #[test] + fn smoke_chan_gone() { let (tx, rx) = channel::<int>(); drop(tx); - rx.recv(); - } #[should_fail] } + assert!(rx.recv().is_err()); + } - test! { fn smoke_chan_gone_shared() { + #[test] + fn smoke_chan_gone_shared() { let (tx, rx) = channel::<()>(); let tx2 = tx.clone(); drop(tx); drop(tx2); - rx.recv(); - } #[should_fail] } + assert!(rx.recv().is_err()); + } - test! { fn chan_gone_concurrent() { + #[test] + fn chan_gone_concurrent() { let (tx, rx) = channel::<int>(); - spawn(move|| { - tx.send(1); - tx.send(1); + let _t = Thread::spawn(move|| { + tx.send(1).unwrap(); + tx.send(1).unwrap(); }); - loop { rx.recv(); } - } #[should_fail] } + while rx.recv().is_ok() {} + } - test! { fn stress() { + #[test] + fn stress() { let (tx, rx) = channel::<int>(); - spawn(move|| { - for _ in range(0u, 10000) { tx.send(1i); } + let t = Thread::spawn(move|| { + for _ in range(0u, 10000) { tx.send(1i).unwrap(); } }); for _ in range(0u, 10000) { - assert_eq!(rx.recv(), 1); + assert_eq!(rx.recv().unwrap(), 1); } - } } + t.join().ok().unwrap(); + } - test! { fn stress_shared() { + #[test] + fn stress_shared() { static AMT: uint = 10000; static NTHREADS: uint = 8; let (tx, rx) = channel::<int>(); - let (dtx, drx) = channel::<()>(); - spawn(move|| { + let t = Thread::spawn(move|| { for _ in range(0, AMT * NTHREADS) { - assert_eq!(rx.recv(), 1); + assert_eq!(rx.recv().unwrap(), 1); } match rx.try_recv() { Ok(..) => panic!(), _ => {} } - dtx.send(()); }); for _ in range(0, NTHREADS) { let tx = tx.clone(); - spawn(move|| { - for _ in range(0, AMT) { tx.send(1); } - }); + Thread::spawn(move|| { + for _ in range(0, AMT) { tx.send(1).unwrap(); } + }).detach(); } drop(tx); - drx.recv(); - } } + t.join().ok().unwrap(); + } #[test] fn send_from_outside_runtime() { let (tx1, rx1) = channel::<()>(); let (tx2, rx2) = channel::<int>(); - let (tx3, rx3) = channel::<()>(); - let tx4 = tx3.clone(); - spawn(move|| { - tx1.send(()); + let t1 = Thread::spawn(move|| { + tx1.send(()).unwrap(); for _ in range(0i, 40) { - assert_eq!(rx2.recv(), 1); + assert_eq!(rx2.recv().unwrap(), 1); } - tx3.send(()); }); - rx1.recv(); - spawn(move|| { + rx1.recv().unwrap(); + let t2 = Thread::spawn(move|| { for _ in range(0i, 40) { - tx2.send(1); + tx2.send(1).unwrap(); } - tx4.send(()); }); - rx3.recv(); - rx3.recv(); + t1.join().ok().unwrap(); + t2.join().ok().unwrap(); } #[test] fn recv_from_outside_runtime() { let (tx, rx) = channel::<int>(); - let (dtx, drx) = channel(); - spawn(move|| { + let t = Thread::spawn(move|| { for _ in range(0i, 40) { - assert_eq!(rx.recv(), 1); + assert_eq!(rx.recv().unwrap(), 1); } - dtx.send(()); }); for _ in range(0u, 40) { - tx.send(1); + tx.send(1).unwrap(); } - drx.recv(); + t.join().ok().unwrap(); } #[test] fn no_runtime() { let (tx1, rx1) = channel::<int>(); let (tx2, rx2) = channel::<int>(); - let (tx3, rx3) = channel::<()>(); - let tx4 = tx3.clone(); - spawn(move|| { - assert_eq!(rx1.recv(), 1); - tx2.send(2); - tx4.send(()); + let t1 = Thread::spawn(move|| { + assert_eq!(rx1.recv().unwrap(), 1); + tx2.send(2).unwrap(); }); - spawn(move|| { - tx1.send(1); - assert_eq!(rx2.recv(), 2); - tx3.send(()); + let t2 = Thread::spawn(move|| { + tx1.send(1).unwrap(); + assert_eq!(rx2.recv().unwrap(), 2); }); - rx3.recv(); - rx3.recv(); + t1.join().ok().unwrap(); + t2.join().ok().unwrap(); } - test! { fn oneshot_single_thread_close_port_first() { + #[test] + fn oneshot_single_thread_close_port_first() { // Simple test of closing without sending let (_tx, rx) = channel::<int>(); drop(rx); - } } + } - test! { fn oneshot_single_thread_close_chan_first() { + #[test] + fn oneshot_single_thread_close_chan_first() { // Simple test of closing without sending let (tx, _rx) = channel::<int>(); drop(tx); - } } + } - test! { fn oneshot_single_thread_send_port_close() { + #[test] + fn oneshot_single_thread_send_port_close() { // Testing that the sender cleans up the payload if receiver is closed let (tx, rx) = channel::<Box<int>>(); drop(rx); - tx.send(box 0); - } #[should_fail] } + assert!(tx.send(box 0).is_err()); + } - test! { fn oneshot_single_thread_recv_chan_close() { + #[test] + fn oneshot_single_thread_recv_chan_close() { // Receiving on a closed chan will panic let res = Thread::spawn(move|| { let (tx, rx) = channel::<int>(); drop(tx); - rx.recv(); + rx.recv().unwrap(); }).join(); // What is our res? assert!(res.is_err()); - } } + } - test! { fn oneshot_single_thread_send_then_recv() { + #[test] + fn oneshot_single_thread_send_then_recv() { let (tx, rx) = channel::<Box<int>>(); - tx.send(box 10); - assert!(rx.recv() == box 10); - } } + tx.send(box 10).unwrap(); + assert!(rx.recv().unwrap() == box 10); + } - test! { fn oneshot_single_thread_try_send_open() { + #[test] + fn oneshot_single_thread_try_send_open() { let (tx, rx) = channel::<int>(); - assert!(tx.send_opt(10).is_ok()); - assert!(rx.recv() == 10); - } } + assert!(tx.send(10).is_ok()); + assert!(rx.recv().unwrap() == 10); + } - test! { fn oneshot_single_thread_try_send_closed() { + #[test] + fn oneshot_single_thread_try_send_closed() { let (tx, rx) = channel::<int>(); drop(rx); - assert!(tx.send_opt(10).is_err()); - } } + assert!(tx.send(10).is_err()); + } - test! { fn oneshot_single_thread_try_recv_open() { + #[test] + fn oneshot_single_thread_try_recv_open() { let (tx, rx) = channel::<int>(); - tx.send(10); - assert!(rx.recv_opt() == Ok(10)); - } } + tx.send(10).unwrap(); + assert!(rx.recv() == Ok(10)); + } - test! { fn oneshot_single_thread_try_recv_closed() { + #[test] + fn oneshot_single_thread_try_recv_closed() { let (tx, rx) = channel::<int>(); drop(tx); - assert!(rx.recv_opt() == Err(())); - } } + assert!(rx.recv().is_err()); + } - test! { fn oneshot_single_thread_peek_data() { + #[test] + fn oneshot_single_thread_peek_data() { let (tx, rx) = channel::<int>(); - assert_eq!(rx.try_recv(), Err(Empty)); - tx.send(10); + assert_eq!(rx.try_recv(), Err(TryRecvError::Empty)); + tx.send(10).unwrap(); assert_eq!(rx.try_recv(), Ok(10)); - } } + } - test! { fn oneshot_single_thread_peek_close() { + #[test] + fn oneshot_single_thread_peek_close() { let (tx, rx) = channel::<int>(); drop(tx); - assert_eq!(rx.try_recv(), Err(Disconnected)); - assert_eq!(rx.try_recv(), Err(Disconnected)); - } } + assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected)); + assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected)); + } - test! { fn oneshot_single_thread_peek_open() { + #[test] + fn oneshot_single_thread_peek_open() { let (_tx, rx) = channel::<int>(); - assert_eq!(rx.try_recv(), Err(Empty)); - } } + assert_eq!(rx.try_recv(), Err(TryRecvError::Empty)); + } - test! { fn oneshot_multi_task_recv_then_send() { + #[test] + fn oneshot_multi_task_recv_then_send() { let (tx, rx) = channel::<Box<int>>(); - spawn(move|| { - assert!(rx.recv() == box 10); + let _t = Thread::spawn(move|| { + assert!(rx.recv().unwrap() == box 10); }); - tx.send(box 10); - } } + tx.send(box 10).unwrap(); + } - test! { fn oneshot_multi_task_recv_then_close() { + #[test] + fn oneshot_multi_task_recv_then_close() { let (tx, rx) = channel::<Box<int>>(); - spawn(move|| { + let _t = Thread::spawn(move|| { drop(tx); }); let res = Thread::spawn(move|| { - assert!(rx.recv() == box 10); + assert!(rx.recv().unwrap() == box 10); }).join(); assert!(res.is_err()); - } } + } - test! { fn oneshot_multi_thread_close_stress() { + #[test] + fn oneshot_multi_thread_close_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = channel::<int>(); - spawn(move|| { + let _t = Thread::spawn(move|| { drop(rx); }); drop(tx); } - } } + } - test! { fn oneshot_multi_thread_send_close_stress() { + #[test] + fn oneshot_multi_thread_send_close_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = channel::<int>(); - spawn(move|| { + let _t = Thread::spawn(move|| { drop(rx); }); let _ = Thread::spawn(move|| { - tx.send(1); + tx.send(1).unwrap(); }).join(); } - } } + } - test! { fn oneshot_multi_thread_recv_close_stress() { + #[test] + fn oneshot_multi_thread_recv_close_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = channel::<int>(); - spawn(move|| { + Thread::spawn(move|| { let res = Thread::spawn(move|| { - rx.recv(); + rx.recv().unwrap(); }).join(); assert!(res.is_err()); - }); - spawn(move|| { - spawn(move|| { + }).detach(); + let _t = Thread::spawn(move|| { + Thread::spawn(move|| { drop(tx); - }); + }).detach(); }); } - } } + } - test! { fn oneshot_multi_thread_send_recv_stress() { + #[test] + fn oneshot_multi_thread_send_recv_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = channel(); - spawn(move|| { - tx.send(box 10i); - }); - spawn(move|| { - assert!(rx.recv() == box 10i); + let _t = Thread::spawn(move|| { + tx.send(box 10i).unwrap(); }); + assert!(rx.recv().unwrap() == box 10i); } - } } + } - test! { fn stream_send_recv_stress() { + #[test] + fn stream_send_recv_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = channel(); @@ -1412,69 +1398,73 @@ mod test { fn send(tx: Sender<Box<int>>, i: int) { if i == 10 { return } - spawn(move|| { - tx.send(box i); + Thread::spawn(move|| { + tx.send(box i).unwrap(); send(tx, i + 1); - }); + }).detach(); } fn recv(rx: Receiver<Box<int>>, i: int) { if i == 10 { return } - spawn(move|| { - assert!(rx.recv() == box i); + Thread::spawn(move|| { + assert!(rx.recv().unwrap() == box i); recv(rx, i + 1); - }); + }).detach(); } } - } } + } - test! { fn recv_a_lot() { + #[test] + fn recv_a_lot() { // Regression test that we don't run out of stack in scheduler context let (tx, rx) = channel(); - for _ in range(0i, 10000) { tx.send(()); } - for _ in range(0i, 10000) { rx.recv(); } - } } + for _ in range(0i, 10000) { tx.send(()).unwrap(); } + for _ in range(0i, 10000) { rx.recv().unwrap(); } + } - test! { fn shared_chan_stress() { + #[test] + fn shared_chan_stress() { let (tx, rx) = channel(); let total = stress_factor() + 100; for _ in range(0, total) { let tx = tx.clone(); - spawn(move|| { - tx.send(()); - }); + Thread::spawn(move|| { + tx.send(()).unwrap(); + }).detach(); } for _ in range(0, total) { - rx.recv(); + rx.recv().unwrap(); } - } } + } - test! { fn test_nested_recv_iter() { + #[test] + fn test_nested_recv_iter() { let (tx, rx) = channel::<int>(); let (total_tx, total_rx) = channel::<int>(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut acc = 0; for x in rx.iter() { acc += x; } - total_tx.send(acc); + total_tx.send(acc).unwrap(); }); - tx.send(3); - tx.send(1); - tx.send(2); + tx.send(3).unwrap(); + tx.send(1).unwrap(); + tx.send(2).unwrap(); drop(tx); - assert_eq!(total_rx.recv(), 6); - } } + assert_eq!(total_rx.recv().unwrap(), 6); + } - test! { fn test_recv_iter_break() { + #[test] + fn test_recv_iter_break() { let (tx, rx) = channel::<int>(); let (count_tx, count_rx) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut count = 0; for x in rx.iter() { if count >= 3 { @@ -1483,49 +1473,51 @@ mod test { count += x; } } - count_tx.send(count); + count_tx.send(count).unwrap(); }); - tx.send(2); - tx.send(2); - tx.send(2); - let _ = tx.send_opt(2); + tx.send(2).unwrap(); + tx.send(2).unwrap(); + tx.send(2).unwrap(); + let _ = tx.send(2); drop(tx); - assert_eq!(count_rx.recv(), 4); - } } + assert_eq!(count_rx.recv().unwrap(), 4); + } - test! { fn try_recv_states() { + #[test] + fn try_recv_states() { let (tx1, rx1) = channel::<int>(); let (tx2, rx2) = channel::<()>(); let (tx3, rx3) = channel::<()>(); - spawn(move|| { - rx2.recv(); - tx1.send(1); - tx3.send(()); - rx2.recv(); + let _t = Thread::spawn(move|| { + rx2.recv().unwrap(); + tx1.send(1).unwrap(); + tx3.send(()).unwrap(); + rx2.recv().unwrap(); drop(tx1); - tx3.send(()); + tx3.send(()).unwrap(); }); - assert_eq!(rx1.try_recv(), Err(Empty)); - tx2.send(()); - rx3.recv(); + assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty)); + tx2.send(()).unwrap(); + rx3.recv().unwrap(); assert_eq!(rx1.try_recv(), Ok(1)); - assert_eq!(rx1.try_recv(), Err(Empty)); - tx2.send(()); - rx3.recv(); - assert_eq!(rx1.try_recv(), Err(Disconnected)); - } } + assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty)); + tx2.send(()).unwrap(); + rx3.recv().unwrap(); + assert_eq!(rx1.try_recv(), Err(TryRecvError::Disconnected)); + } // This bug used to end up in a livelock inside of the Receiver destructor // because the internal state of the Shared packet was corrupted - test! { fn destroy_upgraded_shared_port_when_sender_still_active() { + #[test] + fn destroy_upgraded_shared_port_when_sender_still_active() { let (tx, rx) = channel(); let (tx2, rx2) = channel(); - spawn(move|| { - rx.recv(); // wait on a oneshot + let _t = Thread::spawn(move|| { + rx.recv().unwrap(); // wait on a oneshot drop(rx); // destroy a shared - tx2.send(()); + tx2.send(()).unwrap(); }); // make sure the other task has gone to sleep for _ in range(0u, 5000) { Thread::yield_now(); } @@ -1533,303 +1525,334 @@ mod test { // upgrade to a shared chan and send a message let t = tx.clone(); drop(tx); - t.send(()); + t.send(()).unwrap(); // wait for the child task to exit before we exit - rx2.recv(); - }} + rx2.recv().unwrap(); + } } #[cfg(test)] mod sync_tests { - use prelude::*; + use prelude::v1::*; + use os; + use thread::Thread; + use super::*; pub fn stress_factor() -> uint { match os::getenv("RUST_TEST_STRESS") { - Some(val) => from_str::<uint>(val.as_slice()).unwrap(), + Some(val) => val.parse().unwrap(), None => 1, } } - test! { fn smoke() { + #[test] + fn smoke() { let (tx, rx) = sync_channel::<int>(1); - tx.send(1); - assert_eq!(rx.recv(), 1); - } } + tx.send(1).unwrap(); + assert_eq!(rx.recv().unwrap(), 1); + } - test! { fn drop_full() { + #[test] + fn drop_full() { let (tx, _rx) = sync_channel(1); - tx.send(box 1i); - } } + tx.send(box 1i).unwrap(); + } - test! { fn smoke_shared() { + #[test] + fn smoke_shared() { let (tx, rx) = sync_channel::<int>(1); - tx.send(1); - assert_eq!(rx.recv(), 1); + tx.send(1).unwrap(); + assert_eq!(rx.recv().unwrap(), 1); let tx = tx.clone(); - tx.send(1); - assert_eq!(rx.recv(), 1); - } } + tx.send(1).unwrap(); + assert_eq!(rx.recv().unwrap(), 1); + } - test! { fn smoke_threads() { + #[test] + fn smoke_threads() { let (tx, rx) = sync_channel::<int>(0); - spawn(move|| { - tx.send(1); + let _t = Thread::spawn(move|| { + tx.send(1).unwrap(); }); - assert_eq!(rx.recv(), 1); - } } + assert_eq!(rx.recv().unwrap(), 1); + } - test! { fn smoke_port_gone() { + #[test] + fn smoke_port_gone() { let (tx, rx) = sync_channel::<int>(0); drop(rx); - tx.send(1); - } #[should_fail] } + assert!(tx.send(1).is_err()); + } - test! { fn smoke_shared_port_gone2() { + #[test] + fn smoke_shared_port_gone2() { let (tx, rx) = sync_channel::<int>(0); drop(rx); let tx2 = tx.clone(); drop(tx); - tx2.send(1); - } #[should_fail] } + assert!(tx2.send(1).is_err()); + } - test! { fn port_gone_concurrent() { + #[test] + fn port_gone_concurrent() { let (tx, rx) = sync_channel::<int>(0); - spawn(move|| { - rx.recv(); + let _t = Thread::spawn(move|| { + rx.recv().unwrap(); }); - loop { tx.send(1) } - } #[should_fail] } + while tx.send(1).is_ok() {} + } - test! { fn port_gone_concurrent_shared() { + #[test] + fn port_gone_concurrent_shared() { let (tx, rx) = sync_channel::<int>(0); let tx2 = tx.clone(); - spawn(move|| { - rx.recv(); + let _t = Thread::spawn(move|| { + rx.recv().unwrap(); }); - loop { - tx.send(1); - tx2.send(1); - } - } #[should_fail] } + while tx.send(1).is_ok() && tx2.send(1).is_ok() {} + } - test! { fn smoke_chan_gone() { + #[test] + fn smoke_chan_gone() { let (tx, rx) = sync_channel::<int>(0); drop(tx); - rx.recv(); - } #[should_fail] } + assert!(rx.recv().is_err()); + } - test! { fn smoke_chan_gone_shared() { + #[test] + fn smoke_chan_gone_shared() { let (tx, rx) = sync_channel::<()>(0); let tx2 = tx.clone(); drop(tx); drop(tx2); - rx.recv(); - } #[should_fail] } + assert!(rx.recv().is_err()); + } - test! { fn chan_gone_concurrent() { + #[test] + fn chan_gone_concurrent() { let (tx, rx) = sync_channel::<int>(0); - spawn(move|| { - tx.send(1); - tx.send(1); - }); - loop { rx.recv(); } - } #[should_fail] } + Thread::spawn(move|| { + tx.send(1).unwrap(); + tx.send(1).unwrap(); + }).detach(); + while rx.recv().is_ok() {} + } - test! { fn stress() { + #[test] + fn stress() { let (tx, rx) = sync_channel::<int>(0); - spawn(move|| { - for _ in range(0u, 10000) { tx.send(1); } - }); + Thread::spawn(move|| { + for _ in range(0u, 10000) { tx.send(1).unwrap(); } + }).detach(); for _ in range(0u, 10000) { - assert_eq!(rx.recv(), 1); + assert_eq!(rx.recv().unwrap(), 1); } - } } + } - test! { fn stress_shared() { + #[test] + fn stress_shared() { static AMT: uint = 1000; static NTHREADS: uint = 8; let (tx, rx) = sync_channel::<int>(0); let (dtx, drx) = sync_channel::<()>(0); - spawn(move|| { + Thread::spawn(move|| { for _ in range(0, AMT * NTHREADS) { - assert_eq!(rx.recv(), 1); + assert_eq!(rx.recv().unwrap(), 1); } match rx.try_recv() { Ok(..) => panic!(), _ => {} } - dtx.send(()); - }); + dtx.send(()).unwrap(); + }).detach(); for _ in range(0, NTHREADS) { let tx = tx.clone(); - spawn(move|| { - for _ in range(0, AMT) { tx.send(1); } - }); + Thread::spawn(move|| { + for _ in range(0, AMT) { tx.send(1).unwrap(); } + }).detach(); } drop(tx); - drx.recv(); - } } + drx.recv().unwrap(); + } - test! { fn oneshot_single_thread_close_port_first() { + #[test] + fn oneshot_single_thread_close_port_first() { // Simple test of closing without sending let (_tx, rx) = sync_channel::<int>(0); drop(rx); - } } + } - test! { fn oneshot_single_thread_close_chan_first() { + #[test] + fn oneshot_single_thread_close_chan_first() { // Simple test of closing without sending let (tx, _rx) = sync_channel::<int>(0); drop(tx); - } } + } - test! { fn oneshot_single_thread_send_port_close() { + #[test] + fn oneshot_single_thread_send_port_close() { // Testing that the sender cleans up the payload if receiver is closed let (tx, rx) = sync_channel::<Box<int>>(0); drop(rx); - tx.send(box 0); - } #[should_fail] } + assert!(tx.send(box 0).is_err()); + } - test! { fn oneshot_single_thread_recv_chan_close() { + #[test] + fn oneshot_single_thread_recv_chan_close() { // Receiving on a closed chan will panic let res = Thread::spawn(move|| { let (tx, rx) = sync_channel::<int>(0); drop(tx); - rx.recv(); + rx.recv().unwrap(); }).join(); // What is our res? assert!(res.is_err()); - } } + } - test! { fn oneshot_single_thread_send_then_recv() { + #[test] + fn oneshot_single_thread_send_then_recv() { let (tx, rx) = sync_channel::<Box<int>>(1); - tx.send(box 10); - assert!(rx.recv() == box 10); - } } + tx.send(box 10).unwrap(); + assert!(rx.recv().unwrap() == box 10); + } - test! { fn oneshot_single_thread_try_send_open() { + #[test] + fn oneshot_single_thread_try_send_open() { let (tx, rx) = sync_channel::<int>(1); assert_eq!(tx.try_send(10), Ok(())); - assert!(rx.recv() == 10); - } } + assert!(rx.recv().unwrap() == 10); + } - test! { fn oneshot_single_thread_try_send_closed() { + #[test] + fn oneshot_single_thread_try_send_closed() { let (tx, rx) = sync_channel::<int>(0); drop(rx); - assert_eq!(tx.try_send(10), Err(RecvDisconnected(10))); - } } + assert_eq!(tx.try_send(10), Err(TrySendError::Disconnected(10))); + } - test! { fn oneshot_single_thread_try_send_closed2() { + #[test] + fn oneshot_single_thread_try_send_closed2() { let (tx, _rx) = sync_channel::<int>(0); - assert_eq!(tx.try_send(10), Err(Full(10))); - } } + assert_eq!(tx.try_send(10), Err(TrySendError::Full(10))); + } - test! { fn oneshot_single_thread_try_recv_open() { + #[test] + fn oneshot_single_thread_try_recv_open() { let (tx, rx) = sync_channel::<int>(1); - tx.send(10); - assert!(rx.recv_opt() == Ok(10)); - } } + tx.send(10).unwrap(); + assert!(rx.recv() == Ok(10)); + } - test! { fn oneshot_single_thread_try_recv_closed() { + #[test] + fn oneshot_single_thread_try_recv_closed() { let (tx, rx) = sync_channel::<int>(0); drop(tx); - assert!(rx.recv_opt() == Err(())); - } } + assert!(rx.recv().is_err()); + } - test! { fn oneshot_single_thread_peek_data() { + #[test] + fn oneshot_single_thread_peek_data() { let (tx, rx) = sync_channel::<int>(1); - assert_eq!(rx.try_recv(), Err(Empty)); - tx.send(10); + assert_eq!(rx.try_recv(), Err(TryRecvError::Empty)); + tx.send(10).unwrap(); assert_eq!(rx.try_recv(), Ok(10)); - } } + } - test! { fn oneshot_single_thread_peek_close() { + #[test] + fn oneshot_single_thread_peek_close() { let (tx, rx) = sync_channel::<int>(0); drop(tx); - assert_eq!(rx.try_recv(), Err(Disconnected)); - assert_eq!(rx.try_recv(), Err(Disconnected)); - } } + assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected)); + assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected)); + } - test! { fn oneshot_single_thread_peek_open() { + #[test] + fn oneshot_single_thread_peek_open() { let (_tx, rx) = sync_channel::<int>(0); - assert_eq!(rx.try_recv(), Err(Empty)); - } } + assert_eq!(rx.try_recv(), Err(TryRecvError::Empty)); + } - test! { fn oneshot_multi_task_recv_then_send() { + #[test] + fn oneshot_multi_task_recv_then_send() { let (tx, rx) = sync_channel::<Box<int>>(0); - spawn(move|| { - assert!(rx.recv() == box 10); + let _t = Thread::spawn(move|| { + assert!(rx.recv().unwrap() == box 10); }); - tx.send(box 10); - } } + tx.send(box 10).unwrap(); + } - test! { fn oneshot_multi_task_recv_then_close() { + #[test] + fn oneshot_multi_task_recv_then_close() { let (tx, rx) = sync_channel::<Box<int>>(0); - spawn(move|| { + let _t = Thread::spawn(move|| { drop(tx); }); let res = Thread::spawn(move|| { - assert!(rx.recv() == box 10); + assert!(rx.recv().unwrap() == box 10); }).join(); assert!(res.is_err()); - } } + } - test! { fn oneshot_multi_thread_close_stress() { + #[test] + fn oneshot_multi_thread_close_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = sync_channel::<int>(0); - spawn(move|| { + let _t = Thread::spawn(move|| { drop(rx); }); drop(tx); } - } } + } - test! { fn oneshot_multi_thread_send_close_stress() { + #[test] + fn oneshot_multi_thread_send_close_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = sync_channel::<int>(0); - spawn(move|| { + let _t = Thread::spawn(move|| { drop(rx); }); let _ = Thread::spawn(move || { - tx.send(1); + tx.send(1).unwrap(); }).join(); } - } } + } - test! { fn oneshot_multi_thread_recv_close_stress() { + #[test] + fn oneshot_multi_thread_recv_close_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = sync_channel::<int>(0); - spawn(move|| { + let _t = Thread::spawn(move|| { let res = Thread::spawn(move|| { - rx.recv(); + rx.recv().unwrap(); }).join(); assert!(res.is_err()); }); - spawn(move|| { - spawn(move|| { + let _t = Thread::spawn(move|| { + Thread::spawn(move|| { drop(tx); - }); + }).detach(); }); } - } } + } - test! { fn oneshot_multi_thread_send_recv_stress() { + #[test] + fn oneshot_multi_thread_send_recv_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = sync_channel::<Box<int>>(0); - spawn(move|| { - tx.send(box 10i); - }); - spawn(move|| { - assert!(rx.recv() == box 10i); + let _t = Thread::spawn(move|| { + tx.send(box 10i).unwrap(); }); + assert!(rx.recv().unwrap() == box 10i); } - } } + } - test! { fn stream_send_recv_stress() { + #[test] + fn stream_send_recv_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = sync_channel::<Box<int>>(0); @@ -1839,69 +1862,73 @@ mod sync_tests { fn send(tx: SyncSender<Box<int>>, i: int) { if i == 10 { return } - spawn(move|| { - tx.send(box i); + Thread::spawn(move|| { + tx.send(box i).unwrap(); send(tx, i + 1); - }); + }).detach(); } fn recv(rx: Receiver<Box<int>>, i: int) { if i == 10 { return } - spawn(move|| { - assert!(rx.recv() == box i); + Thread::spawn(move|| { + assert!(rx.recv().unwrap() == box i); recv(rx, i + 1); - }); + }).detach(); } } - } } + } - test! { fn recv_a_lot() { + #[test] + fn recv_a_lot() { // Regression test that we don't run out of stack in scheduler context let (tx, rx) = sync_channel(10000); - for _ in range(0u, 10000) { tx.send(()); } - for _ in range(0u, 10000) { rx.recv(); } - } } + for _ in range(0u, 10000) { tx.send(()).unwrap(); } + for _ in range(0u, 10000) { rx.recv().unwrap(); } + } - test! { fn shared_chan_stress() { + #[test] + fn shared_chan_stress() { let (tx, rx) = sync_channel(0); let total = stress_factor() + 100; for _ in range(0, total) { let tx = tx.clone(); - spawn(move|| { - tx.send(()); - }); + Thread::spawn(move|| { + tx.send(()).unwrap(); + }).detach(); } for _ in range(0, total) { - rx.recv(); + rx.recv().unwrap(); } - } } + } - test! { fn test_nested_recv_iter() { + #[test] + fn test_nested_recv_iter() { let (tx, rx) = sync_channel::<int>(0); let (total_tx, total_rx) = sync_channel::<int>(0); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut acc = 0; for x in rx.iter() { acc += x; } - total_tx.send(acc); + total_tx.send(acc).unwrap(); }); - tx.send(3); - tx.send(1); - tx.send(2); + tx.send(3).unwrap(); + tx.send(1).unwrap(); + tx.send(2).unwrap(); drop(tx); - assert_eq!(total_rx.recv(), 6); - } } + assert_eq!(total_rx.recv().unwrap(), 6); + } - test! { fn test_recv_iter_break() { + #[test] + fn test_recv_iter_break() { let (tx, rx) = sync_channel::<int>(0); let (count_tx, count_rx) = sync_channel(0); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut count = 0; for x in rx.iter() { if count >= 3 { @@ -1910,49 +1937,51 @@ mod sync_tests { count += x; } } - count_tx.send(count); + count_tx.send(count).unwrap(); }); - tx.send(2); - tx.send(2); - tx.send(2); + tx.send(2).unwrap(); + tx.send(2).unwrap(); + tx.send(2).unwrap(); let _ = tx.try_send(2); drop(tx); - assert_eq!(count_rx.recv(), 4); - } } + assert_eq!(count_rx.recv().unwrap(), 4); + } - test! { fn try_recv_states() { + #[test] + fn try_recv_states() { let (tx1, rx1) = sync_channel::<int>(1); let (tx2, rx2) = sync_channel::<()>(1); let (tx3, rx3) = sync_channel::<()>(1); - spawn(move|| { - rx2.recv(); - tx1.send(1); - tx3.send(()); - rx2.recv(); + let _t = Thread::spawn(move|| { + rx2.recv().unwrap(); + tx1.send(1).unwrap(); + tx3.send(()).unwrap(); + rx2.recv().unwrap(); drop(tx1); - tx3.send(()); + tx3.send(()).unwrap(); }); - assert_eq!(rx1.try_recv(), Err(Empty)); - tx2.send(()); - rx3.recv(); + assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty)); + tx2.send(()).unwrap(); + rx3.recv().unwrap(); assert_eq!(rx1.try_recv(), Ok(1)); - assert_eq!(rx1.try_recv(), Err(Empty)); - tx2.send(()); - rx3.recv(); - assert_eq!(rx1.try_recv(), Err(Disconnected)); - } } + assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty)); + tx2.send(()).unwrap(); + rx3.recv().unwrap(); + assert_eq!(rx1.try_recv(), Err(TryRecvError::Disconnected)); + } // This bug used to end up in a livelock inside of the Receiver destructor // because the internal state of the Shared packet was corrupted - test! { fn destroy_upgraded_shared_port_when_sender_still_active() { + #[test] + fn destroy_upgraded_shared_port_when_sender_still_active() { let (tx, rx) = sync_channel::<()>(0); let (tx2, rx2) = sync_channel::<()>(0); - spawn(move|| { - rx.recv(); // wait on a oneshot + let _t = Thread::spawn(move|| { + rx.recv().unwrap(); // wait on a oneshot drop(rx); // destroy a shared - tx2.send(()); + tx2.send(()).unwrap(); }); // make sure the other task has gone to sleep for _ in range(0u, 5000) { Thread::yield_now(); } @@ -1960,92 +1989,91 @@ mod sync_tests { // upgrade to a shared chan and send a message let t = tx.clone(); drop(tx); - t.send(()); + t.send(()).unwrap(); // wait for the child task to exit before we exit - rx2.recv(); - } } + rx2.recv().unwrap(); + } - test! { fn send_opt1() { + #[test] + fn send1() { let (tx, rx) = sync_channel::<int>(0); - spawn(move|| { rx.recv(); }); - assert_eq!(tx.send_opt(1), Ok(())); - } } + let _t = Thread::spawn(move|| { rx.recv().unwrap(); }); + assert_eq!(tx.send(1), Ok(())); + } - test! { fn send_opt2() { + #[test] + fn send2() { let (tx, rx) = sync_channel::<int>(0); - spawn(move|| { drop(rx); }); - assert_eq!(tx.send_opt(1), Err(1)); - } } + let _t = Thread::spawn(move|| { drop(rx); }); + assert!(tx.send(1).is_err()); + } - test! { fn send_opt3() { + #[test] + fn send3() { let (tx, rx) = sync_channel::<int>(1); - assert_eq!(tx.send_opt(1), Ok(())); - spawn(move|| { drop(rx); }); - assert_eq!(tx.send_opt(1), Err(1)); - } } + assert_eq!(tx.send(1), Ok(())); + let _t =Thread::spawn(move|| { drop(rx); }); + assert!(tx.send(1).is_err()); + } - test! { fn send_opt4() { + #[test] + fn send4() { let (tx, rx) = sync_channel::<int>(0); let tx2 = tx.clone(); let (done, donerx) = channel(); let done2 = done.clone(); - spawn(move|| { - assert_eq!(tx.send_opt(1), Err(1)); - done.send(()); + let _t = Thread::spawn(move|| { + assert!(tx.send(1).is_err()); + done.send(()).unwrap(); }); - spawn(move|| { - assert_eq!(tx2.send_opt(2), Err(2)); - done2.send(()); + let _t = Thread::spawn(move|| { + assert!(tx2.send(2).is_err()); + done2.send(()).unwrap(); }); drop(rx); - donerx.recv(); - donerx.recv(); - } } + donerx.recv().unwrap(); + donerx.recv().unwrap(); + } - test! { fn try_send1() { + #[test] + fn try_send1() { let (tx, _rx) = sync_channel::<int>(0); - assert_eq!(tx.try_send(1), Err(Full(1))); - } } + assert_eq!(tx.try_send(1), Err(TrySendError::Full(1))); + } - test! { fn try_send2() { + #[test] + fn try_send2() { let (tx, _rx) = sync_channel::<int>(1); assert_eq!(tx.try_send(1), Ok(())); - assert_eq!(tx.try_send(1), Err(Full(1))); - } } + assert_eq!(tx.try_send(1), Err(TrySendError::Full(1))); + } - test! { fn try_send3() { + #[test] + fn try_send3() { let (tx, rx) = sync_channel::<int>(1); assert_eq!(tx.try_send(1), Ok(())); drop(rx); - assert_eq!(tx.try_send(1), Err(RecvDisconnected(1))); - } } - - test! { fn try_send4() { - let (tx, rx) = sync_channel::<int>(0); - spawn(move|| { - for _ in range(0u, 1000) { Thread::yield_now(); } - assert_eq!(tx.try_send(1), Ok(())); - }); - assert_eq!(rx.recv(), 1); - } #[ignore(reason = "flaky on libnative")] } + assert_eq!(tx.try_send(1), Err(TrySendError::Disconnected(1))); + } - test! { fn issue_15761() { + #[test] + fn issue_15761() { fn repro() { let (tx1, rx1) = sync_channel::<()>(3); let (tx2, rx2) = sync_channel::<()>(3); - spawn(move|| { - rx1.recv(); + let _t = Thread::spawn(move|| { + rx1.recv().unwrap(); tx2.try_send(()).unwrap(); }); tx1.try_send(()).unwrap(); - rx2.recv(); + rx2.recv().unwrap(); } for _ in range(0u, 100) { repro() } - } } + } } diff --git a/src/libstd/comm/mpsc_queue.rs b/src/libstd/sync/mpsc/mpsc_queue.rs index cddef236664..8945233dac9 100644 --- a/src/libstd/comm/mpsc_queue.rs +++ b/src/libstd/sync/mpsc/mpsc_queue.rs @@ -153,11 +153,12 @@ impl<T: Send> Drop for Queue<T> { #[cfg(test)] mod tests { - use prelude::*; - - use alloc::arc::Arc; + use prelude::v1::*; + use sync::mpsc::channel; use super::{Queue, Data, Empty, Inconsistent}; + use sync::Arc; + use thread::Thread; #[test] fn test_full() { @@ -181,12 +182,12 @@ mod tests { for _ in range(0, nthreads) { let tx = tx.clone(); let q = q.clone(); - spawn(move|| { + Thread::spawn(move|| { for i in range(0, nmsgs) { q.push(i); } - tx.send(()); - }); + tx.send(()).unwrap(); + }).detach(); } let mut i = 0u; @@ -198,7 +199,7 @@ mod tests { } drop(tx); for _ in range(0, nthreads) { - rx.recv(); + rx.recv().unwrap(); } } } diff --git a/src/libstd/comm/oneshot.rs b/src/libstd/sync/mpsc/oneshot.rs index 9c5a6518845..5f599752a46 100644 --- a/src/libstd/comm/oneshot.rs +++ b/src/libstd/sync/mpsc/oneshot.rs @@ -39,8 +39,8 @@ use self::MyUpgrade::*; use core::prelude::*; -use comm::Receiver; -use comm::blocking::{mod, SignalToken}; +use sync::mpsc::Receiver; +use sync::mpsc::blocking::{mod, SignalToken}; use core::mem; use sync::atomic; diff --git a/src/libstd/comm/select.rs b/src/libstd/sync/mpsc/select.rs index 690b5861c22..43554d7c335 100644 --- a/src/libstd/comm/select.rs +++ b/src/libstd/sync/mpsc/select.rs @@ -27,18 +27,20 @@ //! # Example //! //! ```rust +//! use std::sync::mpsc::channel; +//! //! let (tx1, rx1) = channel(); //! let (tx2, rx2) = channel(); //! -//! tx1.send(1i); -//! tx2.send(2i); +//! tx1.send(1i).unwrap(); +//! tx2.send(2i).unwrap(); //! //! select! { //! val = rx1.recv() => { -//! assert_eq!(val, 1i); +//! assert_eq!(val.unwrap(), 1i); //! }, //! val = rx2.recv() => { -//! assert_eq!(val, 2i); +//! assert_eq!(val.unwrap(), 2i); //! } //! } //! ``` @@ -59,8 +61,8 @@ use core::kinds::marker; use core::mem; use core::uint; -use comm::Receiver; -use comm::blocking::{mod, SignalToken}; +use sync::mpsc::{Receiver, RecvError}; +use sync::mpsc::blocking::{mod, SignalToken}; /// The "receiver set" of the select interface. This structure is used to manage /// a set of receivers which are being selected over. @@ -245,13 +247,10 @@ impl<'rx, T: Send> Handle<'rx, T> { #[inline] pub fn id(&self) -> uint { self.id } - /// Receive a value on the underlying receiver. Has the same semantics as - /// `Receiver.recv` - pub fn recv(&mut self) -> T { self.rx.recv() } /// Block to receive a value on the underlying receiver, returning `Some` on /// success or `None` if the channel disconnects. This function has the same - /// semantics as `Receiver.recv_opt` - pub fn recv_opt(&mut self) -> Result<T, ()> { self.rx.recv_opt() } + /// semantics as `Receiver.recv` + pub fn recv(&mut self) -> Result<T, RecvError> { self.rx.recv() } /// Adds this handle to the receiver set that the handle was created from. This /// method can be called multiple times, but it has no effect if `add` was @@ -335,9 +334,10 @@ impl Iterator<*mut Handle<'static, ()>> for Packets { #[cfg(test)] #[allow(unused_imports)] mod test { - use prelude::*; + use prelude::v1::*; - use super::*; + use thread::Thread; + use sync::mpsc::*; // Don't use the libstd version so we can pull in the right Select structure // (std::comm points at the wrong one) @@ -345,7 +345,6 @@ mod test { ( $($name:pat = $rx:ident.$meth:ident() => $code:expr),+ ) => ({ - use comm::Select; let sel = Select::new(); $( let mut $rx = sel.handle(&$rx); )+ unsafe { @@ -357,365 +356,391 @@ mod test { }) } - test! { fn smoke() { + #[test] + fn smoke() { let (tx1, rx1) = channel::<int>(); let (tx2, rx2) = channel::<int>(); - tx1.send(1); + tx1.send(1).unwrap(); select! { - foo = rx1.recv() => { assert_eq!(foo, 1); }, + foo = rx1.recv() => { assert_eq!(foo.unwrap(), 1); }, _bar = rx2.recv() => { panic!() } } - tx2.send(2); + tx2.send(2).unwrap(); select! { _foo = rx1.recv() => { panic!() }, - bar = rx2.recv() => { assert_eq!(bar, 2) } + bar = rx2.recv() => { assert_eq!(bar.unwrap(), 2) } } drop(tx1); select! { - foo = rx1.recv_opt() => { assert_eq!(foo, Err(())); }, + foo = rx1.recv() => { assert!(foo.is_err()); }, _bar = rx2.recv() => { panic!() } } drop(tx2); select! { - bar = rx2.recv_opt() => { assert_eq!(bar, Err(())); } + bar = rx2.recv() => { assert!(bar.is_err()); } } - } } + } - test! { fn smoke2() { + #[test] + fn smoke2() { let (_tx1, rx1) = channel::<int>(); let (_tx2, rx2) = channel::<int>(); let (_tx3, rx3) = channel::<int>(); let (_tx4, rx4) = channel::<int>(); let (tx5, rx5) = channel::<int>(); - tx5.send(4); + tx5.send(4).unwrap(); select! { _foo = rx1.recv() => { panic!("1") }, _foo = rx2.recv() => { panic!("2") }, _foo = rx3.recv() => { panic!("3") }, _foo = rx4.recv() => { panic!("4") }, - foo = rx5.recv() => { assert_eq!(foo, 4); } + foo = rx5.recv() => { assert_eq!(foo.unwrap(), 4); } } - } } + } - test! { fn closed() { + #[test] + fn closed() { let (_tx1, rx1) = channel::<int>(); let (tx2, rx2) = channel::<int>(); drop(tx2); select! { - _a1 = rx1.recv_opt() => { panic!() }, - a2 = rx2.recv_opt() => { assert_eq!(a2, Err(())); } + _a1 = rx1.recv() => { panic!() }, + a2 = rx2.recv() => { assert!(a2.is_err()); } } - } } + } - test! { fn unblocks() { + #[test] + fn unblocks() { let (tx1, rx1) = channel::<int>(); let (_tx2, rx2) = channel::<int>(); let (tx3, rx3) = channel::<int>(); - spawn(move|| { + let _t = Thread::spawn(move|| { for _ in range(0u, 20) { Thread::yield_now(); } - tx1.send(1); - rx3.recv(); + tx1.send(1).unwrap(); + rx3.recv().unwrap(); for _ in range(0u, 20) { Thread::yield_now(); } }); select! { - a = rx1.recv() => { assert_eq!(a, 1); }, + a = rx1.recv() => { assert_eq!(a.unwrap(), 1); }, _b = rx2.recv() => { panic!() } } - tx3.send(1); + tx3.send(1).unwrap(); select! { - a = rx1.recv_opt() => { assert_eq!(a, Err(())); }, + a = rx1.recv() => { assert!(a.is_err()) }, _b = rx2.recv() => { panic!() } } - } } + } - test! { fn both_ready() { + #[test] + fn both_ready() { let (tx1, rx1) = channel::<int>(); let (tx2, rx2) = channel::<int>(); let (tx3, rx3) = channel::<()>(); - spawn(move|| { + let _t = Thread::spawn(move|| { for _ in range(0u, 20) { Thread::yield_now(); } - tx1.send(1); - tx2.send(2); - rx3.recv(); + tx1.send(1).unwrap(); + tx2.send(2).unwrap(); + rx3.recv().unwrap(); }); select! { - a = rx1.recv() => { assert_eq!(a, 1); }, - a = rx2.recv() => { assert_eq!(a, 2); } + a = rx1.recv() => { assert_eq!(a.unwrap(), 1); }, + a = rx2.recv() => { assert_eq!(a.unwrap(), 2); } } select! { - a = rx1.recv() => { assert_eq!(a, 1); }, - a = rx2.recv() => { assert_eq!(a, 2); } + a = rx1.recv() => { assert_eq!(a.unwrap(), 1); }, + a = rx2.recv() => { assert_eq!(a.unwrap(), 2); } } - assert_eq!(rx1.try_recv(), Err(Empty)); - assert_eq!(rx2.try_recv(), Err(Empty)); - tx3.send(()); - } } + assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty)); + assert_eq!(rx2.try_recv(), Err(TryRecvError::Empty)); + tx3.send(()).unwrap(); + } - test! { fn stress() { + #[test] + fn stress() { static AMT: int = 10000; let (tx1, rx1) = channel::<int>(); let (tx2, rx2) = channel::<int>(); let (tx3, rx3) = channel::<()>(); - spawn(move|| { + let _t = Thread::spawn(move|| { for i in range(0, AMT) { if i % 2 == 0 { - tx1.send(i); + tx1.send(i).unwrap(); } else { - tx2.send(i); + tx2.send(i).unwrap(); } - rx3.recv(); + rx3.recv().unwrap(); } }); for i in range(0, AMT) { select! { - i1 = rx1.recv() => { assert!(i % 2 == 0 && i == i1); }, - i2 = rx2.recv() => { assert!(i % 2 == 1 && i == i2); } + i1 = rx1.recv() => { assert!(i % 2 == 0 && i == i1.unwrap()); }, + i2 = rx2.recv() => { assert!(i % 2 == 1 && i == i2.unwrap()); } } - tx3.send(()); + tx3.send(()).unwrap(); } - } } + } - test! { fn cloning() { + #[test] + fn cloning() { let (tx1, rx1) = channel::<int>(); let (_tx2, rx2) = channel::<int>(); let (tx3, rx3) = channel::<()>(); - spawn(move|| { - rx3.recv(); + let _t = Thread::spawn(move|| { + rx3.recv().unwrap(); tx1.clone(); - assert_eq!(rx3.try_recv(), Err(Empty)); - tx1.send(2); - rx3.recv(); + assert_eq!(rx3.try_recv(), Err(TryRecvError::Empty)); + tx1.send(2).unwrap(); + rx3.recv().unwrap(); }); - tx3.send(()); + tx3.send(()).unwrap(); select! { _i1 = rx1.recv() => {}, _i2 = rx2.recv() => panic!() } - tx3.send(()); - } } + tx3.send(()).unwrap(); + } - test! { fn cloning2() { + #[test] + fn cloning2() { let (tx1, rx1) = channel::<int>(); let (_tx2, rx2) = channel::<int>(); let (tx3, rx3) = channel::<()>(); - spawn(move|| { - rx3.recv(); + let _t = Thread::spawn(move|| { + rx3.recv().unwrap(); tx1.clone(); - assert_eq!(rx3.try_recv(), Err(Empty)); - tx1.send(2); - rx3.recv(); + assert_eq!(rx3.try_recv(), Err(TryRecvError::Empty)); + tx1.send(2).unwrap(); + rx3.recv().unwrap(); }); - tx3.send(()); + tx3.send(()).unwrap(); select! { _i1 = rx1.recv() => {}, _i2 = rx2.recv() => panic!() } - tx3.send(()); - } } + tx3.send(()).unwrap(); + } - test! { fn cloning3() { + #[test] + fn cloning3() { let (tx1, rx1) = channel::<()>(); let (tx2, rx2) = channel::<()>(); let (tx3, rx3) = channel::<()>(); - spawn(move|| { + let _t = Thread::spawn(move|| { let s = Select::new(); let mut h1 = s.handle(&rx1); let mut h2 = s.handle(&rx2); unsafe { h2.add(); } unsafe { h1.add(); } assert_eq!(s.wait(), h2.id); - tx3.send(()); + tx3.send(()).unwrap(); }); for _ in range(0u, 1000) { Thread::yield_now(); } drop(tx1.clone()); - tx2.send(()); - rx3.recv(); - } } + tx2.send(()).unwrap(); + rx3.recv().unwrap(); + } - test! { fn preflight1() { + #[test] + fn preflight1() { let (tx, rx) = channel(); - tx.send(()); + tx.send(()).unwrap(); select! { - () = rx.recv() => {} + _n = rx.recv() => {} } - } } + } - test! { fn preflight2() { + #[test] + fn preflight2() { let (tx, rx) = channel(); - tx.send(()); - tx.send(()); + tx.send(()).unwrap(); + tx.send(()).unwrap(); select! { - () = rx.recv() => {} + _n = rx.recv() => {} } - } } + } - test! { fn preflight3() { + #[test] + fn preflight3() { let (tx, rx) = channel(); drop(tx.clone()); - tx.send(()); + tx.send(()).unwrap(); select! { - () = rx.recv() => {} + _n = rx.recv() => {} } - } } + } - test! { fn preflight4() { + #[test] + fn preflight4() { let (tx, rx) = channel(); - tx.send(()); + tx.send(()).unwrap(); let s = Select::new(); let mut h = s.handle(&rx); unsafe { h.add(); } assert_eq!(s.wait2(false), h.id); - } } + } - test! { fn preflight5() { + #[test] + fn preflight5() { let (tx, rx) = channel(); - tx.send(()); - tx.send(()); + tx.send(()).unwrap(); + tx.send(()).unwrap(); let s = Select::new(); let mut h = s.handle(&rx); unsafe { h.add(); } assert_eq!(s.wait2(false), h.id); - } } + } - test! { fn preflight6() { + #[test] + fn preflight6() { let (tx, rx) = channel(); drop(tx.clone()); - tx.send(()); + tx.send(()).unwrap(); let s = Select::new(); let mut h = s.handle(&rx); unsafe { h.add(); } assert_eq!(s.wait2(false), h.id); - } } + } - test! { fn preflight7() { + #[test] + fn preflight7() { let (tx, rx) = channel::<()>(); drop(tx); let s = Select::new(); let mut h = s.handle(&rx); unsafe { h.add(); } assert_eq!(s.wait2(false), h.id); - } } + } - test! { fn preflight8() { + #[test] + fn preflight8() { let (tx, rx) = channel(); - tx.send(()); + tx.send(()).unwrap(); drop(tx); - rx.recv(); + rx.recv().unwrap(); let s = Select::new(); let mut h = s.handle(&rx); unsafe { h.add(); } assert_eq!(s.wait2(false), h.id); - } } + } - test! { fn preflight9() { + #[test] + fn preflight9() { let (tx, rx) = channel(); drop(tx.clone()); - tx.send(()); + tx.send(()).unwrap(); drop(tx); - rx.recv(); + rx.recv().unwrap(); let s = Select::new(); let mut h = s.handle(&rx); unsafe { h.add(); } assert_eq!(s.wait2(false), h.id); - } } + } - test! { fn oneshot_data_waiting() { + #[test] + fn oneshot_data_waiting() { let (tx1, rx1) = channel(); let (tx2, rx2) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { select! { - () = rx1.recv() => {} + _n = rx1.recv() => {} } - tx2.send(()); + tx2.send(()).unwrap(); }); for _ in range(0u, 100) { Thread::yield_now() } - tx1.send(()); - rx2.recv(); - } } + tx1.send(()).unwrap(); + rx2.recv().unwrap(); + } - test! { fn stream_data_waiting() { + #[test] + fn stream_data_waiting() { let (tx1, rx1) = channel(); let (tx2, rx2) = channel(); - tx1.send(()); - tx1.send(()); - rx1.recv(); - rx1.recv(); - spawn(move|| { + tx1.send(()).unwrap(); + tx1.send(()).unwrap(); + rx1.recv().unwrap(); + rx1.recv().unwrap(); + let _t = Thread::spawn(move|| { select! { - () = rx1.recv() => {} + _n = rx1.recv() => {} } - tx2.send(()); + tx2.send(()).unwrap(); }); for _ in range(0u, 100) { Thread::yield_now() } - tx1.send(()); - rx2.recv(); - } } + tx1.send(()).unwrap(); + rx2.recv().unwrap(); + } - test! { fn shared_data_waiting() { + #[test] + fn shared_data_waiting() { let (tx1, rx1) = channel(); let (tx2, rx2) = channel(); drop(tx1.clone()); - tx1.send(()); - rx1.recv(); - spawn(move|| { + tx1.send(()).unwrap(); + rx1.recv().unwrap(); + let _t = Thread::spawn(move|| { select! { - () = rx1.recv() => {} + _n = rx1.recv() => {} } - tx2.send(()); + tx2.send(()).unwrap(); }); for _ in range(0u, 100) { Thread::yield_now() } - tx1.send(()); - rx2.recv(); - } } + tx1.send(()).unwrap(); + rx2.recv().unwrap(); + } - test! { fn sync1() { + #[test] + fn sync1() { let (tx, rx) = sync_channel::<int>(1); - tx.send(1); + tx.send(1).unwrap(); select! { - n = rx.recv() => { assert_eq!(n, 1); } + n = rx.recv() => { assert_eq!(n.unwrap(), 1); } } - } } + } - test! { fn sync2() { + #[test] + fn sync2() { let (tx, rx) = sync_channel::<int>(0); - spawn(move|| { + let _t = Thread::spawn(move|| { for _ in range(0u, 100) { Thread::yield_now() } - tx.send(1); + tx.send(1).unwrap(); }); select! { - n = rx.recv() => { assert_eq!(n, 1); } + n = rx.recv() => { assert_eq!(n.unwrap(), 1); } } - } } + } - test! { fn sync3() { + #[test] + fn sync3() { let (tx1, rx1) = sync_channel::<int>(0); let (tx2, rx2): (Sender<int>, Receiver<int>) = channel(); - spawn(move|| { tx1.send(1); }); - spawn(move|| { tx2.send(2); }); + let _t = Thread::spawn(move|| { tx1.send(1).unwrap(); }); + let _t = Thread::spawn(move|| { tx2.send(2).unwrap(); }); select! { n = rx1.recv() => { + let n = n.unwrap(); assert_eq!(n, 1); - assert_eq!(rx2.recv(), 2); + assert_eq!(rx2.recv().unwrap(), 2); }, n = rx2.recv() => { + let n = n.unwrap(); assert_eq!(n, 2); - assert_eq!(rx1.recv(), 1); + assert_eq!(rx1.recv().unwrap(), 1); } } - } } + } } diff --git a/src/libstd/comm/shared.rs b/src/libstd/sync/mpsc/shared.rs index 3f23ec5dc66..e15c38cf9a1 100644 --- a/src/libstd/comm/shared.rs +++ b/src/libstd/sync/mpsc/shared.rs @@ -26,10 +26,10 @@ use core::cmp; use core::int; use sync::{atomic, Mutex, MutexGuard}; -use comm::mpsc_queue as mpsc; -use comm::blocking::{mod, SignalToken}; -use comm::select::StartResult; -use comm::select::StartResult::*; +use sync::mpsc::mpsc_queue as mpsc; +use sync::mpsc::blocking::{mod, SignalToken}; +use sync::mpsc::select::StartResult; +use sync::mpsc::select::StartResult::*; use thread::Thread; const DISCONNECTED: int = int::MIN; diff --git a/src/libstd/comm/spsc_queue.rs b/src/libstd/sync/mpsc/spsc_queue.rs index becb78063ae..15624601157 100644 --- a/src/libstd/comm/spsc_queue.rs +++ b/src/libstd/sync/mpsc/spsc_queue.rs @@ -240,10 +240,12 @@ impl<T: Send> Drop for Queue<T> { #[cfg(test)] mod test { - use prelude::*; + use prelude::v1::*; use sync::Arc; use super::Queue; + use thread::Thread; + use sync::mpsc::channel; #[test] fn smoke() { @@ -320,7 +322,7 @@ mod test { let (tx, rx) = channel(); let q2 = q.clone(); - spawn(move|| { + let _t = Thread::spawn(move|| { for _ in range(0u, 100000) { loop { match q2.pop() { @@ -330,12 +332,12 @@ mod test { } } } - tx.send(()); + tx.send(()).unwrap(); }); for _ in range(0i, 100000) { q.push(1); } - rx.recv(); + rx.recv().unwrap(); } } } diff --git a/src/libstd/comm/stream.rs b/src/libstd/sync/mpsc/stream.rs index b68f626060e..01b799283ee 100644 --- a/src/libstd/comm/stream.rs +++ b/src/libstd/sync/mpsc/stream.rs @@ -28,10 +28,10 @@ use core::cmp; use core::int; use thread::Thread; +use sync::mpsc::blocking::{mod, SignalToken}; +use sync::mpsc::spsc_queue as spsc; +use sync::mpsc::Receiver; use sync::atomic; -use comm::spsc_queue as spsc; -use comm::Receiver; -use comm::blocking::{mod, SignalToken}; const DISCONNECTED: int = int::MIN; #[cfg(test)] diff --git a/src/libstd/comm/sync.rs b/src/libstd/sync/mpsc/sync.rs index a8004155af0..98f1c4c46f9 100644 --- a/src/libstd/comm/sync.rs +++ b/src/libstd/sync/mpsc/sync.rs @@ -42,8 +42,8 @@ use vec::Vec; use core::mem; use sync::{atomic, Mutex, MutexGuard}; -use comm::blocking::{mod, WaitToken, SignalToken}; -use comm::select::StartResult::{mod, Installed, Abort}; +use sync::mpsc::blocking::{mod, WaitToken, SignalToken}; +use sync::mpsc::select::StartResult::{mod, Installed, Abort}; pub struct Packet<T> { /// Only field outside of the mutex. Just done for kicks, but mainly because @@ -204,14 +204,14 @@ impl<T: Send> Packet<T> { pub fn try_send(&self, t: T) -> Result<(), super::TrySendError<T>> { let mut guard = self.lock.lock().unwrap(); if guard.disconnected { - Err(super::RecvDisconnected(t)) + Err(super::TrySendError::Disconnected(t)) } else if guard.buf.size() == guard.buf.cap() { - Err(super::Full(t)) + Err(super::TrySendError::Full(t)) } else if guard.cap == 0 { // With capacity 0, even though we have buffer space we can't // transfer the data unless there's a receiver waiting. match mem::replace(&mut guard.blocker, NoneBlocked) { - NoneBlocked => Err(super::Full(t)), + NoneBlocked => Err(super::TrySendError::Full(t)), BlockedSender(..) => unreachable!(), BlockedReceiver(token) => { guard.buf.enqueue(t); diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 52004bb4a8f..f9f9a809221 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -8,10 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use prelude::*; +use prelude::v1::*; use cell::UnsafeCell; use kinds::marker; +use ops::{Deref, DerefMut}; use sync::poison::{mod, TryLockError, TryLockResult, LockResult}; use sys_common::mutex as sys; @@ -47,6 +48,8 @@ use sys_common::mutex as sys; /// ```rust /// use std::sync::{Arc, Mutex}; /// use std::thread::Thread; +/// use std::sync::mpsc::channel; +/// /// const N: uint = 10; /// /// // Spawn a few threads to increment a shared variable (non-atomically), and @@ -69,13 +72,13 @@ use sys_common::mutex as sys; /// let mut data = data.lock().unwrap(); /// *data += 1; /// if *data == N { -/// tx.send(()); +/// tx.send(()).unwrap(); /// } /// // the lock is unlocked here when `data` goes out of scope. /// }).detach(); /// } /// -/// rx.recv(); +/// rx.recv().unwrap(); /// ``` /// /// To recover from a poisoned mutex: @@ -288,12 +291,14 @@ impl<'mutex, T> MutexGuard<'mutex, T> { } } -impl<'mutex, T> Deref<T> for MutexGuard<'mutex, T> { +impl<'mutex, T> Deref for MutexGuard<'mutex, T> { + type Target = T; + fn deref<'a>(&'a self) -> &'a T { unsafe { &*self.__data.get() } } } -impl<'mutex, T> DerefMut<T> for MutexGuard<'mutex, T> { +impl<'mutex, T> DerefMut for MutexGuard<'mutex, T> { fn deref_mut<'a>(&'a mut self) -> &'a mut T { unsafe { &mut *self.__data.get() } } @@ -320,10 +325,11 @@ pub fn guard_poison<'a, T>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag { #[cfg(test)] mod test { - use prelude::*; + use prelude::v1::*; - use thread::Thread; + use sync::mpsc::channel; use sync::{Arc, Mutex, StaticMutex, MUTEX_INIT, Condvar}; + use thread::Thread; struct Packet<T>(Arc<(Mutex<T>, Condvar)>); @@ -366,14 +372,14 @@ mod test { let (tx, rx) = channel(); for _ in range(0, K) { let tx2 = tx.clone(); - spawn(move|| { inc(); tx2.send(()); }); + Thread::spawn(move|| { inc(); tx2.send(()).unwrap(); }).detach(); let tx2 = tx.clone(); - spawn(move|| { inc(); tx2.send(()); }); + Thread::spawn(move|| { inc(); tx2.send(()).unwrap(); }).detach(); } drop(tx); for _ in range(0, 2 * K) { - rx.recv(); + rx.recv().unwrap(); } assert_eq!(unsafe {CNT}, J * K * 2); unsafe { @@ -392,9 +398,9 @@ mod test { let packet = Packet(Arc::new((Mutex::new(false), Condvar::new()))); let packet2 = Packet(packet.0.clone()); let (tx, rx) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { // wait until parent gets in - rx.recv(); + rx.recv().unwrap(); let &(ref lock, ref cvar) = &*packet2.0; let mut lock = lock.lock().unwrap(); *lock = true; @@ -403,7 +409,7 @@ mod test { let &(ref lock, ref cvar) = &*packet.0; let mut lock = lock.lock().unwrap(); - tx.send(()); + tx.send(()).unwrap(); assert!(!*lock); while !*lock { lock = cvar.wait(lock).unwrap(); @@ -416,8 +422,8 @@ mod test { let packet2 = Packet(packet.0.clone()); let (tx, rx) = channel(); - spawn(move|| { - rx.recv(); + let _t = Thread::spawn(move || -> () { + rx.recv().unwrap(); let &(ref lock, ref cvar) = &*packet2.0; let _g = lock.lock().unwrap(); cvar.notify_one(); @@ -427,7 +433,7 @@ mod test { let &(ref lock, ref cvar) = &*packet.0; let mut lock = lock.lock().unwrap(); - tx.send(()); + tx.send(()).unwrap(); while *lock == 1 { match cvar.wait(lock) { Ok(l) => { @@ -443,7 +449,7 @@ mod test { fn test_mutex_arc_poison() { let arc = Arc::new(Mutex::new(1i)); let arc2 = arc.clone(); - Thread::spawn(move|| { + let _ = Thread::spawn(move|| { let lock = arc2.lock().unwrap(); assert_eq!(*lock, 2); }).join(); @@ -457,13 +463,13 @@ mod test { let arc = Arc::new(Mutex::new(1i)); let arc2 = Arc::new(Mutex::new(arc)); let (tx, rx) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { let lock = arc2.lock().unwrap(); - let lock2 = lock.deref().lock().unwrap(); + let lock2 = lock.lock().unwrap(); assert_eq!(*lock2, 1); - tx.send(()); + tx.send(()).unwrap(); }); - rx.recv(); + rx.recv().unwrap(); } #[test] diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 4d9fbb59908..9e9a17e482f 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -32,10 +32,11 @@ use sync::{StaticMutex, MUTEX_INIT}; /// /// static START: Once = ONCE_INIT; /// -/// START.doit(|| { +/// START.call_once(|| { /// // run initialization here /// }); /// ``` +#[stable] pub struct Once { mutex: StaticMutex, cnt: atomic::AtomicInt, @@ -45,23 +46,25 @@ pub struct Once { unsafe impl Sync for Once {} /// Initialization value for static `Once` values. +#[stable] pub const ONCE_INIT: Once = Once { mutex: MUTEX_INIT, - cnt: atomic::INIT_ATOMIC_INT, - lock_cnt: atomic::INIT_ATOMIC_INT, + cnt: atomic::ATOMIC_INT_INIT, + lock_cnt: atomic::ATOMIC_INT_INIT, }; impl Once { /// Perform an initialization routine once and only once. The given closure - /// will be executed if this is the first time `doit` has been called, and - /// otherwise the routine will *not* be invoked. + /// will be executed if this is the first time `call_once` has been called, + /// and otherwise the routine will *not* be invoked. /// /// This method will block the calling task if another initialization /// routine is currently running. /// /// When this function returns, it is guaranteed that some initialization /// has run and completed (it may not be the closure specified). - pub fn doit<F>(&'static self, f: F) where F: FnOnce() { + #[stable] + pub fn call_once<F>(&'static self, f: F) where F: FnOnce() { // Optimize common path: load is much cheaper than fetch_add. if self.cnt.load(atomic::SeqCst) < 0 { return @@ -91,13 +94,13 @@ impl Once { // // It is crucial that the negative value is swapped in *after* the // initialization routine has completed because otherwise new threads - // calling `doit` will return immediately before the initialization has - // completed. + // calling `call_once` will return immediately before the initialization + // has completed. let prev = self.cnt.fetch_add(1, atomic::SeqCst); if prev < 0 { // Make sure we never overflow, we'll never have int::MIN - // simultaneous calls to `doit` to make this value go back to 0 + // simultaneous calls to `call_once` to make this value go back to 0 self.cnt.store(int::MIN, atomic::SeqCst); return } @@ -118,22 +121,27 @@ impl Once { unsafe { self.mutex.destroy() } } } + + /// Deprecated + #[deprecated = "renamed to `call_once`"] + pub fn doit<F>(&'static self, f: F) where F: FnOnce() { self.call_once(f) } } #[cfg(test)] mod test { - use prelude::*; + use prelude::v1::*; use thread::Thread; use super::{ONCE_INIT, Once}; + use sync::mpsc::channel; #[test] fn smoke_once() { static O: Once = ONCE_INIT; let mut a = 0i; - O.doit(|| a += 1); + O.call_once(|| a += 1); assert_eq!(a, 1); - O.doit(|| a += 1); + O.call_once(|| a += 1); assert_eq!(a, 1); } @@ -145,21 +153,21 @@ mod test { let (tx, rx) = channel(); for _ in range(0u, 10) { let tx = tx.clone(); - spawn(move|| { + Thread::spawn(move|| { for _ in range(0u, 4) { Thread::yield_now() } unsafe { - O.doit(|| { + O.call_once(|| { assert!(!run); run = true; }); assert!(run); } - tx.send(()); - }); + tx.send(()).unwrap(); + }).detach(); } unsafe { - O.doit(|| { + O.call_once(|| { assert!(!run); run = true; }); @@ -167,7 +175,7 @@ mod test { } for _ in range(0u, 10) { - rx.recv(); + rx.recv().unwrap(); } } } diff --git a/src/libstd/sync/poison.rs b/src/libstd/sync/poison.rs index edf16d99f49..6e4df118209 100644 --- a/src/libstd/sync/poison.rs +++ b/src/libstd/sync/poison.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use prelude::*; +use prelude::v1::*; use cell::UnsafeCell; use error::FromError; diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index 7f3c77c97ad..431aeb9cae9 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -8,10 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use prelude::*; +use prelude::v1::*; use cell::UnsafeCell; use kinds::marker; +use ops::{Deref, DerefMut}; use sync::poison::{mod, LockResult, TryLockError, TryLockResult}; use sys_common::rwlock as sys; @@ -326,13 +327,17 @@ impl<'rwlock, T> RWLockWriteGuard<'rwlock, T> { } } -impl<'rwlock, T> Deref<T> for RWLockReadGuard<'rwlock, T> { +impl<'rwlock, T> Deref for RWLockReadGuard<'rwlock, T> { + type Target = T; + fn deref(&self) -> &T { unsafe { &*self.__data.get() } } } -impl<'rwlock, T> Deref<T> for RWLockWriteGuard<'rwlock, T> { +impl<'rwlock, T> Deref for RWLockWriteGuard<'rwlock, T> { + type Target = T; + fn deref(&self) -> &T { unsafe { &*self.__data.get() } } } -impl<'rwlock, T> DerefMut<T> for RWLockWriteGuard<'rwlock, T> { +impl<'rwlock, T> DerefMut for RWLockWriteGuard<'rwlock, T> { fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.__data.get() } } @@ -355,9 +360,10 @@ impl<'a, T> Drop for RWLockWriteGuard<'a, T> { #[cfg(test)] mod tests { - use prelude::*; + use prelude::v1::*; use rand::{mod, Rng}; + use sync::mpsc::channel; use thread::Thread; use sync::{Arc, RWLock, StaticRWLock, RWLOCK_INIT}; @@ -389,7 +395,7 @@ mod tests { let (tx, rx) = channel::<()>(); for _ in range(0, N) { let tx = tx.clone(); - spawn(move|| { + Thread::spawn(move|| { let mut rng = rand::thread_rng(); for _ in range(0, M) { if rng.gen_weighted_bool(N) { @@ -399,10 +405,10 @@ mod tests { } } drop(tx); - }); + }).detach(); } drop(tx); - let _ = rx.recv_opt(); + let _ = rx.recv(); unsafe { R.destroy(); } } @@ -465,7 +471,7 @@ mod tests { Thread::yield_now(); *lock = tmp + 1; } - tx.send(()); + tx.send(()).unwrap(); }).detach(); // Readers try to catch the writer in the act @@ -484,7 +490,7 @@ mod tests { } // Wait for writer to finish - rx.recv(); + rx.recv().unwrap(); let lock = arc.read().unwrap(); assert_eq!(*lock, 10); } diff --git a/src/libstd/sync/semaphore.rs b/src/libstd/sync/semaphore.rs index e3b683a6ccb..c0ff674ba0f 100644 --- a/src/libstd/sync/semaphore.rs +++ b/src/libstd/sync/semaphore.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![unstable = "the interaction between semaphores and the acquisition/release \ + of resources is currently unclear"] + use ops::Drop; use sync::{Mutex, Condvar}; @@ -104,10 +107,12 @@ impl<'a> Drop for SemaphoreGuard<'a> { #[cfg(test)] mod tests { - use prelude::*; + use prelude::v1::*; use sync::Arc; use super::Semaphore; + use sync::mpsc::channel; + use thread::Thread; #[test] fn test_sem_acquire_release() { @@ -127,7 +132,7 @@ mod tests { fn test_sem_as_mutex() { let s = Arc::new(Semaphore::new(1)); let s2 = s.clone(); - spawn(move|| { + let _t = Thread::spawn(move|| { let _g = s2.access(); }); let _g = s.access(); @@ -139,9 +144,9 @@ mod tests { let (tx, rx) = channel(); let s = Arc::new(Semaphore::new(0)); let s2 = s.clone(); - spawn(move|| { + let _t = Thread::spawn(move|| { s2.acquire(); - tx.send(()); + tx.send(()).unwrap(); }); s.release(); let _ = rx.recv(); @@ -150,12 +155,12 @@ mod tests { let (tx, rx) = channel(); let s = Arc::new(Semaphore::new(0)); let s2 = s.clone(); - spawn(move|| { + let _t = Thread::spawn(move|| { s2.release(); let _ = rx.recv(); }); s.acquire(); - tx.send(()); + tx.send(()).unwrap(); } #[test] @@ -166,14 +171,14 @@ mod tests { let s2 = s.clone(); let (tx1, rx1) = channel(); let (tx2, rx2) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { let _g = s2.access(); let _ = rx2.recv(); - tx1.send(()); + tx1.send(()).unwrap(); }); let _g = s.access(); - tx2.send(()); - let _ = rx1.recv(); + tx2.send(()).unwrap(); + rx1.recv().unwrap(); } #[test] @@ -183,13 +188,13 @@ mod tests { let (tx, rx) = channel(); { let _g = s.access(); - spawn(move|| { - tx.send(()); + Thread::spawn(move|| { + tx.send(()).unwrap(); drop(s2.access()); - tx.send(()); - }); - rx.recv(); // wait for child to come alive + tx.send(()).unwrap(); + }).detach(); + rx.recv().unwrap(); // wait for child to come alive } - rx.recv(); // wait for child to be done + rx.recv().unwrap(); // wait for child to be done } } diff --git a/src/libstd/sync/task_pool.rs b/src/libstd/sync/task_pool.rs index ee534f6cdde..088827dc084 100644 --- a/src/libstd/sync/task_pool.rs +++ b/src/libstd/sync/task_pool.rs @@ -10,11 +10,16 @@ //! Abstraction of a thread pool for basic parallelism. +#![unstable = "the semantics of a failing task and whether a thread is \ + re-attached to a thread pool are somewhat unclear, and the \ + utility of this type in `std::sync` is questionable with \ + respect to the jobs of other primitives"] + use core::prelude::*; -use thread::Thread; -use comm::{channel, Sender, Receiver}; use sync::{Arc, Mutex}; +use sync::mpsc::{channel, Sender, Receiver}; +use thread::Thread; use thunk::Thunk; struct Sentinel<'a> { @@ -53,8 +58,9 @@ impl<'a> Drop for Sentinel<'a> { /// # Example /// /// ```rust -/// # use std::sync::TaskPool; -/// # use std::iter::AdditiveIterator; +/// use std::sync::TaskPool; +/// use std::iter::AdditiveIterator; +/// use std::sync::mpsc::channel; /// /// let pool = TaskPool::new(4u); /// @@ -62,7 +68,7 @@ impl<'a> Drop for Sentinel<'a> { /// for _ in range(0, 8u) { /// let tx = tx.clone(); /// pool.execute(move|| { -/// tx.send(1u); +/// tx.send(1u).unwrap(); /// }); /// } /// @@ -100,7 +106,7 @@ impl TaskPool { pub fn execute<F>(&self, job: F) where F : FnOnce(), F : Send { - self.jobs.send(Thunk::new(job)); + self.jobs.send(Thunk::new(job)).unwrap(); } } @@ -114,7 +120,7 @@ fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk>>>) { // Only lock jobs for the time it takes // to get a job, not run it. let lock = jobs.lock().unwrap(); - lock.recv_opt() + lock.recv() }; match message { @@ -131,8 +137,9 @@ fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk>>>) { #[cfg(test)] mod test { - use prelude::*; + use prelude::v1::*; use super::*; + use sync::mpsc::channel; const TEST_TASKS: uint = 4u; @@ -146,7 +153,7 @@ mod test { for _ in range(0, TEST_TASKS) { let tx = tx.clone(); pool.execute(move|| { - tx.send(1u); + tx.send(1u).unwrap(); }); } @@ -175,7 +182,7 @@ mod test { for _ in range(0, TEST_TASKS) { let tx = tx.clone(); pool.execute(move|| { - tx.send(1u); + tx.send(1u).unwrap(); }); } diff --git a/src/libstd/sys/common/backtrace.rs b/src/libstd/sys/common/backtrace.rs index 866bf1d8a7d..d4039fd96ff 100644 --- a/src/libstd/sys/common/backtrace.rs +++ b/src/libstd/sys/common/backtrace.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use prelude::*; +use prelude::v1::*; use io::IoResult; diff --git a/src/libstd/sys/common/helper_thread.rs b/src/libstd/sys/common/helper_thread.rs index 9ef1c33312f..bdf1bf3dfd0 100644 --- a/src/libstd/sys/common/helper_thread.rs +++ b/src/libstd/sys/common/helper_thread.rs @@ -20,12 +20,13 @@ //! can be created in the future and there must be no active timers at that //! time. -use prelude::*; +use prelude::v1::*; use cell::UnsafeCell; use mem; -use sync::{StaticMutex, StaticCondvar}; use rt; +use sync::{StaticMutex, StaticCondvar}; +use sync::mpsc::{channel, Sender, Receiver}; use sys::helper_signal; use thread::Thread; @@ -117,7 +118,7 @@ impl<M: Send> Helper<M> { // message. Otherwise it could wake up and go to sleep before we // send the message. assert!(!self.chan.get().is_null()); - (**self.chan.get()).send(msg); + (**self.chan.get()).send(msg).unwrap(); helper_signal::signal(*self.signal.get() as helper_signal::signal); } } diff --git a/src/libstd/sys/common/mod.rs b/src/libstd/sys/common/mod.rs index dc0ad08cdbe..97015f74a4a 100644 --- a/src/libstd/sys/common/mod.rs +++ b/src/libstd/sys/common/mod.rs @@ -12,7 +12,7 @@ #![allow(dead_code)] use io::{mod, IoError, IoResult}; -use prelude::*; +use prelude::v1::*; use sys::{last_error, retry}; use c_str::CString; use num::Int; diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs index 259c15b5f06..cb0c5581abd 100644 --- a/src/libstd/sys/common/net.rs +++ b/src/libstd/sys/common/net.rs @@ -8,24 +8,24 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use prelude::v1::*; use self::SocketStatus::*; use self::InAddr::*; -use alloc::arc::Arc; +use c_str::ToCStr; +use io::net::addrinfo; +use io::net::ip::{SocketAddr, IpAddr, Ipv4Addr, Ipv6Addr}; +use io::{IoResult, IoError}; use libc::{mod, c_char, c_int}; use c_str::CString; use mem; use num::Int; use ptr::{mod, null, null_mut}; -use io::net::ip::{SocketAddr, IpAddr, Ipv4Addr, Ipv6Addr}; -use io::net::addrinfo; -use io::{IoResult, IoError}; use sys::{mod, retry, c, sock_t, last_error, last_net_error, last_gai_error, close_sock, wrlen, msglen_t, os, wouldblock, set_nonblocking, timer, ms_to_timeval, decode_error_detailed}; -use sync::{Mutex, MutexGuard}; +use sync::{Arc, Mutex, MutexGuard}; use sys_common::{mod, keep_going, short_write, timeout}; -use prelude::*; use cmp; use io; diff --git a/src/libstd/sys/common/thread_info.rs b/src/libstd/sys/common/thread_info.rs index 8c76eb1504d..92b936e74f6 100644 --- a/src/libstd/sys/common/thread_info.rs +++ b/src/libstd/sys/common/thread_info.rs @@ -10,9 +10,10 @@ use core::prelude::*; -use thread::Thread; use cell::RefCell; use string::String; +use thread::Thread; +use thread_local::State; struct ThreadInfo { // This field holds the known bounds of the stack in (lo, hi) @@ -27,7 +28,7 @@ thread_local! { static THREAD_INFO: RefCell<Option<ThreadInfo>> = RefCell::new(N impl ThreadInfo { fn with<R, F>(f: F) -> R where F: FnOnce(&mut ThreadInfo) -> R { - if THREAD_INFO.destroyed() { + if THREAD_INFO.state() == State::Destroyed { panic!("Use of std::thread::Thread::current() is not possible after \ the thread's local data has been destroyed"); } diff --git a/src/libstd/sys/common/thread_local.rs b/src/libstd/sys/common/thread_local.rs index fe7a7d8d037..9d7188a37bc 100644 --- a/src/libstd/sys/common/thread_local.rs +++ b/src/libstd/sys/common/thread_local.rs @@ -56,7 +56,7 @@ #![allow(non_camel_case_types)] -use prelude::*; +use prelude::v1::*; use sync::atomic::{mod, AtomicUint}; use sync::{Mutex, Once, ONCE_INIT}; @@ -137,7 +137,7 @@ pub const INIT: StaticKey = StaticKey { /// /// This value allows specific configuration of the destructor for a TLS key. pub const INIT_INNER: StaticKeyInner = StaticKeyInner { - key: atomic::INIT_ATOMIC_UINT, + key: atomic::ATOMIC_UINT_INIT, }; static INIT_KEYS: Once = ONCE_INIT; @@ -246,7 +246,7 @@ impl Drop for Key { #[cfg(test)] mod tests { - use prelude::*; + use prelude::v1::*; use super::{Key, StaticKey, INIT_INNER}; fn assert_sync<T: Sync>() {} diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 8de4ffa7022..e3e0b279c12 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -10,16 +10,15 @@ //! Blocking posix-based file I/O -use libc::{mod, c_int, c_void}; -use c_str::CString; -use mem; -use io; - -use prelude::*; +use prelude::v1::*; +use c_str::{CString, ToCStr}; use io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode}; use io::{IoResult, FileStat, SeekStyle}; use io::{Read, Truncate, SeekCur, SeekSet, ReadWrite, SeekEnd, Append}; +use io; +use libc::{mod, c_int, c_void}; +use mem; use sys::retry; use sys_common::{keep_going, eof, mkerr_libc}; @@ -360,7 +359,7 @@ mod tests { use super::FileDesc; use libc; use os; - use prelude::*; + use prelude::v1::*; #[cfg_attr(target_os = "freebsd", ignore)] // hmm, maybe pipes have a tiny buffer #[test] diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index c82dacf1e44..4199cbc1bb9 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -19,7 +19,7 @@ extern crate libc; use num; use num::{Int, SignedInt}; -use prelude::*; +use prelude::v1::*; use io::{mod, IoResult, IoError}; use sys_common::mkerr_libc; diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index 595191db3b2..6a8f55e79c8 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -10,17 +10,18 @@ //! Implementation of `std::os` functionality for unix systems -use prelude::*; +use prelude::v1::*; +use c_str::ToCStr; use error::{FromError, Error}; use fmt; use io::{IoError, IoResult}; use libc::{mod, c_int, c_char, c_void}; -use path::BytesContainer; +use os; +use path::{BytesContainer}; use ptr; -use sync::atomic::{AtomicInt, INIT_ATOMIC_INT, SeqCst}; +use sync::atomic::{AtomicInt, SeqCst}; use sys::fs::FileDesc; -use os; use os::TMPBUF_SZ; diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs index 868b460aa5e..623f3f6a89c 100644 --- a/src/libstd/sys/unix/pipe.rs +++ b/src/libstd/sys/unix/pipe.rs @@ -8,13 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use alloc::arc::Arc; +use prelude::v1::*; + use libc; use c_str::CString; use mem; -use sync::{atomic, Mutex}; +use sync::{atomic, Arc, Mutex}; use io::{mod, IoResult, IoError}; -use prelude::*; use sys::{mod, timer, retry, c, set_nonblocking, wouldblock}; use sys::fs::{fd_t, FileDesc}; @@ -117,9 +117,6 @@ pub struct UnixStream { write_deadline: u64, } -unsafe impl Send for UnixStream {} -unsafe impl Sync for UnixStream {} - impl UnixStream { pub fn connect(addr: &CString, timeout: Option<u64>) -> IoResult<UnixStream> { @@ -218,6 +215,7 @@ pub struct UnixListener { path: CString, } +// we currently own the CString, so these impls should be safe unsafe impl Send for UnixListener {} unsafe impl Sync for UnixListener {} @@ -265,9 +263,6 @@ struct AcceptorInner { closed: atomic::AtomicBool, } -unsafe impl Send for AcceptorInner {} -unsafe impl Sync for AcceptorInner {} - impl UnixAcceptor { pub fn fd(&self) -> fd_t { self.inner.listener.fd() } diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs index c1c28bd5fc4..af09bf4fbd0 100644 --- a/src/libstd/sys/unix/process.rs +++ b/src/libstd/sys/unix/process.rs @@ -7,22 +7,23 @@ // <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. + +use prelude::v1::*; use self::Req::*; -use libc::{mod, pid_t, c_void, c_int}; -use c_str::CString; +use c_str::{CString, ToCStr}; +use collections; +use hash::Hash; +use io::process::{ProcessExit, ExitStatus, ExitSignal}; use io::{mod, IoResult, IoError, EndOfFile}; +use libc::{mod, pid_t, c_void, c_int}; use mem; use os; -use ptr; -use prelude::*; -use io::process::{ProcessExit, ExitStatus, ExitSignal}; -use collections; use path::BytesContainer; -use hash::Hash; - -use sys::{mod, retry, c, wouldblock, set_nonblocking, ms_to_timeval}; +use ptr; +use sync::mpsc::{channel, Sender, Receiver}; use sys::fs::FileDesc; +use sys::{mod, retry, c, wouldblock, set_nonblocking, ms_to_timeval}; use sys_common::helper_thread::Helper; use sys_common::{AsInner, mkerr_libc, timeout}; @@ -276,8 +277,8 @@ impl Process { } pub fn wait(&self, deadline: u64) -> IoResult<ProcessExit> { - use std::cmp; - use std::comm; + use cmp; + use sync::mpsc::TryRecvError; static mut WRITE_FD: libc::c_int = 0; @@ -336,9 +337,9 @@ impl Process { let (tx, rx) = channel(); unsafe { HELPER.send(NewChild(self.pid, tx, deadline)); } - return match rx.recv_opt() { + return match rx.recv() { Ok(e) => Ok(e), - Err(()) => Err(timeout("wait timed out")), + Err(..) => Err(timeout("wait timed out")), }; // Register a new SIGCHLD handler, returning the reading half of the @@ -419,11 +420,11 @@ impl Process { Ok(NewChild(pid, tx, deadline)) => { active.push((pid, tx, deadline)); } - Err(comm::Disconnected) => { + Err(TryRecvError::Disconnected) => { assert!(active.len() == 0); break 'outer; } - Err(comm::Empty) => break, + Err(TryRecvError::Empty) => break, } } } @@ -459,7 +460,7 @@ impl Process { active.retain(|&(pid, ref tx, _)| { let pr = Process { pid: pid }; match pr.try_wait() { - Some(msg) => { tx.send(msg); false } + Some(msg) => { tx.send(msg).unwrap(); false } None => true, } }); diff --git a/src/libstd/sys/unix/tcp.rs b/src/libstd/sys/unix/tcp.rs index e2a78947e16..13ccf685fd7 100644 --- a/src/libstd/sys/unix/tcp.rs +++ b/src/libstd/sys/unix/tcp.rs @@ -8,12 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use prelude::v1::*; + use io::net::ip; use io::IoResult; use libc; use mem; use ptr; -use prelude::*; use super::{last_error, last_net_error, retry, sock_t}; use sync::{Arc, atomic}; use sys::fs::FileDesc; diff --git a/src/libstd/sys/unix/thread_local.rs b/src/libstd/sys/unix/thread_local.rs index b300e93eeb6..e507377a8fc 100644 --- a/src/libstd/sys/unix/thread_local.rs +++ b/src/libstd/sys/unix/thread_local.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use prelude::*; +use prelude::v1::*; use libc::c_int; pub type Key = pthread_key_t; diff --git a/src/libstd/sys/unix/timer.rs b/src/libstd/sys/unix/timer.rs index c0ef89666c0..80f93dd2f61 100644 --- a/src/libstd/sys/unix/timer.rs +++ b/src/libstd/sys/unix/timer.rs @@ -46,19 +46,19 @@ //! //! Note that all time units in this file are in *milliseconds*. +use prelude::v1::*; use self::Req::*; +use io::IoResult; use libc; use mem; use os; use ptr; use sync::atomic; -use comm; +use sync::mpsc::{channel, Sender, Receiver, TryRecvError}; use sys::c; use sys::fs::FileDesc; use sys_common::helper_thread::Helper; -use prelude::*; -use io::IoResult; helper_init! { static HELPER: Helper<Req> } @@ -168,7 +168,7 @@ fn helper(input: libc::c_int, messages: Receiver<Req>, _: ()) { 1 => { loop { match messages.try_recv() { - Err(comm::Disconnected) => { + Err(TryRecvError::Disconnected) => { assert!(active.len() == 0); break 'outer; } @@ -179,7 +179,7 @@ fn helper(input: libc::c_int, messages: Receiver<Req>, _: ()) { match dead.iter().position(|&(i, _)| id == i) { Some(i) => { let (_, i) = dead.remove(i); - ack.send(i); + ack.send(i).unwrap(); continue } None => {} @@ -187,7 +187,7 @@ fn helper(input: libc::c_int, messages: Receiver<Req>, _: ()) { let i = active.iter().position(|i| i.id == id); let i = i.expect("no timer found"); let t = active.remove(i); - ack.send(t); + ack.send(t).unwrap(); } Err(..) => break } @@ -211,7 +211,7 @@ impl Timer { // instead of () HELPER.boot(|| {}, helper); - static ID: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT; + static ID: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT; let id = ID.fetch_add(1, atomic::Relaxed); Ok(Timer { id: id, @@ -271,7 +271,7 @@ impl Timer { None => { let (tx, rx) = channel(); HELPER.send(RemoveTimer(self.id, tx)); - rx.recv() + rx.recv().unwrap() } } } diff --git a/src/libstd/sys/unix/tty.rs b/src/libstd/sys/unix/tty.rs index 28c17fd4966..4ef687d41d8 100644 --- a/src/libstd/sys/unix/tty.rs +++ b/src/libstd/sys/unix/tty.rs @@ -8,8 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use prelude::v1::*; + use sys::fs::FileDesc; -use prelude::*; use libc::{mod, c_int}; use io::{mod, IoResult, IoError}; use sys_common; diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 6cccefbe890..1ee57434fb9 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -15,7 +15,7 @@ #![allow(non_camel_case_types)] use libc; -use prelude::*; +use prelude::v1::*; pub const WSADESCRIPTION_LEN: uint = 256; pub const WSASYS_STATUS_LEN: uint = 128; @@ -132,7 +132,8 @@ extern "system" { pub mod compat { use intrinsics::{atomic_store_relaxed, transmute}; use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID}; - use prelude::*; + use prelude::v1::*; + use c_str::ToCStr; extern "system" { fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE; diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 3ad439078b9..523d60c71aa 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -21,7 +21,7 @@ use ptr; use str; use io; -use prelude::*; +use prelude::v1::*; use sys; use sys::os; use sys_common::{keep_going, eof, mkerr_libc}; diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 57c284ed6a3..1034f0615d9 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -18,9 +18,10 @@ extern crate libc; +use prelude::v1::*; + use num; use mem; -use prelude::*; use io::{mod, IoResult, IoError}; use sync::{Once, ONCE_INIT}; @@ -28,7 +29,7 @@ macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => ( static $name: Helper<$m> = Helper { lock: ::sync::MUTEX_INIT, cond: ::sync::CONDVAR_INIT, - chan: ::cell::UnsafeCell { value: 0 as *mut Sender<$m> }, + chan: ::cell::UnsafeCell { value: 0 as *mut ::sync::mpsc::Sender<$m> }, signal: ::cell::UnsafeCell { value: 0 }, initialized: ::cell::UnsafeCell { value: false }, shutdown: ::cell::UnsafeCell { value: false }, @@ -171,7 +172,7 @@ pub fn init_net() { unsafe { static START: Once = ONCE_INIT; - START.doit(|| { + START.call_once(|| { let mut data: c::WSADATA = mem::zeroed(); let ret = c::WSAStartup(0x202, // version 2.2 &mut data); diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs index 3ac7c09154e..e0fa02b5599 100644 --- a/src/libstd/sys/windows/mutex.rs +++ b/src/libstd/sys/windows/mutex.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use prelude::*; +use prelude::v1::*; use sync::atomic; use alloc::{mod, heap}; @@ -20,7 +20,7 @@ const SPIN_COUNT: DWORD = 4000; pub struct Mutex { inner: atomic::AtomicUint } -pub const MUTEX_INIT: Mutex = Mutex { inner: atomic::INIT_ATOMIC_UINT }; +pub const MUTEX_INIT: Mutex = Mutex { inner: atomic::ATOMIC_UINT_INIT }; unsafe impl Sync for Mutex {} diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index 09003f87ff0..dfdee0e0385 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -13,7 +13,7 @@ // FIXME: move various extern bindings from here into liblibc or // something similar -use prelude::*; +use prelude::v1::*; use fmt; use io::{IoResult, IoError}; diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs index fc3640f2604..f173d5fc6d4 100644 --- a/src/libstd/sys/windows/pipe.rs +++ b/src/libstd/sys/windows/pipe.rs @@ -84,14 +84,14 @@ //! the test suite passing (the suite is in libstd), and that's good enough for //! me! -use alloc::arc::Arc; +use prelude::v1::*; + use libc; use c_str::CString; use mem; use ptr; -use sync::{atomic, Mutex}; +use sync::{atomic, Arc, Mutex}; use io::{mod, IoError, IoResult}; -use prelude::*; use sys_common::{mod, eof}; diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index b03c62395d1..cb99a886ce4 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -8,14 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use prelude::v1::*; + use libc::{pid_t, c_void, c_int}; use libc; -use c_str::CString; +use c_str::{CString, ToCStr}; use io; use mem; use os; use ptr; -use prelude::*; use io::process::{ProcessExit, ExitStatus, ExitSignal}; use collections; use path::BytesContainer; @@ -466,10 +467,11 @@ fn free_handle(handle: *mut ()) { #[cfg(test)] mod tests { + use c_str::ToCStr; #[test] fn test_make_command_line() { - use prelude::*; + use prelude::v1::*; use str; use c_str::CString; use super::make_command_line; diff --git a/src/libstd/sys/windows/tcp.rs b/src/libstd/sys/windows/tcp.rs index 513c1d38e36..5a929f6b2b5 100644 --- a/src/libstd/sys/windows/tcp.rs +++ b/src/libstd/sys/windows/tcp.rs @@ -13,7 +13,7 @@ use io::IoResult; use libc; use mem; use ptr; -use prelude::*; +use prelude::v1::*; use super::{last_error, last_net_error, retry, sock_t}; use sync::{Arc, atomic}; use sys::fs::FileDesc; diff --git a/src/libstd/sys/windows/thread_local.rs b/src/libstd/sys/windows/thread_local.rs index 60b0d584db3..b96e26c7a86 100644 --- a/src/libstd/sys/windows/thread_local.rs +++ b/src/libstd/sys/windows/thread_local.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use prelude::*; +use prelude::v1::*; use libc::types::os::arch::extra::{DWORD, LPVOID, BOOL}; diff --git a/src/libstd/sys/windows/timer.rs b/src/libstd/sys/windows/timer.rs index 874838950cd..343b78543bf 100644 --- a/src/libstd/sys/windows/timer.rs +++ b/src/libstd/sys/windows/timer.rs @@ -21,16 +21,16 @@ //! the other two implementations of timers with nothing *that* new showing up. use self::Req::*; +use prelude::v1::*; use libc; use ptr; -use comm; +use io::IoResult; +use sync::mpsc::{channel, Sender, Receiver, TryRecvError}; use sys::c; use sys::fs::FileDesc; use sys_common::helper_thread::Helper; -use prelude::*; -use io::IoResult; helper_init! { static HELPER: Helper<Req> } @@ -71,7 +71,7 @@ fn helper(input: libc::HANDLE, messages: Receiver<Req>, _: ()) { chans.push((c, one)); } Ok(RemoveTimer(obj, c)) => { - c.send(()); + c.send(()).unwrap(); match objs.iter().position(|&o| o == obj) { Some(i) => { drop(objs.remove(i)); @@ -80,7 +80,7 @@ fn helper(input: libc::HANDLE, messages: Receiver<Req>, _: ()) { None => {} } } - Err(comm::Disconnected) => { + Err(TryRecvError::Disconnected) => { assert_eq!(objs.len(), 1); assert_eq!(chans.len(), 0); break 'outer; @@ -132,7 +132,7 @@ impl Timer { let (tx, rx) = channel(); HELPER.send(RemoveTimer(self.obj, tx)); - rx.recv(); + rx.recv().unwrap(); self.on_worker = false; } diff --git a/src/libstd/sys/windows/tty.rs b/src/libstd/sys/windows/tty.rs index a88d11eed22..7591025d76d 100644 --- a/src/libstd/sys/windows/tty.rs +++ b/src/libstd/sys/windows/tty.rs @@ -25,19 +25,20 @@ //! wrapper that performs encoding/decoding, this implementation should switch //! to working in raw UTF-16, with such a wrapper around it. -use super::c::{ReadConsoleW, WriteConsoleW, GetConsoleMode, SetConsoleMode}; -use super::c::{ERROR_ILLEGAL_CHARACTER}; -use super::c::{ENABLE_ECHO_INPUT, ENABLE_EXTENDED_FLAGS}; -use super::c::{ENABLE_INSERT_MODE, ENABLE_LINE_INPUT}; -use super::c::{ENABLE_PROCESSED_INPUT, ENABLE_QUICK_EDIT_MODE}; -use libc::{c_int, HANDLE, LPDWORD, DWORD, LPVOID}; -use libc::{get_osfhandle, CloseHandle}; -use libc::types::os::arch::extra::LPCVOID; +use prelude::v1::*; + use io::{mod, IoError, IoResult, MemReader}; use iter::repeat; -use prelude::*; +use libc::types::os::arch::extra::LPCVOID; +use libc::{c_int, HANDLE, LPDWORD, DWORD, LPVOID}; +use libc::{get_osfhandle, CloseHandle}; use ptr; use str::from_utf8; +use super::c::{ENABLE_ECHO_INPUT, ENABLE_EXTENDED_FLAGS}; +use super::c::{ENABLE_INSERT_MODE, ENABLE_LINE_INPUT}; +use super::c::{ENABLE_PROCESSED_INPUT, ENABLE_QUICK_EDIT_MODE}; +use super::c::{ERROR_ILLEGAL_CHARACTER}; +use super::c::{ReadConsoleW, WriteConsoleW, GetConsoleMode, SetConsoleMode}; fn invalid_encoding() -> IoError { IoError { diff --git a/src/libstd/thread.rs b/src/libstd/thread.rs index a7b3ee996a3..3c87309dabc 100644 --- a/src/libstd/thread.rs +++ b/src/libstd/thread.rs @@ -440,13 +440,15 @@ impl<T: Send> Drop for JoinGuard<T> { #[cfg(test)] mod test { - use prelude::*; + use prelude::v1::*; + use any::{Any, AnyRefExt}; + use sync::mpsc::{channel, Sender}; use boxed::BoxAny; use result; use std::io::{ChanReader, ChanWriter}; - use thunk::Thunk; use super::{Thread, Builder}; + use thunk::Thunk; // !!! These tests are dangerous. If something is buggy, they will hang, !!! // !!! instead of exiting cleanly. This might wedge the buildbots. !!! @@ -469,9 +471,9 @@ mod test { fn test_run_basic() { let (tx, rx) = channel(); Thread::spawn(move|| { - tx.send(()); + tx.send(()).unwrap(); }).detach(); - rx.recv(); + rx.recv().unwrap(); } #[test] @@ -504,7 +506,7 @@ mod test { let tx = tx.clone(); Thread::spawn(move|| { if i == 0 { - tx.send(()); + tx.send(()).unwrap(); } else { f(i - 1, tx); } @@ -512,7 +514,7 @@ mod test { } f(10, tx); - rx.recv(); + rx.recv().unwrap(); } #[test] @@ -521,11 +523,11 @@ mod test { Thread::spawn(move|| { Thread::spawn(move|| { - tx.send(()); + tx.send(()).unwrap(); }).detach(); }).detach(); - rx.recv(); + rx.recv().unwrap(); } fn avoid_copying_the_body<F>(spawnfn: F) where F: FnOnce(Thunk) { @@ -536,10 +538,10 @@ mod test { spawnfn(Thunk::new(move|| { let x_in_child = (&*x) as *const int as uint; - tx.send(x_in_child); + tx.send(x_in_child).unwrap(); })); - let x_in_child = rx.recv(); + let x_in_child = rx.recv().unwrap(); assert_eq!(x_in_parent, x_in_child); } diff --git a/src/libstd/thread_local/mod.rs b/src/libstd/thread_local/mod.rs index 14dd2a1ac9b..75e5ac59685 100644 --- a/src/libstd/thread_local/mod.rs +++ b/src/libstd/thread_local/mod.rs @@ -35,20 +35,23 @@ //! `Cell` or `RefCell` types. #![macro_escape] -#![experimental] +#![stable] -use prelude::*; +use prelude::v1::*; use cell::UnsafeCell; -// Sure wish we had macro hygiene, no? -#[doc(hidden)] pub use self::imp::Key as KeyInner; -#[doc(hidden)] pub use self::imp::destroy_value; -#[doc(hidden)] pub use sys_common::thread_local::INIT_INNER as OS_INIT_INNER; -#[doc(hidden)] pub use sys_common::thread_local::StaticKey as OsStaticKey; - pub mod scoped; +// Sure wish we had macro hygiene, no? +#[doc(hidden)] +pub mod __impl { + pub use super::imp::Key as KeyInner; + pub use super::imp::destroy_value; + pub use sys_common::thread_local::INIT_INNER as OS_INIT_INNER; + pub use sys_common::thread_local::StaticKey as OsStaticKey; +} + /// A thread local storage key which owns its contents. /// /// This key uses the fastest possible implementation available to it for the @@ -90,6 +93,7 @@ pub mod scoped; /// assert_eq!(*f.borrow(), 2); /// }); /// ``` +#[stable] pub struct Key<T> { // The key itself may be tagged with #[thread_local], and this `Key` is // stored as a `static`, and it's not valid for a static to reference the @@ -100,7 +104,7 @@ pub struct Key<T> { // This is trivially devirtualizable by LLVM because we never store anything // to this field and rustc can declare the `static` as constant as well. #[doc(hidden)] - pub inner: fn() -> &'static KeyInner<UnsafeCell<Option<T>>>, + pub inner: fn() -> &'static __impl::KeyInner<UnsafeCell<Option<T>>>, // initialization routine to invoke to create a value #[doc(hidden)] @@ -109,12 +113,12 @@ pub struct Key<T> { /// Declare a new thread local storage key of type `std::thread_local::Key`. #[macro_export] -#[doc(hidden)] +#[stable] macro_rules! thread_local { (static $name:ident: $t:ty = $init:expr) => ( static $name: ::std::thread_local::Key<$t> = { use std::cell::UnsafeCell as __UnsafeCell; - use std::thread_local::KeyInner as __KeyInner; + use std::thread_local::__impl::KeyInner as __KeyInner; use std::option::Option as __Option; use std::option::Option::None as __None; @@ -131,7 +135,7 @@ macro_rules! thread_local { (pub static $name:ident: $t:ty = $init:expr) => ( pub static $name: ::std::thread_local::Key<$t> = { use std::cell::UnsafeCell as __UnsafeCell; - use std::thread_local::KeyInner as __KeyInner; + use std::thread_local::__impl::KeyInner as __KeyInner; use std::option::Option as __Option; use std::option::Option::None as __None; @@ -168,21 +172,22 @@ macro_rules! thread_local { // itself. Woohoo. #[macro_export] +#[doc(hidden)] macro_rules! __thread_local_inner { (static $name:ident: $t:ty = $init:expr) => ( #[cfg_attr(any(target_os = "macos", target_os = "linux"), thread_local)] - static $name: ::std::thread_local::KeyInner<$t> = + static $name: ::std::thread_local::__impl::KeyInner<$t> = __thread_local_inner!($init, $t); ); (pub static $name:ident: $t:ty = $init:expr) => ( #[cfg_attr(any(target_os = "macos", target_os = "linux"), thread_local)] - pub static $name: ::std::thread_local::KeyInner<$t> = + pub static $name: ::std::thread_local::__impl::KeyInner<$t> = __thread_local_inner!($init, $t); ); ($init:expr, $t:ty) => ({ #[cfg(any(target_os = "macos", target_os = "linux"))] - const INIT: ::std::thread_local::KeyInner<$t> = { - ::std::thread_local::KeyInner { + const _INIT: ::std::thread_local::__impl::KeyInner<$t> = { + ::std::thread_local::__impl::KeyInner { inner: ::std::cell::UnsafeCell { value: $init }, dtor_registered: ::std::cell::UnsafeCell { value: false }, dtor_running: ::std::cell::UnsafeCell { value: false }, @@ -190,24 +195,54 @@ macro_rules! __thread_local_inner { }; #[cfg(all(not(any(target_os = "macos", target_os = "linux"))))] - const INIT: ::std::thread_local::KeyInner<$t> = { + const _INIT: ::std::thread_local::__impl::KeyInner<$t> = { unsafe extern fn __destroy(ptr: *mut u8) { - ::std::thread_local::destroy_value::<$t>(ptr); + ::std::thread_local::__impl::destroy_value::<$t>(ptr); } - ::std::thread_local::KeyInner { + ::std::thread_local::__impl::KeyInner { inner: ::std::cell::UnsafeCell { value: $init }, - os: ::std::thread_local::OsStaticKey { - inner: ::std::thread_local::OS_INIT_INNER, + os: ::std::thread_local::__impl::OsStaticKey { + inner: ::std::thread_local::__impl::OS_INIT_INNER, dtor: ::std::option::Option::Some(__destroy as unsafe extern fn(*mut u8)), }, } }; - INIT + _INIT }); } +/// Indicator of the state of a thread local storage key. +#[unstable = "state querying was recently added"] +#[deriving(Eq, PartialEq, Copy)] +pub enum State { + /// All keys are in this state whenever a thread starts. Keys will + /// transition to the `Valid` state once the first call to `with` happens + /// and the initialization expression succeeds. + /// + /// Keys in the `Uninitialized` state will yield a reference to the closure + /// passed to `with` so long as the initialization routine does not panic. + Uninitialized, + + /// Once a key has been accessed successfully, it will enter the `Valid` + /// state. Keys in the `Valid` state will remain so until the thread exits, + /// at which point the destructor will be run and the key will enter the + /// `Destroyed` state. + /// + /// Keys in the `Valid` state will be guaranteed to yield a reference to the + /// closure passed to `with`. + Valid, + + /// When a thread exits, the destructors for keys will be run (if + /// necessary). While a destructor is running, and possibly after a + /// destructor has run, a key is in the `Destroyed` state. + /// + /// Keys in the `Destroyed` states will trigger a panic when accessed via + /// `with`. + Destroyed, +} + impl<T: 'static> Key<T> { /// Acquire a reference to the value in this TLS key. /// @@ -219,6 +254,7 @@ impl<T: 'static> Key<T> { /// This function will `panic!()` if the key currently has its /// destructor running, and it **may** panic if the destructor has /// previously been run for this thread. + #[stable] pub fn with<F, R>(&'static self, f: F) -> R where F: FnOnce(&T) -> R { let slot = (self.inner)(); @@ -233,22 +269,57 @@ impl<T: 'static> Key<T> { } unsafe fn init(&self, slot: &UnsafeCell<Option<T>>) -> &T { - *slot.get() = Some((self.init)()); - (*slot.get()).as_ref().unwrap() + // Execute the initialization up front, *then* move it into our slot, + // just in case initialization fails. + let value = (self.init)(); + let ptr = slot.get(); + *ptr = Some(value); + (*ptr).as_ref().unwrap() } - /// Test this TLS key to determine whether its value has been destroyed for - /// the current thread or not. + /// Query the current state of this key. + /// + /// A key is initially in the `Uninitialized` state whenever a thread + /// starts. It will remain in this state up until the first call to `with` + /// within a thread has run the initialization expression successfully. + /// + /// Once the initialization expression succeeds, the key transitions to the + /// `Valid` state which will guarantee that future calls to `with` will + /// succeed within the thread. /// - /// This will not initialize the key if it is not already initialized. - pub fn destroyed(&'static self) -> bool { - unsafe { (self.inner)().get().is_none() } + /// When a thread exits, each key will be destroyed in turn, and as keys are + /// destroyed they will enter the `Destroyed` state just before the + /// destructor starts to run. Keys may remain in the `Destroyed` state after + /// destruction has completed. Keys without destructors (e.g. with types + /// that are `Copy`), may never enter the `Destroyed` state. + /// + /// Keys in the `Uninitialized` can be accessed so long as the + /// initialization does not panic. Keys in the `Valid` state are guaranteed + /// to be able to be accessed. Keys in the `Destroyed` state will panic on + /// any call to `with`. + #[unstable = "state querying was recently added"] + pub fn state(&'static self) -> State { + unsafe { + match (self.inner)().get() { + Some(cell) => { + match *cell.get() { + Some(..) => State::Valid, + None => State::Uninitialized, + } + } + None => State::Destroyed, + } + } } + + /// Deprecated + #[deprecated = "function renamed to state() and returns more info"] + pub fn destroyed(&'static self) -> bool { self.state() == State::Destroyed } } #[cfg(any(target_os = "macos", target_os = "linux"))] mod imp { - use prelude::*; + use prelude::v1::*; use cell::UnsafeCell; use intrinsics; @@ -380,7 +451,7 @@ mod imp { #[cfg(not(any(target_os = "macos", target_os = "linux")))] mod imp { - use prelude::*; + use prelude::v1::*; use cell::UnsafeCell; use mem; @@ -453,9 +524,11 @@ mod imp { #[cfg(test)] mod tests { - use prelude::*; + use prelude::v1::*; + use sync::mpsc::{channel, Sender}; use cell::UnsafeCell; + use super::State; use thread::Thread; struct Foo(Sender<()>); @@ -463,7 +536,7 @@ mod tests { impl Drop for Foo { fn drop(&mut self) { let Foo(ref s) = *self; - s.send(()); + s.send(()).unwrap(); } } @@ -476,13 +549,13 @@ mod tests { *f.get() = 2; }); let (tx, rx) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { FOO.with(|f| unsafe { assert_eq!(*f.get(), 1); }); - tx.send(()); + tx.send(()).unwrap(); }); - rx.recv(); + rx.recv().unwrap(); FOO.with(|f| unsafe { assert_eq!(*f.get(), 2); @@ -490,19 +563,42 @@ mod tests { } #[test] + fn states() { + struct Foo; + impl Drop for Foo { + fn drop(&mut self) { + assert!(FOO.state() == State::Destroyed); + } + } + fn foo() -> Foo { + assert!(FOO.state() == State::Uninitialized); + Foo + } + thread_local!(static FOO: Foo = foo()); + + Thread::spawn(|| { + assert!(FOO.state() == State::Uninitialized); + FOO.with(|_| { + assert!(FOO.state() == State::Valid); + }); + assert!(FOO.state() == State::Valid); + }).join().ok().unwrap(); + } + + #[test] fn smoke_dtor() { thread_local!(static FOO: UnsafeCell<Option<Foo>> = UnsafeCell { value: None }); let (tx, rx) = channel(); - spawn(move|| unsafe { + let _t = Thread::spawn(move|| unsafe { let mut tx = Some(tx); FOO.with(|f| { *f.get() = Some(Foo(tx.take().unwrap())); }); }); - rx.recv(); + rx.recv().unwrap(); } #[test] @@ -521,7 +617,7 @@ mod tests { fn drop(&mut self) { unsafe { HITS += 1; - if K2.destroyed() { + if K2.state() == State::Destroyed { assert_eq!(HITS, 3); } else { if HITS == 1 { @@ -537,7 +633,7 @@ mod tests { fn drop(&mut self) { unsafe { HITS += 1; - assert!(!K1.destroyed()); + assert!(K1.state() != State::Destroyed); assert_eq!(HITS, 2); K1.with(|s| *s.get() = Some(S1)); } @@ -546,7 +642,7 @@ mod tests { Thread::spawn(move|| { drop(S1); - }).join(); + }).join().ok().unwrap(); } #[test] @@ -558,13 +654,13 @@ mod tests { impl Drop for S1 { fn drop(&mut self) { - assert!(K1.destroyed()); + assert!(K1.state() == State::Destroyed); } } Thread::spawn(move|| unsafe { K1.with(|s| *s.get() = Some(S1)); - }).join(); + }).join().ok().unwrap(); } #[test] @@ -581,7 +677,7 @@ mod tests { fn drop(&mut self) { let S1(ref tx) = *self; unsafe { - if !K2.destroyed() { + if K2.state() != State::Destroyed { K2.with(|s| *s.get() = Some(Foo(tx.clone()))); } } @@ -589,17 +685,17 @@ mod tests { } let (tx, rx) = channel(); - spawn(move|| unsafe { + let _t = Thread::spawn(move|| unsafe { let mut tx = Some(tx); K1.with(|s| *s.get() = Some(S1(tx.take().unwrap()))); }); - rx.recv(); + rx.recv().unwrap(); } } #[cfg(test)] mod dynamic_tests { - use prelude::*; + use prelude::v1::*; use cell::RefCell; use collections::HashMap; diff --git a/src/libstd/thread_local/scoped.rs b/src/libstd/thread_local/scoped.rs index 5f96548c053..c53d393f1eb 100644 --- a/src/libstd/thread_local/scoped.rs +++ b/src/libstd/thread_local/scoped.rs @@ -39,12 +39,17 @@ //! ``` #![macro_escape] +#![unstable = "scoped TLS has yet to have wide enough use to fully consider \ + stabilizing its interface"] -use prelude::*; +use prelude::v1::*; // macro hygiene sure would be nice, wouldn't it? -#[doc(hidden)] pub use self::imp::KeyInner; -#[doc(hidden)] pub use sys_common::thread_local::INIT as OS_INIT; +#[doc(hidden)] +pub mod __impl { + pub use super::imp::KeyInner; + pub use sys_common::thread_local::INIT as OS_INIT; +} /// Type representing a thread local storage key corresponding to a reference /// to the type parameter `T`. @@ -53,7 +58,7 @@ use prelude::*; /// type `T` scoped to a particular lifetime. Keys provides two methods, `set` /// and `with`, both of which currently use closures to control the scope of /// their contents. -pub struct Key<T> { #[doc(hidden)] pub inner: KeyInner<T> } +pub struct Key<T> { #[doc(hidden)] pub inner: __impl::KeyInner<T> } /// Declare a new scoped thread local storage key. /// @@ -88,21 +93,21 @@ macro_rules! __scoped_thread_local_inner { use std::thread_local::scoped::Key as __Key; #[cfg(not(any(windows, target_os = "android", target_os = "ios")))] - const INIT: __Key<$t> = __Key { - inner: ::std::thread_local::scoped::KeyInner { + const _INIT: __Key<$t> = __Key { + inner: ::std::thread_local::scoped::__impl::KeyInner { inner: ::std::cell::UnsafeCell { value: 0 as *mut _ }, } }; #[cfg(any(windows, target_os = "android", target_os = "ios"))] - const INIT: __Key<$t> = __Key { - inner: ::std::thread_local::scoped::KeyInner { - inner: ::std::thread_local::scoped::OS_INIT, + const _INIT: __Key<$t> = __Key { + inner: ::std::thread_local::scoped::__impl::KeyInner { + inner: ::std::thread_local::scoped::__impl::OS_INIT, marker: ::std::kinds::marker::InvariantType, } }; - INIT + _INIT }) } @@ -139,7 +144,7 @@ impl<T> Key<T> { F: FnOnce() -> R, { struct Reset<'a, T: 'a> { - key: &'a KeyInner<T>, + key: &'a __impl::KeyInner<T>, val: *mut T, } #[unsafe_destructor] @@ -238,7 +243,7 @@ mod imp { #[cfg(test)] mod tests { use cell::Cell; - use prelude::*; + use prelude::v1::*; scoped_thread_local!(static FOO: uint); diff --git a/src/libstd/time/mod.rs b/src/libstd/time/mod.rs index 7bc15798a4f..d6c94f27a8b 100644 --- a/src/libstd/time/mod.rs +++ b/src/libstd/time/mod.rs @@ -45,7 +45,7 @@ fn precise_time_ns() -> u64 { denom: 0 }; static ONCE: sync::Once = sync::ONCE_INIT; unsafe { - ONCE.doit(|| { + ONCE.call_once(|| { imp::mach_timebase_info(&mut TIMEBASE); }); let time = imp::mach_absolute_time(); diff --git a/src/libstd/tuple.rs b/src/libstd/tuple.rs index 5cd60d6e153..fc90bffa03c 100644 --- a/src/libstd/tuple.rs +++ b/src/libstd/tuple.rs @@ -35,14 +35,14 @@ //! //! # Examples //! -//! Using methods: +//! Using fields: //! //! ``` //! #[allow(deprecated)] //! # fn main() { //! let pair = ("pi", 3.14f64); -//! assert_eq!(pair.val0(), "pi"); -//! assert_eq!(pair.val1(), 3.14f64); +//! assert_eq!(pair.0, "pi"); +//! assert_eq!(pair.1, 3.14f64); //! # } //! ``` //! diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 12432c8c78f..a705872b53d 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -643,8 +643,8 @@ pub enum LocalSource { /// Local represents a `let` statement, e.g., `let <pat>:<ty> = <expr>;` #[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct Local { - pub ty: P<Ty>, pub pat: P<Pat>, + pub ty: Option<P<Ty>>, pub init: Option<P<Expr>>, pub id: NodeId, pub span: Span, @@ -1662,6 +1662,7 @@ mod test { use serialize; use codemap::*; use super::*; + use std::fmt; // are ASTs encodable? #[test] @@ -1687,6 +1688,6 @@ mod test { exported_macros: Vec::new(), }; // doesn't matter which encoder we use.... - let _f = &e as &serialize::Encodable<json::Encoder, io::IoError>; + let _f = &e as &serialize::Encodable<json::Encoder, fmt::Error>; } } diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index e61afb8b193..5eac6546c6b 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -10,19 +10,24 @@ // // ignore-lexer-test FIXME #15679 -//! The CodeMap tracks all the source code used within a single crate, mapping from integer byte -//! positions to the original source code location. Each bit of source parsed during crate parsing -//! (typically files, in-memory strings, or various bits of macro expansion) cover a continuous -//! range of bytes in the CodeMap and are represented by FileMaps. Byte positions are stored in -//! `spans` and used pervasively in the compiler. They are absolute positions within the CodeMap, -//! which upon request can be converted to line and column information, source code snippets, etc. +//! The CodeMap tracks all the source code used within a single crate, mapping +//! from integer byte positions to the original source code location. Each bit +//! of source parsed during crate parsing (typically files, in-memory strings, +//! or various bits of macro expansion) cover a continuous range of bytes in the +//! CodeMap and are represented by FileMaps. Byte positions are stored in +//! `spans` and used pervasively in the compiler. They are absolute positions +//! within the CodeMap, which upon request can be converted to line and column +//! information, source code snippets, etc. pub use self::MacroFormat::*; -use serialize::{Encodable, Decodable, Encoder, Decoder}; use std::cell::RefCell; +use std::num::ToPrimitive; +use std::ops::{Add, Sub}; use std::rc::Rc; + use libc::c_uint; +use serialize::{Encodable, Decodable, Encoder, Decoder}; pub trait Pos { fn from_uint(n: uint) -> Self; diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 239af188909..ea345f3a458 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -482,8 +482,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.pat_ident(sp, ident) }; let local = P(ast::Local { - ty: self.ty_infer(sp), pat: pat, + ty: None, init: Some(ex), id: ast::DUMMY_NODE_ID, span: sp, @@ -506,8 +506,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.pat_ident(sp, ident) }; let local = P(ast::Local { - ty: typ, pat: pat, + ty: Some(typ), init: Some(ex), id: ast::DUMMY_NODE_ID, span: sp, diff --git a/src/libsyntax/ext/bytes.rs b/src/libsyntax/ext/bytes.rs index 2844c0b523e..9f225d55b44 100644 --- a/src/libsyntax/ext/bytes.rs +++ b/src/libsyntax/ext/bytes.rs @@ -17,7 +17,6 @@ use ext::base; use ext::build::AstBuilder; use std::ascii::AsciiExt; - pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 5de7068563d..dcf25a26e2c 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -712,7 +712,7 @@ fn expand_non_macro_stmt(Spanned {node, span: stmt_span}: Stmt, fld: &mut MacroE let rewritten_local = local.map(|Local {id, pat, ty, init, source, span}| { // expand the ty since TyFixedLengthVec contains an Expr // and thus may have a macro use - let expanded_ty = fld.fold_ty(ty); + let expanded_ty = ty.map(|t| fld.fold_ty(t)); // expand the pat (it might contain macro uses): let expanded_pat = fld.fold_pat(pat); // find the PatIdents in the pattern: diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index d87960ebdb8..e46bd7ac4bc 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -50,8 +50,7 @@ pub mod rt { impl<T: ToTokens> ToTokens for Vec<T> { fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> { - let a = self.iter().flat_map(|t| t.to_tokens(cx).into_iter()); - FromIterator::from_iter(a) + self.iter().flat_map(|t| t.to_tokens(cx).into_iter()).collect() } } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index b2c2d7eb626..545856a27af 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -56,6 +56,7 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[ ("simd", Active), ("default_type_params", Active), ("quote", Active), + ("link_llvm_intrinsics", Active), ("linkage", Active), ("struct_inherit", Removed), @@ -77,8 +78,11 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[ // to bootstrap fix for #5723. ("issue_5723_bootstrap", Accepted), - // A way to temporary opt out of opt in copy. This will *never* be accepted. - ("opt_out_copy", Active), + // A way to temporarily opt out of opt in copy. This will *never* be accepted. + ("opt_out_copy", Deprecated), + + // A way to temporarily opt out of the new orphan rules. This will *never* be accepted. + ("old_orphan_check", Deprecated), // These are used to test this portion of the compiler, they don't actually // mean anything @@ -91,6 +95,10 @@ enum Status { /// currently being considered for addition/removal. Active, + /// Represents a feature gate that is temporarily enabling deprecated behavior. + /// This gate will never be accepted. + Deprecated, + /// Represents a feature which has since been removed (it was once Active) Removed, @@ -108,6 +116,7 @@ pub struct Features { pub visible_private_types: bool, pub quote: bool, pub opt_out_copy: bool, + pub old_orphan_check: bool, } impl Features { @@ -120,6 +129,7 @@ impl Features { visible_private_types: false, quote: false, opt_out_copy: false, + old_orphan_check: false, } } } @@ -327,6 +337,16 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { "the `linkage` attribute is experimental \ and not portable across platforms") } + + let links_to_llvm = match attr::first_attr_value_str_by_name(i.attrs[], "link_name") { + Some(val) => val.get().starts_with("llvm."), + _ => false + }; + if links_to_llvm { + self.gate_feature("link_llvm_intrinsics", i.span, + "linking to LLVM intrinsics is experimental"); + } + visit::walk_foreign_item(self, i) } @@ -442,7 +462,16 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::C }; match KNOWN_FEATURES.iter() .find(|& &(n, _)| name == n) { - Some(&(name, Active)) => { cx.features.push(name); } + Some(&(name, Active)) => { + cx.features.push(name); + } + Some(&(name, Deprecated)) => { + cx.features.push(name); + span_handler.span_warn( + mi.span, + "feature is deprecated and will only be available \ + for a limited time, please rewrite code that relies on it"); + } Some(&(_, Removed)) => { span_handler.span_err(mi.span, "feature has been removed"); } @@ -469,6 +498,7 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::C visible_private_types: cx.has_feature("visible_private_types"), quote: cx.has_feature("quote"), opt_out_copy: cx.has_feature("opt_out_copy"), + old_orphan_check: cx.has_feature("old_orphan_check"), }, unknown_features) } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 4f0169e31f2..3d3068f6868 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -53,7 +53,7 @@ impl<T> MoveMap<T> for OwnedSlice<T> { } } -pub trait Folder { +pub trait Folder : Sized { // Any additions to this trait should happen in form // of a call to a public `noop_*` function that only calls // out to the folder again, not other `noop_*` functions. @@ -553,7 +553,7 @@ pub fn noop_fold_parenthesized_parameter_data<T: Folder>(data: ParenthesizedPara pub fn noop_fold_local<T: Folder>(l: P<Local>, fld: &mut T) -> P<Local> { l.map(|Local {id, pat, ty, init, source, span}| Local { id: fld.new_id(id), - ty: fld.fold_ty(ty), + ty: ty.map(|t| fld.fold_ty(t)), pat: fld.fold_pat(pat), init: init.map(|e| fld.fold_expr(e)), source: source, diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index d5093c5055c..18cdb3fc647 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -26,6 +26,8 @@ #![feature(macro_rules, globs, default_type_params, phase, slicing_syntax)] #![feature(quote, unsafe_destructor)] #![feature(unboxed_closures)] +#![feature(old_orphan_check)] +#![feature(associated_types)] extern crate arena; extern crate fmt_macros; diff --git a/src/libsyntax/owned_slice.rs b/src/libsyntax/owned_slice.rs index 3023c547fb0..bc2e0923115 100644 --- a/src/libsyntax/owned_slice.rs +++ b/src/libsyntax/owned_slice.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::fmt; use std::default::Default; +use std::fmt; +use std::iter::FromIterator; +use std::ops::Deref; use std::vec; use serialize::{Encodable, Decodable, Encoder, Decoder}; @@ -54,7 +56,9 @@ impl<T> OwnedSlice<T> { } } -impl<T> Deref<[T]> for OwnedSlice<T> { +impl<T> Deref for OwnedSlice<T> { + type Target = [T]; + fn deref(&self) -> &[T] { self.as_slice() } diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 13d020f6ae3..0f5ff33021c 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -16,6 +16,7 @@ use ext::tt::transcribe::tt_next_token; use parse::token; use parse::token::{str_to_ident}; +use std::borrow::IntoCow; use std::char; use std::fmt; use std::mem::replace; @@ -358,7 +359,7 @@ impl<'a> StringReader<'a> { pub fn nextnextch(&self) -> Option<char> { let offset = self.byte_offset(self.pos).to_uint(); - let s = self.filemap.deref().src[]; + let s = self.filemap.src.as_slice(); if offset >= s.len() { return None } let str::CharRange { next, .. } = s.char_range_at(offset); if next < s.len() { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index f84ddcf360e..c597968d4ae 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -84,11 +84,12 @@ use owned_slice::OwnedSlice; use std::collections::HashSet; use std::io::fs::PathExtensions; +use std::iter; use std::mem; use std::num::Float; use std::rc::Rc; -use std::iter; use std::slice; +use std::str::from_str; bitflags! { flags Restrictions: u8 { @@ -3631,13 +3632,9 @@ impl<'a> Parser<'a> { let lo = self.span.lo; let pat = self.parse_pat(); - let mut ty = P(Ty { - id: ast::DUMMY_NODE_ID, - node: TyInfer, - span: mk_sp(lo, lo), - }); + let mut ty = None; if self.eat(&token::Colon) { - ty = self.parse_ty_sum(); + ty = Some(self.parse_ty_sum()); } let init = self.parse_initializer(); P(ast::Local { diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index f22a4b5c6ed..2745b7e13e9 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -22,8 +22,10 @@ use util::interner::{RcStr, StrInterner}; use util::interner; use serialize::{Decodable, Decoder, Encodable, Encoder}; +use std::cmp::Equiv; use std::fmt; use std::mem; +use std::ops::Deref; use std::path::BytesContainer; use std::rc::Rc; @@ -606,7 +608,9 @@ impl InternedString { } } -impl Deref<str> for InternedString { +impl Deref for InternedString { + type Target = str; + fn deref(&self) -> &str { &*self.string } } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 877b2c7b7d3..64eb4192bf0 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1858,13 +1858,11 @@ impl<'a> State<'a> { pub fn print_local_decl(&mut self, loc: &ast::Local) -> IoResult<()> { try!(self.print_pat(&*loc.pat)); - match loc.ty.node { - ast::TyInfer => Ok(()), - _ => { - try!(self.word_space(":")); - self.print_type(&*loc.ty) - } + if let Some(ref ty) = loc.ty { + try!(self.word_space(":")); + try!(self.print_type(&**ty)); } + Ok(()) } pub fn print_decl(&mut self, decl: &ast::Decl) -> IoResult<()> { diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs index 1b3ebde2461..a989b323723 100644 --- a/src/libsyntax/ptr.rs +++ b/src/libsyntax/ptr.rs @@ -10,16 +10,18 @@ //! The AST pointer //! -//! Provides `P<T>`, a frozen owned smart pointer, as a replacement for `@T` in the AST. +//! Provides `P<T>`, a frozen owned smart pointer, as a replacement for `@T` in +//! the AST. //! //! # Motivations and benefits //! -//! * **Identity**: sharing AST nodes is problematic for the various analysis passes -//! (e.g. one may be able to bypass the borrow checker with a shared `ExprAddrOf` -//! node taking a mutable borrow). The only reason `@T` in the AST hasn't caused -//! issues is because of inefficient folding passes which would always deduplicate -//! any such shared nodes. Even if the AST were to switch to an arena, this would -//! still hold, i.e. it couldn't use `&'a T`, but rather a wrapper like `P<'a, T>`. +//! * **Identity**: sharing AST nodes is problematic for the various analysis +//! passes (e.g. one may be able to bypass the borrow checker with a shared +//! `ExprAddrOf` node taking a mutable borrow). The only reason `@T` in the +//! AST hasn't caused issues is because of inefficient folding passes which +//! would always deduplicate any such shared nodes. Even if the AST were to +//! switch to an arena, this would still hold, i.e. it couldn't use `&'a T`, +//! but rather a wrapper like `P<'a, T>`. //! //! * **Immutability**: `P<T>` disallows mutating its inner `T`, unlike `Box<T>` //! (unless it contains an `Unsafe` interior, but that may be denied later). @@ -34,9 +36,9 @@ //! implementation changes (using a special thread-local heap, for example). //! Moreover, a switch to, e.g. `P<'a, T>` would be easy and mostly automated. -use std::fmt; -use std::fmt::Show; +use std::fmt::{mod, Show}; use std::hash::Hash; +use std::ops::Deref; use std::ptr; use serialize::{Encodable, Decodable, Encoder, Decoder}; @@ -75,7 +77,9 @@ impl<T: 'static> P<T> { } } -impl<T> Deref<T> for P<T> { +impl<T> Deref for P<T> { + type Target = T; + fn deref<'a>(&'a self) -> &'a T { &*self.ptr } diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index c1823231e24..5a4d0cc3bd8 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -152,7 +152,7 @@ impl<'a> fold::Folder for PreludeInjector<'a> { let prelude_path = ast::Path { span: DUMMY_SP, global: false, - segments: vec!( + segments: vec![ ast::PathSegment { identifier: token::str_to_ident("std"), parameters: ast::PathParameters::none(), @@ -160,7 +160,12 @@ impl<'a> fold::Folder for PreludeInjector<'a> { ast::PathSegment { identifier: token::str_to_ident("prelude"), parameters: ast::PathParameters::none(), - }), + }, + ast::PathSegment { + identifier: token::str_to_ident("v1"), + parameters: ast::PathParameters::none(), + }, + ], }; let (crates, uses): (Vec<_>, _) = view_items.iter().cloned().partition(|x| { diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index 97eb4316583..6e087778de9 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -15,10 +15,12 @@ use ast::Name; use std::borrow::BorrowFrom; -use std::collections::HashMap; use std::cell::RefCell; +use std::cmp::Ordering; +use std::collections::HashMap; use std::fmt; use std::hash::Hash; +use std::ops::Deref; use std::rc::Rc; pub struct Interner<T> { @@ -124,7 +126,9 @@ impl BorrowFrom<RcStr> for str { } } -impl Deref<str> for RcStr { +impl Deref for RcStr { + type Target = str; + fn deref(&self) -> &str { self.string[] } } diff --git a/src/libsyntax/util/small_vector.rs b/src/libsyntax/util/small_vector.rs index 946181770c8..953a7ae960e 100644 --- a/src/libsyntax/util/small_vector.rs +++ b/src/libsyntax/util/small_vector.rs @@ -7,9 +7,11 @@ // <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. + use self::SmallVectorRepr::*; use self::IntoIterRepr::*; +use std::iter::FromIterator; use std::mem; use std::slice; use std::vec; diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 40ca6354ca6..a1fe63e3f6f 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -54,8 +54,7 @@ pub enum FnKind<'a> { /// explicitly, you need to override each method. (And you also need /// to monitor future changes to `Visitor` in case a new method with a /// new default implementation gets introduced.) -pub trait Visitor<'v> { - +pub trait Visitor<'v> : Sized { fn visit_name(&mut self, _span: Span, _name: Name) { // Nothing to do. } @@ -211,7 +210,7 @@ pub fn walk_view_item<'v, V: Visitor<'v>>(visitor: &mut V, vi: &'v ViewItem) { pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) { visitor.visit_pat(&*local.pat); - visitor.visit_ty(&*local.ty); + walk_ty_opt(visitor, &local.ty); walk_expr_opt(visitor, &local.init); } @@ -381,6 +380,13 @@ pub fn skip_ty<'v, V: Visitor<'v>>(_: &mut V, _: &'v Ty) { // Empty! } +pub fn walk_ty_opt<'v, V: Visitor<'v>>(visitor: &mut V, optional_type: &'v Option<P<Ty>>) { + match *optional_type { + Some(ref ty) => visitor.visit_ty(&**ty), + None => () + } +} + pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { match typ.node { TyVec(ref ty) | TyParen(ref ty) => { @@ -583,10 +589,7 @@ pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, pub fn walk_ty_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v TyParam) { visitor.visit_ident(param.span, param.ident); walk_ty_param_bounds_helper(visitor, ¶m.bounds); - match param.default { - Some(ref ty) => visitor.visit_ty(&**ty), - None => {} - } + walk_ty_opt(visitor, ¶m.default); } pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) { diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 19821ecb7ca..b2d3611fc64 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -31,8 +31,10 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/nightly/")] +#![allow(unknown_features)] #![feature(asm, macro_rules, phase, globs, slicing_syntax)] #![feature(unboxed_closures, default_type_params)] +#![feature(old_orphan_check)] extern crate getopts; extern crate regex; @@ -49,8 +51,6 @@ use self::TestEvent::*; use self::NamePadding::*; use self::OutputLocation::*; -use std::any::{Any, AnyRefExt}; -use std::collections::BTreeMap; use stats::Stats; use getopts::{OptGroup, optflag, optopt}; use regex::Regex; @@ -58,7 +58,9 @@ use serialize::{json, Decodable, Encodable}; use term::Terminal; use term::color::{Color, RED, YELLOW, GREEN, CYAN}; +use std::any::{Any, AnyRefExt}; use std::cmp; +use std::collections::BTreeMap; use std::f64; use std::fmt::Show; use std::fmt; @@ -69,11 +71,11 @@ use std::io; use std::iter::repeat; use std::num::{Float, FloatMath, Int}; use std::os; -use std::str::FromStr; -use std::string::String; +use std::str::{FromStr, from_str}; +use std::sync::mpsc::{channel, Sender}; use std::thread::{mod, Thread}; -use std::time::Duration; use std::thunk::{Thunk, Invoke}; +use std::time::Duration; // to be used by rustc to compile tests in libtest pub mod test { @@ -171,14 +173,14 @@ impl TestFn { impl fmt::Show for TestFn { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write(match *self { + f.write_str(match *self { StaticTestFn(..) => "StaticTestFn(..)", StaticBenchFn(..) => "StaticBenchFn(..)", StaticMetricFn(..) => "StaticMetricFn(..)", DynTestFn(..) => "DynTestFn(..)", DynMetricFn(..) => "DynMetricFn(..)", DynBenchFn(..) => "DynBenchFn(..)" - }.as_bytes()) + }) } } @@ -1021,7 +1023,7 @@ fn run_tests<F>(opts: &TestOpts, pending += 1; } - let (desc, result, stdout) = rx.recv(); + let (desc, result, stdout) = rx.recv().unwrap(); if concurrency != 1 { try!(callback(TeWait(desc.clone(), PadNone))); } @@ -1034,7 +1036,7 @@ fn run_tests<F>(opts: &TestOpts, for b in filtered_benchs_and_metrics.into_iter() { try!(callback(TeWait(b.desc.clone(), b.testfn.padding()))); run_test(opts, !opts.run_benchmarks, b, tx.clone()); - let (test, result, stdout) = rx.recv(); + let (test, result, stdout) = rx.recv().unwrap(); try!(callback(TeResult(test, result, stdout))); } Ok(()) @@ -1111,7 +1113,7 @@ pub fn run_test(opts: &TestOpts, let TestDescAndFn {desc, testfn} = test; if force_ignore || desc.ignore { - monitor_ch.send((desc, TrIgnored, Vec::new())); + monitor_ch.send((desc, TrIgnored, Vec::new())).unwrap(); return; } @@ -1138,31 +1140,31 @@ pub fn run_test(opts: &TestOpts, let result_guard = cfg.spawn(move || { testfn.invoke(()) }); let stdout = reader.read_to_end().unwrap().into_iter().collect(); let test_result = calc_result(&desc, result_guard.join()); - monitor_ch.send((desc.clone(), test_result, stdout)); + monitor_ch.send((desc.clone(), test_result, stdout)).unwrap(); }).detach(); } match testfn { DynBenchFn(bencher) => { let bs = ::bench::benchmark(|harness| bencher.run(harness)); - monitor_ch.send((desc, TrBench(bs), Vec::new())); + monitor_ch.send((desc, TrBench(bs), Vec::new())).unwrap(); return; } StaticBenchFn(benchfn) => { let bs = ::bench::benchmark(|harness| (benchfn.clone())(harness)); - monitor_ch.send((desc, TrBench(bs), Vec::new())); + monitor_ch.send((desc, TrBench(bs), Vec::new())).unwrap(); return; } DynMetricFn(f) => { let mut mm = MetricMap::new(); f.invoke(&mut mm); - monitor_ch.send((desc, TrMetrics(mm), Vec::new())); + monitor_ch.send((desc, TrMetrics(mm), Vec::new())).unwrap(); return; } StaticMetricFn(f) => { let mut mm = MetricMap::new(); f(&mut mm); - monitor_ch.send((desc, TrMetrics(mm), Vec::new())); + monitor_ch.send((desc, TrMetrics(mm), Vec::new())).unwrap(); return; } DynTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture, f), @@ -1212,8 +1214,7 @@ impl MetricMap { pub fn save(&self, p: &Path) -> io::IoResult<()> { let mut file = try!(File::create(p)); let MetricMap(ref map) = *self; - let mut enc = json::PrettyEncoder::new(&mut file); - map.encode(&mut enc) + write!(&mut file, "{}", json::as_json(map)) } /// Compare against another MetricMap. Optionally compare all @@ -1466,6 +1467,7 @@ mod tests { StaticTestName, DynTestName, DynTestFn, ShouldFail}; use std::io::TempDir; use std::thunk::Thunk; + use std::sync::mpsc::channel; #[test] pub fn do_not_run_ignored_tests() { @@ -1480,7 +1482,7 @@ mod tests { }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, tx); - let (_, res, _) = rx.recv(); + let (_, res, _) = rx.recv().unwrap(); assert!(res != TrOk); } @@ -1497,7 +1499,7 @@ mod tests { }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, tx); - let (_, res, _) = rx.recv(); + let (_, res, _) = rx.recv().unwrap(); assert!(res == TrIgnored); } @@ -1514,7 +1516,7 @@ mod tests { }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, tx); - let (_, res, _) = rx.recv(); + let (_, res, _) = rx.recv().unwrap(); assert!(res == TrOk); } @@ -1531,7 +1533,7 @@ mod tests { }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, tx); - let (_, res, _) = rx.recv(); + let (_, res, _) = rx.recv().unwrap(); assert!(res == TrOk); } @@ -1548,7 +1550,7 @@ mod tests { }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, tx); - let (_, res, _) = rx.recv(); + let (_, res, _) = rx.recv().unwrap(); assert!(res == TrFailed); } @@ -1565,7 +1567,7 @@ mod tests { }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, tx); - let (_, res, _) = rx.recv(); + let (_, res, _) = rx.recv().unwrap(); assert!(res == TrFailed); } diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs index 41146cded70..ed6a00a8e91 100644 --- a/src/libtest/stats.rs +++ b/src/libtest/stats.rs @@ -10,13 +10,14 @@ #![allow(missing_docs)] -use std::collections::hash_map; +use std::cmp::Ordering::{mod, Less, Greater, Equal}; use std::collections::hash_map::Entry::{Occupied, Vacant}; +use std::collections::hash_map; use std::fmt::Show; use std::hash::Hash; use std::io; use std::mem; -use std::num::{Float, FloatMath}; +use std::num::{Float, FloatMath, FromPrimitive}; fn local_cmp<T:Float>(x: T, y: T) -> Ordering { // arbitrarily decide that NaNs are larger than everything. diff --git a/src/libtime/lib.rs b/src/libtime/lib.rs index 87a00334c47..bc5d0c21aae 100644 --- a/src/libtime/lib.rs +++ b/src/libtime/lib.rs @@ -20,7 +20,10 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/nightly/", html_playground_url = "http://play.rust-lang.org/")] + +#![allow(unknown_features)] #![feature(phase, globs)] +#![feature(old_orphan_check)] #[cfg(test)] #[phase(plugin, link)] extern crate log; @@ -30,10 +33,9 @@ extern crate libc; pub use self::ParseError::*; use self::Fmt::*; -use std::fmt::Show; -use std::fmt; +use std::fmt::{mod, Show}; use std::num::SignedInt; -use std::string::String; +use std::ops::{Add, Sub}; use std::time::Duration; static NSEC_PER_SEC: i32 = 1_000_000_000_i32; @@ -198,7 +200,7 @@ pub fn precise_time_ns() -> u64 { denom: 0 }; static ONCE: std::sync::Once = std::sync::ONCE_INIT; unsafe { - ONCE.doit(|| { + ONCE.call_once(|| { imp::mach_timebase_info(&mut TIMEBASE); }); let time = imp::mach_absolute_time(); @@ -1274,6 +1276,7 @@ mod tests { #[cfg(windows)] fn set_time_zone() { use libc; + use std::c_str::ToCStr; // Windows crt doesn't see any environment variable set by // `SetEnvironmentVariable`, which `os::setenv` internally uses. // It is why we use `putenv` here. diff --git a/src/snapshots.txt b/src/snapshots.txt index 6a9bfa07cf7..34beb53bd07 100644 --- a/src/snapshots.txt +++ b/src/snapshots.txt @@ -1,3 +1,12 @@ +S 2015-01-01 7d4f487 + freebsd-x86_64 5dc87adb17bc33abc08f1bf4c092e0b5b92a6ca4 + linux-i386 63bf82a5b540d8acbbf1e445ce48be0fa0f003fc + linux-x86_64 b1a414355ef5d2feff18ab9d008a2e9afc7b4625 + macos-i386 26042e3e648eb40848bf02f3e05ba31fd686179c + macos-x86_64 f01d7c6faf5db480a18a521c6971364f4ce8ddca + winnt-i386 6f04af045d26a0c87d487ba7254d4ad0c166ecaf + winnt-x86_64 392ab49482ec926de6a167afe920518b9a502a3f + S 2014-12-30 023dfb0 freebsd-x86_64 41ecd0ac557c823831c46696c7d78dc250398f25 linux-i386 fe6b59bf70a397e18629cb82264f7c6a70df34d4 diff --git a/src/test/auxiliary/cci_capture_clause.rs b/src/test/auxiliary/cci_capture_clause.rs index 1cccb0f7ccb..ec470ddc213 100644 --- a/src/test/auxiliary/cci_capture_clause.rs +++ b/src/test/auxiliary/cci_capture_clause.rs @@ -9,6 +9,7 @@ // except according to those terms. use std::task; +use std::sync::mpsc::{Receiver, channel}; pub fn foo<T:Send + Clone>(x: T) -> Receiver<T> { let (tx, rx) = channel(); diff --git a/src/test/auxiliary/coherence-lib.rs b/src/test/auxiliary/coherence-lib.rs new file mode 100644 index 00000000000..daa123849e4 --- /dev/null +++ b/src/test/auxiliary/coherence-lib.rs @@ -0,0 +1,25 @@ +// Copyright 2012 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="lib"] + +pub trait Remote { + fn foo(&self) { } +} + +pub trait Remote1<T> { + fn foo(&self, t: T) { } +} + +pub trait Remote2<T, U> { + fn foo(&self, t: T, u: U) { } +} + +pub struct Pair<T,U>(T,U); diff --git a/src/test/auxiliary/issue-17718.rs b/src/test/auxiliary/issue-17718.rs index f0b431b1db9..689610d799e 100644 --- a/src/test/auxiliary/issue-17718.rs +++ b/src/test/auxiliary/issue-17718.rs @@ -11,12 +11,12 @@ use std::sync::atomic; pub const C1: uint = 1; -pub const C2: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT; +pub const C2: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT; pub const C3: fn() = foo; pub const C4: uint = C1 * C1 + C1 / C1; pub const C5: &'static uint = &C4; pub static S1: uint = 3; -pub static S2: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT; +pub static S2: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT; fn foo() {} diff --git a/src/test/bench/spawnone.rs b/src/test/auxiliary/issue_20389.rs index ca36d99014c..60e3cb13e2e 100644 --- a/src/test/bench/spawnone.rs +++ b/src/test/auxiliary/issue_20389.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Useful for checking syscall usage of baseline scheduler usage -fn main() { - spawn(move|| {}); +#![feature(associated_types)] + +pub trait T { + type C; } diff --git a/src/test/auxiliary/method_self_arg2.rs b/src/test/auxiliary/method_self_arg2.rs index e1e79b59e3e..eb4d62b01ad 100644 --- a/src/test/auxiliary/method_self_arg2.rs +++ b/src/test/auxiliary/method_self_arg2.rs @@ -32,7 +32,7 @@ impl Foo { } } -pub trait Bar { +pub trait Bar : Sized { fn foo1(&self); fn foo2(self); fn foo3(self: Box<Self>); diff --git a/src/test/auxiliary/overloaded_autoderef_xc.rs b/src/test/auxiliary/overloaded_autoderef_xc.rs index 26d61e166f2..05960a5b8e1 100644 --- a/src/test/auxiliary/overloaded_autoderef_xc.rs +++ b/src/test/auxiliary/overloaded_autoderef_xc.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(associated_types)] + use std::ops::Deref; struct DerefWithHelper<H, T> { @@ -24,7 +26,9 @@ impl<T> Helper<T> for Option<T> { } } -impl<T, H: Helper<T>> Deref<T> for DerefWithHelper<H, T> { +impl<T, H: Helper<T>> Deref for DerefWithHelper<H, T> { + type Target = T; + fn deref(&self) -> &T { self.helper.helper_borrow() } diff --git a/src/test/auxiliary/static-methods-crate.rs b/src/test/auxiliary/static-methods-crate.rs index 811d8f11692..ea4751bf4ed 100644 --- a/src/test/auxiliary/static-methods-crate.rs +++ b/src/test/auxiliary/static-methods-crate.rs @@ -12,6 +12,7 @@ #![crate_type = "lib"] use std::int; +use std::str::from_str; pub trait read { fn readMaybe(s: String) -> Option<Self>; diff --git a/src/test/auxiliary/trait_inheritance_overloading_xc.rs b/src/test/auxiliary/trait_inheritance_overloading_xc.rs index 0e90db2835f..7ddf2c43489 100644 --- a/src/test/auxiliary/trait_inheritance_overloading_xc.rs +++ b/src/test/auxiliary/trait_inheritance_overloading_xc.rs @@ -9,6 +9,7 @@ // except according to those terms. use std::cmp::PartialEq; +use std::ops::{Add, Sub, Mul}; pub trait MyNum : Add<Self,Self> + Sub<Self,Self> + Mul<Self,Self> + PartialEq + Clone { } diff --git a/src/test/auxiliary/traitimpl.rs b/src/test/auxiliary/traitimpl.rs new file mode 100644 index 00000000000..fd454509b39 --- /dev/null +++ b/src/test/auxiliary/traitimpl.rs @@ -0,0 +1,17 @@ +// Copyright 2014 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. + +// Test inherant trait impls work cross-crait. + +pub trait Bar<'a> for ?Sized : 'a {} + +impl<'a> Bar<'a> { + pub fn bar(&self) {} +} diff --git a/src/test/auxiliary/unboxed-closures-cross-crate.rs b/src/test/auxiliary/unboxed-closures-cross-crate.rs index 9a6a2c7495b..0b65fa913cb 100644 --- a/src/test/auxiliary/unboxed-closures-cross-crate.rs +++ b/src/test/auxiliary/unboxed-closures-cross-crate.rs @@ -10,6 +10,8 @@ #![feature(unboxed_closures)] +use std::ops::Add; + #[inline] pub fn has_closures() -> uint { let x = 1u; diff --git a/src/test/bench/core-map.rs b/src/test/bench/core-map.rs index 60331dfb550..0ada1cb991c 100644 --- a/src/test/bench/core-map.rs +++ b/src/test/bench/core-map.rs @@ -13,6 +13,7 @@ use std::collections::{BTreeMap, HashMap, HashSet}; use std::os; use std::rand::{Rng, IsaacRng, SeedableRng}; +use std::str::from_str; use std::time::Duration; use std::uint; diff --git a/src/test/bench/core-set.rs b/src/test/bench/core-set.rs index 49f5c7751d9..52380001c6c 100644 --- a/src/test/bench/core-set.rs +++ b/src/test/bench/core-set.rs @@ -15,11 +15,12 @@ extern crate collections; extern crate rand; +use std::collections::BTreeSet; use std::collections::BitvSet; use std::collections::HashSet; -use std::collections::BTreeSet; use std::hash::Hash; use std::os; +use std::str::from_str; use std::time::Duration; use std::uint; diff --git a/src/test/bench/core-uint-to-str.rs b/src/test/bench/core-uint-to-str.rs index 98113cb8347..08637b4bf1c 100644 --- a/src/test/bench/core-uint-to-str.rs +++ b/src/test/bench/core-uint-to-str.rs @@ -9,6 +9,7 @@ // except according to those terms. use std::os; +use std::str::from_str; use std::uint; fn main() { diff --git a/src/test/bench/msgsend-pipes-shared.rs b/src/test/bench/msgsend-pipes-shared.rs index 645c029f935..285d193e7da 100644 --- a/src/test/bench/msgsend-pipes-shared.rs +++ b/src/test/bench/msgsend-pipes-shared.rs @@ -18,8 +18,9 @@ // different scalability characteristics compared to the select // version. -use std::comm; +use std::sync::mpsc::{channel, Sender, Receiver}; use std::os; +use std::str::from_str; use std::thread::Thread; use std::time::Duration; use std::uint; @@ -36,8 +37,8 @@ fn server(requests: &Receiver<request>, responses: &Sender<uint>) { let mut count = 0u; let mut done = false; while !done { - match requests.recv_opt() { - Ok(request::get_count) => { responses.send(count.clone()); } + match requests.recv() { + Ok(request::get_count) => { responses.send(count.clone()).unwrap(); } Ok(request::bytes(b)) => { //println!("server: received {} bytes", b); count += b; @@ -46,7 +47,7 @@ fn server(requests: &Receiver<request>, responses: &Sender<uint>) { _ => { } } } - responses.send(count); + responses.send(count).unwrap(); //println!("server exiting"); } @@ -67,7 +68,7 @@ fn run(args: &[String]) { worker_results.push(Thread::spawn(move|| { for _ in range(0u, size / workers) { //println!("worker {}: sending {} bytes", i, num_bytes); - to_child.send(request::bytes(num_bytes)); + to_child.send(request::bytes(num_bytes)).unwrap(); } //println!("worker {} exiting", i); })); @@ -81,9 +82,9 @@ fn run(args: &[String]) { } //println!("sending stop message"); - to_child.send(request::stop); + to_child.send(request::stop).unwrap(); move_out(to_child); - result = Some(from_child.recv()); + result = Some(from_child.recv().unwrap()); }); let result = result.unwrap(); print!("Count is {}\n", result); diff --git a/src/test/bench/msgsend-pipes.rs b/src/test/bench/msgsend-pipes.rs index ed96c6406d8..ef22aac776e 100644 --- a/src/test/bench/msgsend-pipes.rs +++ b/src/test/bench/msgsend-pipes.rs @@ -14,6 +14,7 @@ // // I *think* it's the same, more or less. +use std::sync::mpsc::{channel, Sender, Receiver}; use std::os; use std::thread::Thread; use std::time::Duration; @@ -31,7 +32,7 @@ fn server(requests: &Receiver<request>, responses: &Sender<uint>) { let mut count: uint = 0; let mut done = false; while !done { - match requests.recv_opt() { + match requests.recv() { Ok(request::get_count) => { responses.send(count.clone()); } Ok(request::bytes(b)) => { //println!("server: received {} bytes", b); @@ -48,8 +49,8 @@ fn server(requests: &Receiver<request>, responses: &Sender<uint>) { fn run(args: &[String]) { let (to_parent, from_child) = channel(); - let size = from_str::<uint>(args[1].as_slice()).unwrap(); - let workers = from_str::<uint>(args[2].as_slice()).unwrap(); + let size = args[1].parse::<uint>().unwrap(); + let workers = args[2].parse::<uint>().unwrap(); let num_bytes = 100; let mut result = None; let mut to_parent = Some(to_parent); @@ -91,7 +92,7 @@ fn run(args: &[String]) { //println!("sending stop message"); //to_child.send(stop); //move_out(to_child); - result = Some(from_child.recv()); + result = Some(from_child.recv().unwrap()); }); let result = result.unwrap(); print!("Count is {}\n", result); diff --git a/src/test/bench/msgsend-ring-mutex-arcs.rs b/src/test/bench/msgsend-ring-mutex-arcs.rs index 8ec44b2dd3c..3ead5ef64fd 100644 --- a/src/test/bench/msgsend-ring-mutex-arcs.rs +++ b/src/test/bench/msgsend-ring-mutex-arcs.rs @@ -19,6 +19,7 @@ // ignore-lexer-test FIXME #15679 use std::os; +use std::str::from_str; use std::sync::{Arc, Future, Mutex, Condvar}; use std::time::Duration; use std::uint; diff --git a/src/test/bench/rt-messaging-ping-pong.rs b/src/test/bench/rt-messaging-ping-pong.rs index 73d54372b27..de9e6629fbf 100644 --- a/src/test/bench/rt-messaging-ping-pong.rs +++ b/src/test/bench/rt-messaging-ping-pong.rs @@ -17,7 +17,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::sync::mpsc::channel; use std::os; +use std::str::from_str; +use std::thread::Thread; use std::uint; // This is a simple bench that creates M pairs of tasks. These @@ -34,21 +37,21 @@ fn ping_pong_bench(n: uint, m: uint) { // Create a stream B->A let (btx, brx) = channel::<()>(); - spawn(move|| { + Thread::spawn(move|| { let (tx, rx) = (atx, brx); for _ in range(0, n) { tx.send(()); rx.recv(); } - }); + }).detach(); - spawn(move|| { + Thread::spawn(move|| { let (tx, rx) = (btx, arx); for _ in range(0, n) { rx.recv(); tx.send(()); } - }); + }).detach(); } for _ in range(0, m) { diff --git a/src/test/bench/rt-parfib.rs b/src/test/bench/rt-parfib.rs index bdf22cd7395..8b212555d40 100644 --- a/src/test/bench/rt-parfib.rs +++ b/src/test/bench/rt-parfib.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::sync::mpsc::channel; use std::os; +use std::thread::Thread; use std::uint; // A simple implementation of parfib. One subtree is found in a new @@ -21,11 +23,11 @@ fn parfib(n: uint) -> uint { } let (tx, rx) = channel(); - spawn(move|| { + Thread::spawn(move|| { tx.send(parfib(n-1)); - }); + }).detach(); let m2 = parfib(n-2); - return (rx.recv() + m2); + return (rx.recv().unwrap() + m2); } fn main() { @@ -33,7 +35,7 @@ fn main() { let args = os::args(); let args = args.as_slice(); let n = if args.len() == 2 { - from_str::<uint>(args[1].as_slice()).unwrap() + args[1].parse::<uint>().unwrap() } else { 10 }; diff --git a/src/test/bench/shootout-ackermann.rs b/src/test/bench/shootout-ackermann.rs index e7a50382c94..f7810d5d740 100644 --- a/src/test/bench/shootout-ackermann.rs +++ b/src/test/bench/shootout-ackermann.rs @@ -9,6 +9,7 @@ // except according to those terms. use std::os; +use std::str::from_str; fn ack(m: int, n: int) -> int { if m == 0 { diff --git a/src/test/bench/shootout-binarytrees.rs b/src/test/bench/shootout-binarytrees.rs index 0b16e8011e8..c7a43d61a9a 100644 --- a/src/test/bench/shootout-binarytrees.rs +++ b/src/test/bench/shootout-binarytrees.rs @@ -41,7 +41,7 @@ extern crate arena; use std::iter::range_step; -use std::sync::Future; +use std::thread::Thread; use arena::TypedArena; enum Tree<'a> { @@ -75,7 +75,7 @@ fn main() { } else if args.len() <= 1u { 8 } else { - from_str(args[1].as_slice()).unwrap() + args[1].parse().unwrap() }; let min_depth = 4; let max_depth = if min_depth + 2 > n {min_depth + 2} else {n}; @@ -95,7 +95,7 @@ fn main() { let mut messages = range_step(min_depth, max_depth + 1, 2).map(|depth| { use std::num::Int; let iterations = 2i.pow((max_depth - depth + min_depth) as uint); - Future::spawn(move|| { + Thread::spawn(move|| { let mut chk = 0; for i in range(1, iterations + 1) { let arena = TypedArena::new(); @@ -106,10 +106,10 @@ fn main() { format!("{}\t trees of depth {}\t check: {}", iterations * 2, depth, chk) }) - }).collect::<Vec<Future<String>>>(); + }).collect::<Vec<_>>(); - for message in messages.iter_mut() { - println!("{}", *message.get_ref()); + for message in messages.into_iter() { + println!("{}", message.join().ok().unwrap()); } println!("long lived tree of depth {}\t check: {}", diff --git a/src/test/bench/shootout-chameneos-redux.rs b/src/test/bench/shootout-chameneos-redux.rs index dcdb90a11c8..030c627b6f7 100644 --- a/src/test/bench/shootout-chameneos-redux.rs +++ b/src/test/bench/shootout-chameneos-redux.rs @@ -41,8 +41,10 @@ // no-pretty-expanded use self::Color::{Red, Yellow, Blue}; -use std::string::String; +use std::sync::mpsc::{channel, Sender, Receiver}; use std::fmt; +use std::str::from_str; +use std::thread::Thread; fn print_complements() { let all = [Blue, Red, Yellow]; @@ -152,7 +154,7 @@ fn creature( loop { // ask for a pairing - to_rendezvous.send(CreatureInfo {name: name, color: color}); + to_rendezvous.send(CreatureInfo {name: name, color: color}).unwrap(); // log and change, or quit match rendezvous.next() { @@ -170,7 +172,7 @@ fn creature( } // log creatures met and evil clones of self let report = format!("{}{}", creatures_met, Number(evil_clones_met)); - to_rendezvous_log.send(report); + to_rendezvous_log.send(report).unwrap(); } fn rendezvous(nn: uint, set: Vec<Color>) { @@ -188,13 +190,13 @@ fn rendezvous(nn: uint, set: Vec<Color>) { let to_rendezvous = to_rendezvous.clone(); let to_rendezvous_log = to_rendezvous_log.clone(); let (to_creature, from_rendezvous) = channel(); - spawn(move|| { + Thread::spawn(move|| { creature(ii, col, from_rendezvous, to_rendezvous, to_rendezvous_log); - }); + }).detach(); to_creature }).collect(); @@ -202,13 +204,13 @@ fn rendezvous(nn: uint, set: Vec<Color>) { // set up meetings... for _ in range(0, nn) { - let fst_creature = from_creatures.recv(); - let snd_creature = from_creatures.recv(); + let fst_creature = from_creatures.recv().unwrap(); + let snd_creature = from_creatures.recv().unwrap(); creatures_met += 2; - to_creature[fst_creature.name].send(snd_creature); - to_creature[snd_creature.name].send(fst_creature); + to_creature[fst_creature.name].send(snd_creature).unwrap(); + to_creature[snd_creature.name].send(fst_creature).unwrap(); } // tell each creature to stop diff --git a/src/test/bench/shootout-fannkuch-redux.rs b/src/test/bench/shootout-fannkuch-redux.rs index ef38f5ef743..7dca2b24fc1 100644 --- a/src/test/bench/shootout-fannkuch-redux.rs +++ b/src/test/bench/shootout-fannkuch-redux.rs @@ -41,7 +41,7 @@ #![feature(slicing_syntax)] use std::{cmp, iter, mem}; -use std::sync::Future; +use std::thread::Thread; fn rotate(x: &mut [i32]) { let mut prev = x[0]; @@ -168,15 +168,15 @@ fn fannkuch(n: i32) -> (i32, i32) { for (i, j) in range(0, N).zip(iter::count(0, k)) { let max = cmp::min(j+k, perm.max()); - futures.push(Future::spawn(move|| { + futures.push(Thread::spawn(move|| { work(perm, j as uint, max as uint) })) } let mut checksum = 0; let mut maxflips = 0; - for fut in futures.iter_mut() { - let (cs, mf) = fut.get(); + for fut in futures.into_iter() { + let (cs, mf) = fut.join().ok().unwrap(); checksum += cs; maxflips = cmp::max(maxflips, mf); } @@ -186,7 +186,7 @@ fn fannkuch(n: i32) -> (i32, i32) { fn main() { let n = std::os::args().as_slice() .get(1) - .and_then(|arg| from_str(arg.as_slice())) + .and_then(|arg| arg.parse()) .unwrap_or(2i32); let (checksum, maxflips) = fannkuch(n); diff --git a/src/test/bench/shootout-fasta-redux.rs b/src/test/bench/shootout-fasta-redux.rs index 178d6777939..09f7f236f19 100644 --- a/src/test/bench/shootout-fasta-redux.rs +++ b/src/test/bench/shootout-fasta-redux.rs @@ -44,6 +44,7 @@ use std::cmp::min; use std::io::{stdout, IoResult}; use std::os; use std::slice::bytes::copy_memory; +use std::str::from_str; const LINE_LEN: uint = 60; const LOOKUP_SIZE: uint = 4 * 1024; diff --git a/src/test/bench/shootout-fasta.rs b/src/test/bench/shootout-fasta.rs index 2de61cf3572..7009dd4c1a7 100644 --- a/src/test/bench/shootout-fasta.rs +++ b/src/test/bench/shootout-fasta.rs @@ -40,11 +40,12 @@ #![feature(slicing_syntax)] -use std::io; -use std::io::{BufferedWriter, File}; use std::cmp::min; +use std::io::{BufferedWriter, File}; +use std::io; use std::num::Float; use std::os; +use std::str::from_str; const LINE_LENGTH: uint = 60; const IM: u32 = 139968; diff --git a/src/test/bench/shootout-fibo.rs b/src/test/bench/shootout-fibo.rs index 10c0d0a8044..cbacf415f6f 100644 --- a/src/test/bench/shootout-fibo.rs +++ b/src/test/bench/shootout-fibo.rs @@ -9,6 +9,7 @@ // except according to those terms. use std::os; +use std::str::from_str; fn fib(n: int) -> int { if n < 2 { diff --git a/src/test/bench/shootout-k-nucleotide-pipes.rs b/src/test/bench/shootout-k-nucleotide-pipes.rs index f49b648e215..d92d30ca844 100644 --- a/src/test/bench/shootout-k-nucleotide-pipes.rs +++ b/src/test/bench/shootout-k-nucleotide-pipes.rs @@ -18,12 +18,15 @@ extern crate collections; use std::ascii::{AsciiExt, OwnedAsciiExt}; +use std::cmp::Ordering::{mod, Less, Greater, Equal}; use std::collections::HashMap; +use std::sync::mpsc::{channel, Sender, Receiver}; use std::mem::replace; use std::num::Float; use std::option; use std::os; -use std::string::String; +use std::string::IntoString; +use std::thread::Thread; fn f64_cmp(x: f64, y: f64) -> Ordering { // arbitrarily decide that NaNs are larger than everything. @@ -117,7 +120,7 @@ fn make_sequence_processor(sz: uint, loop { - line = from_parent.recv(); + line = from_parent.recv().unwrap(); if line == Vec::new() { break; } carry.push_all(line.as_slice()); @@ -167,9 +170,9 @@ fn main() { let (to_child, from_parent) = channel(); - spawn(move|| { + Thread::spawn(move|| { make_sequence_processor(sz, &from_parent, &to_parent_); - }); + }).detach(); to_child }).collect::<Vec<Sender<Vec<u8> >> >(); @@ -219,6 +222,6 @@ fn main() { // now fetch and print result messages for (ii, _sz) in sizes.iter().enumerate() { - println!("{}", from_child[ii].recv()); + println!("{}", from_child[ii].recv().unwrap()); } } diff --git a/src/test/bench/shootout-k-nucleotide.rs b/src/test/bench/shootout-k-nucleotide.rs index 1408cfe6eee..26ef696b616 100644 --- a/src/test/bench/shootout-k-nucleotide.rs +++ b/src/test/bench/shootout-k-nucleotide.rs @@ -43,7 +43,6 @@ #![feature(slicing_syntax)] use std::ascii::OwnedAsciiExt; -use std::string::String; use std::slice; use std::sync::{Arc, Future}; diff --git a/src/test/bench/shootout-mandelbrot.rs b/src/test/bench/shootout-mandelbrot.rs index bb0e09370d8..51ce4cbaa84 100644 --- a/src/test/bench/shootout-mandelbrot.rs +++ b/src/test/bench/shootout-mandelbrot.rs @@ -47,6 +47,7 @@ use std::io; use std::os; use std::simd::f64x2; +use std::str::from_str; use std::sync::{Arc, Future}; const ITER: int = 50; diff --git a/src/test/bench/shootout-meteor.rs b/src/test/bench/shootout-meteor.rs index 9a3b6953062..0c3152d4780 100644 --- a/src/test/bench/shootout-meteor.rs +++ b/src/test/bench/shootout-meteor.rs @@ -40,7 +40,9 @@ // no-pretty-expanded FIXME #15189 +use std::sync::mpsc::channel; use std::sync::Arc; +use std::thread::Thread; // // Utilities. @@ -310,16 +312,16 @@ fn par_search(masks: Vec<Vec<Vec<u64>>>) -> Data { let masks = masks.clone(); let tx = tx.clone(); let m = *m; - spawn(move|| { + Thread::spawn(move|| { let mut data = Data::new(); search(&*masks, m, 1, List::Cons(m, &List::Nil), &mut data); - tx.send(data); - }); + tx.send(data).unwrap(); + }).detach(); } // collecting the results drop(tx); - let mut data = rx.recv(); + let mut data = rx.recv().unwrap(); for d in rx.iter() { data.reduce_from(d); } data } diff --git a/src/test/bench/shootout-nbody.rs b/src/test/bench/shootout-nbody.rs index dab67331120..6a325798f58 100644 --- a/src/test/bench/shootout-nbody.rs +++ b/src/test/bench/shootout-nbody.rs @@ -39,6 +39,7 @@ // OF THE POSSIBILITY OF SUCH DAMAGE. use std::num::Float; +use std::str::from_str; const PI: f64 = 3.141592653589793; const SOLAR_MASS: f64 = 4.0 * PI * PI; diff --git a/src/test/bench/shootout-pfib.rs b/src/test/bench/shootout-pfib.rs index f7e8fc8fe1b..78b5ac00b45 100644 --- a/src/test/bench/shootout-pfib.rs +++ b/src/test/bench/shootout-pfib.rs @@ -20,30 +20,32 @@ extern crate getopts; +use std::sync::mpsc::{channel, Sender}; use std::os; use std::result::Result::{Ok, Err}; +use std::str::from_str; use std::thread::Thread; use std::time::Duration; fn fib(n: int) -> int { fn pfib(tx: &Sender<int>, n: int) { if n == 0 { - tx.send(0); + tx.send(0).unwrap(); } else if n <= 2 { - tx.send(1); + tx.send(1).unwrap(); } else { let (tx1, rx) = channel(); let tx2 = tx1.clone(); Thread::spawn(move|| pfib(&tx2, n - 1)).detach(); let tx2 = tx1.clone(); Thread::spawn(move|| pfib(&tx2, n - 2)).detach(); - tx.send(rx.recv() + rx.recv()); + tx.send(rx.recv().unwrap() + rx.recv().unwrap()); } } let (tx, rx) = channel(); Thread::spawn(move|| pfib(&tx, n) ).detach(); - rx.recv() + rx.recv().unwrap() } struct Config { diff --git a/src/test/bench/shootout-reverse-complement.rs b/src/test/bench/shootout-reverse-complement.rs index 909f8afc34a..d9dfd65d5b3 100644 --- a/src/test/bench/shootout-reverse-complement.rs +++ b/src/test/bench/shootout-reverse-complement.rs @@ -45,9 +45,10 @@ extern crate libc; use std::io::stdio::{stdin_raw, stdout_raw}; +use std::io::{IoResult, EndOfFile}; use std::num::{div_rem}; use std::ptr::{copy_memory, Unique}; -use std::io::{IoResult, EndOfFile}; +use std::thread::Thread; struct Tables { table8: [u8;1 << 8], @@ -229,26 +230,20 @@ unsafe impl<T: 'static> Send for Racy<T> {} fn parallel<'a, I, T, F>(mut iter: I, f: F) where T: 'a+Send + Sync, I: Iterator<&'a mut [T]>, - F: Fn(&'a mut [T]) + Sync { + F: Fn(&mut [T]) + Sync { use std::mem; use std::raw::Repr; - let (tx, rx) = channel(); - for chunk in iter { - let tx = tx.clone(); - + iter.map(|chunk| { // Need to convert `f` and `chunk` to something that can cross the task // boundary. let f = Racy(&f as *const F as *const uint); let raw = Racy(chunk.repr()); - spawn(move|| { + Thread::spawn(move|| { let f = f.0 as *const F; unsafe { (*f)(mem::transmute(raw.0)) } - drop(tx) - }); - } - drop(tx); - for () in rx.iter() {} + }) + }).collect::<Vec<_>>(); } fn main() { diff --git a/src/test/bench/shootout-spectralnorm.rs b/src/test/bench/shootout-spectralnorm.rs index df388fbdde5..a5af1227a16 100644 --- a/src/test/bench/shootout-spectralnorm.rs +++ b/src/test/bench/shootout-spectralnorm.rs @@ -44,11 +44,13 @@ #![feature(unboxed_closures)] use std::iter::AdditiveIterator; +use std::thread::Thread; use std::mem; use std::num::Float; use std::os; use std::raw::Repr; use std::simd::f64x2; +use std::str::from_str; fn main() { let args = os::args(); @@ -80,14 +82,15 @@ fn mult_AtAv(v: &[f64], out: &mut [f64], tmp: &mut [f64]) { } fn mult_Av(v: &[f64], out: &mut [f64]) { - parallel(out, |&: start, out| mult(v, out, start, |i, j| A(i, j))); + parallel(out, |start, out| mult(v, out, start, |i, j| A(i, j))); } fn mult_Atv(v: &[f64], out: &mut [f64]) { - parallel(out, |&: start, out| mult(v, out, start, |i, j| A(j, i))); + parallel(out, |start, out| mult(v, out, start, |i, j| A(j, i))); } -fn mult(v: &[f64], out: &mut [f64], start: uint, a: |uint, uint| -> f64) { +fn mult<F>(v: &[f64], out: &mut [f64], start: uint, a: F) + where F: Fn(uint, uint) -> f64 { for (i, slot) in out.iter_mut().enumerate().map(|(i, s)| (i + start, s)) { let mut sum = f64x2(0.0, 0.0); for (j, chunk) in v.chunks(2).enumerate().map(|(j, s)| (2 * j, s)) { @@ -116,25 +119,19 @@ unsafe impl<T: 'static> Send for Racy<T> {} // Executes a closure in parallel over the given mutable slice. The closure `f` // is run in parallel and yielded the starting index within `v` as well as a // sub-slice of `v`. -fn parallel<'a, T, F>(v: &'a mut [T], f: F) - where T: Send + Sync, - F: Fn(uint, &'a mut [T]) + Sync { - let (tx, rx) = channel(); +fn parallel<T, F>(v: &mut [T], f: F) + where T: Send + Sync, + F: Fn(uint, &mut [T]) + Sync { let size = v.len() / os::num_cpus() + 1; - for (i, chunk) in v.chunks_mut(size).enumerate() { - let tx = tx.clone(); - + v.chunks_mut(size).enumerate().map(|(i, chunk)| { // Need to convert `f` and `chunk` to something that can cross the task // boundary. let f = Racy(&f as *const _ as *const uint); let raw = Racy(chunk.repr()); - spawn(move|| { + Thread::spawn(move|| { let f = f.0 as *const F; unsafe { (*f)(i * size, mem::transmute(raw.0)) } - drop(tx) - }); - } - drop(tx); - for () in rx.iter() {} + }) + }).collect::<Vec<_>>(); } diff --git a/src/test/bench/shootout-threadring.rs b/src/test/bench/shootout-threadring.rs index 111a92b083a..543597d8c81 100644 --- a/src/test/bench/shootout-threadring.rs +++ b/src/test/bench/shootout-threadring.rs @@ -38,15 +38,19 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED // OF THE POSSIBILITY OF SUCH DAMAGE. +use std::sync::mpsc::{channel, Sender, Receiver}; +use std::str::from_str; +use std::thread::Thread; + fn start(n_tasks: int, token: int) { let (tx, mut rx) = channel(); tx.send(token); for i in range(2, n_tasks + 1) { let (tx, next_rx) = channel(); - spawn(move|| roundtrip(i, tx, rx)); + Thread::spawn(move|| roundtrip(i, tx, rx)).detach(); rx = next_rx; } - spawn(move|| roundtrip(1, tx, rx)); + Thread::spawn(move|| roundtrip(1, tx, rx)).detach(); } fn roundtrip(id: int, tx: Sender<int>, rx: Receiver<int>) { diff --git a/src/test/bench/std-smallintmap.rs b/src/test/bench/std-smallintmap.rs index 576d96ba2a3..035b222e6ce 100644 --- a/src/test/bench/std-smallintmap.rs +++ b/src/test/bench/std-smallintmap.rs @@ -12,6 +12,7 @@ use std::collections::VecMap; use std::os; +use std::str::from_str; use std::time::Duration; use std::uint; diff --git a/src/test/bench/sudoku.rs b/src/test/bench/sudoku.rs index 5fb7e2c3a84..cccc9362a72 100644 --- a/src/test/bench/sudoku.rs +++ b/src/test/bench/sudoku.rs @@ -12,11 +12,12 @@ #![allow(non_snake_case)] -use std::io; -use std::io::stdio::StdReader; use std::io::BufferedReader; +use std::io::stdio::StdReader; +use std::io; use std::num::Int; use std::os; +use std::str::from_str; // Computes a single solution to a given 9x9 sudoku // diff --git a/src/test/bench/task-perf-jargon-metal-smoke.rs b/src/test/bench/task-perf-jargon-metal-smoke.rs index 789ccb6142a..a0278a63a51 100644 --- a/src/test/bench/task-perf-jargon-metal-smoke.rs +++ b/src/test/bench/task-perf-jargon-metal-smoke.rs @@ -17,25 +17,27 @@ // ignore-pretty very bad with line comments -use std::comm; +use std::sync::mpsc::{channel, Sender}; use std::os; +use std::str::from_str; use std::task; +use std::thread::Thread; use std::uint; -fn child_generation(gens_left: uint, tx: comm::Sender<()>) { +fn child_generation(gens_left: uint, tx: Sender<()>) { // This used to be O(n^2) in the number of generations that ever existed. // With this code, only as many generations are alive at a time as tasks // alive at a time, - spawn(move|| { + Thread::spawn(move|| { if gens_left & 1 == 1 { task::deschedule(); // shake things up a bit } if gens_left > 0 { child_generation(gens_left - 1, tx); // recurse } else { - tx.send(()) + tx.send(()).unwrap() } - }); + }).detach(); } fn main() { @@ -50,7 +52,7 @@ fn main() { let (tx, rx) = channel(); child_generation(from_str::<uint>(args[1].as_slice()).unwrap(), tx); - if rx.recv_opt().is_err() { + if rx.recv().is_err() { panic!("it happened when we slumbered"); } } diff --git a/src/test/bench/task-perf-spawnalot.rs b/src/test/bench/task-perf-spawnalot.rs index a6852d396d9..7e2c6fcf0ec 100644 --- a/src/test/bench/task-perf-spawnalot.rs +++ b/src/test/bench/task-perf-spawnalot.rs @@ -11,6 +11,7 @@ use std::os; use std::task; use std::uint; +use std::str::from_str; fn f(n: uint) { let mut i = 0u; diff --git a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs new file mode 100644 index 00000000000..5743216b6ca --- /dev/null +++ b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs @@ -0,0 +1,34 @@ +// Copyright 2014 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. + +// Test that we do not ICE when the self type is `ty::err`, but rather +// just propagate the error. + +#![crate_type = "lib"] +#![feature(associated_types, default_type_params, lang_items)] +#![no_std] + +#[lang="sized"] +pub trait Sized for Sized? { + // Empty. +} + +#[lang = "add"] +trait Add<RHS=Self> { + type Output; + + fn add(self, RHS) -> Self::Output; +} + +fn ice<A>(a: A) { + let r = loop {}; + r = r + a; // here the type `r` is not yet inferred, hence `r+a` generates an error. + //~^ ERROR type of this value must be known +} diff --git a/src/test/compile-fail/bind-by-move-no-guards.rs b/src/test/compile-fail/bind-by-move-no-guards.rs index 18534db0dd5..bb6060f2543 100644 --- a/src/test/compile-fail/bind-by-move-no-guards.rs +++ b/src/test/compile-fail/bind-by-move-no-guards.rs @@ -8,13 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::sync::mpsc::channel; + fn main() { let (tx, rx) = channel(); let x = Some(rx); tx.send(false); match x { - Some(z) if z.recv() => { panic!() }, //~ ERROR cannot bind by-move into a pattern guard - Some(z) => { assert!(!z.recv()); }, + Some(z) if z.recv().unwrap() => { panic!() }, + //~^ ERROR cannot bind by-move into a pattern guard + Some(z) => { assert!(!z.recv().unwrap()); }, None => panic!() } } diff --git a/src/test/compile-fail/binop-consume-args.rs b/src/test/compile-fail/binop-consume-args.rs index 2bdd148b99b..afa255be699 100644 --- a/src/test/compile-fail/binop-consume-args.rs +++ b/src/test/compile-fail/binop-consume-args.rs @@ -10,6 +10,8 @@ // Test that binary operators consume their arguments +use std::ops::{Add, Sub, Mul, Div, Rem, BitAnd, BitXor, BitOr, Shl, Shr}; + fn add<A: Add<B, ()>, B>(lhs: A, rhs: B) { lhs + rhs; drop(lhs); //~ ERROR use of moved value: `lhs` diff --git a/src/test/compile-fail/binop-move-semantics.rs b/src/test/compile-fail/binop-move-semantics.rs index d9440e18375..e48c88a49f0 100644 --- a/src/test/compile-fail/binop-move-semantics.rs +++ b/src/test/compile-fail/binop-move-semantics.rs @@ -10,6 +10,8 @@ // Test that move restrictions are enforced on overloaded binary operations +use std::ops::Add; + fn double_move<T: Add<T, ()>>(x: T) { x + diff --git a/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref-mut.rs b/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref-mut.rs index 05bc0d1e13b..7cd170f7773 100644 --- a/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref-mut.rs +++ b/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref-mut.rs @@ -11,19 +11,23 @@ // Test how overloaded deref interacts with borrows when DerefMut // is implemented. +#![feature(associated_types)] + use std::ops::{Deref, DerefMut}; struct Own<T> { value: *mut T } -impl<T> Deref<T> for Own<T> { +impl<T> Deref for Own<T> { + type Target = T; + fn deref(&self) -> &T { unsafe { &*self.value } } } -impl<T> DerefMut<T> for Own<T> { +impl<T> DerefMut for Own<T> { fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.value } } diff --git a/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref.rs b/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref.rs index 5aaefd01739..759467aeda3 100644 --- a/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref.rs +++ b/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref.rs @@ -11,13 +11,17 @@ // Test how overloaded deref interacts with borrows when only // Deref and not DerefMut is implemented. +#![feature(associated_types)] + use std::ops::Deref; struct Rc<T> { value: *const T } -impl<T> Deref<T> for Rc<T> { +impl<T> Deref for Rc<T> { + type Target = T; + fn deref(&self) -> &T { unsafe { &*self.value } } diff --git a/src/test/compile-fail/borrowck-borrow-overloaded-deref-mut.rs b/src/test/compile-fail/borrowck-borrow-overloaded-deref-mut.rs index 974fe3bc5d5..74dceab18ea 100644 --- a/src/test/compile-fail/borrowck-borrow-overloaded-deref-mut.rs +++ b/src/test/compile-fail/borrowck-borrow-overloaded-deref-mut.rs @@ -11,19 +11,23 @@ // Test how overloaded deref interacts with borrows when DerefMut // is implemented. +#![feature(associated_types)] + use std::ops::{Deref, DerefMut}; struct Own<T> { value: *mut T } -impl<T> Deref<T> for Own<T> { +impl<T> Deref for Own<T> { + type Target = T; + fn deref<'a>(&'a self) -> &'a T { unsafe { &*self.value } } } -impl<T> DerefMut<T> for Own<T> { +impl<T> DerefMut for Own<T> { fn deref_mut<'a>(&'a mut self) -> &'a mut T { unsafe { &mut *self.value } } diff --git a/src/test/compile-fail/borrowck-borrow-overloaded-deref.rs b/src/test/compile-fail/borrowck-borrow-overloaded-deref.rs index 5397c5b8a56..635e440c6fe 100644 --- a/src/test/compile-fail/borrowck-borrow-overloaded-deref.rs +++ b/src/test/compile-fail/borrowck-borrow-overloaded-deref.rs @@ -11,13 +11,17 @@ // Test how overloaded deref interacts with borrows when only // Deref and not DerefMut is implemented. +#![feature(associated_types)] + use std::ops::Deref; struct Rc<T> { value: *const T } -impl<T> Deref<T> for Rc<T> { +impl<T> Deref for Rc<T> { + type Target = T; + fn deref<'a>(&'a self) -> &'a T { unsafe { &*self.value } } diff --git a/src/test/compile-fail/borrowck-loan-in-overloaded-op.rs b/src/test/compile-fail/borrowck-loan-in-overloaded-op.rs index 3317295f88f..bcbb1f08b89 100644 --- a/src/test/compile-fail/borrowck-loan-in-overloaded-op.rs +++ b/src/test/compile-fail/borrowck-loan-in-overloaded-op.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::ops::Add; #[derive(Clone)] struct foo(Box<uint>); diff --git a/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs b/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs index 3143da99f48..a0edd078184 100644 --- a/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs +++ b/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::ops::Add; + #[derive(Copy)] struct Point { x: int, diff --git a/src/test/compile-fail/borrowck-overloaded-index-2.rs b/src/test/compile-fail/borrowck-overloaded-index-2.rs index d9d7a43d46c..01afe405d5e 100644 --- a/src/test/compile-fail/borrowck-overloaded-index-2.rs +++ b/src/test/compile-fail/borrowck-overloaded-index-2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::ops::Index; + struct MyVec<T> { data: Vec<T>, } diff --git a/src/test/compile-fail/borrowck-overloaded-index-autoderef.rs b/src/test/compile-fail/borrowck-overloaded-index-autoderef.rs index 2253d7512c0..e8949d4b30b 100644 --- a/src/test/compile-fail/borrowck-overloaded-index-autoderef.rs +++ b/src/test/compile-fail/borrowck-overloaded-index-autoderef.rs @@ -11,6 +11,8 @@ // Test that we still see borrowck errors of various kinds when using // indexing and autoderef in combination. +use std::ops::{Index, IndexMut}; + struct Foo { x: int, y: int, diff --git a/src/test/compile-fail/borrowck-overloaded-index.rs b/src/test/compile-fail/borrowck-overloaded-index.rs index 0422f6381dc..933d0f15e4e 100644 --- a/src/test/compile-fail/borrowck-overloaded-index.rs +++ b/src/test/compile-fail/borrowck-overloaded-index.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::ops::{Index, IndexMut}; + struct Foo { x: int, y: int, diff --git a/src/test/compile-fail/builtin-superkinds-self-type.rs b/src/test/compile-fail/builtin-superkinds-self-type.rs index 4c7ff60fbdd..9826a5a0126 100644 --- a/src/test/compile-fail/builtin-superkinds-self-type.rs +++ b/src/test/compile-fail/builtin-superkinds-self-type.rs @@ -11,6 +11,8 @@ // Tests (negatively) the ability for the Self type in default methods // to use capabilities granted by builtin kinds as supertraits. +use std::sync::mpsc::{channel, Sender}; + trait Foo : Sync+'static { fn foo(self, mut chan: Sender<Self>) { } } diff --git a/src/test/compile-fail/coherence-all-remote.rs b/src/test/compile-fail/coherence-all-remote.rs new file mode 100644 index 00000000000..67d96aa95a6 --- /dev/null +++ b/src/test/compile-fail/coherence-all-remote.rs @@ -0,0 +1,19 @@ +// Copyright 2014 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:coherence-lib.rs + +extern crate "coherence-lib" as lib; +use lib::Remote; + +impl<T> Remote for int { } +//~^ ERROR cannot provide an extension implementation + +fn main() { } diff --git a/src/test/compile-fail/coherence-bigint-param.rs b/src/test/compile-fail/coherence-bigint-param.rs new file mode 100644 index 00000000000..a04dfd36c98 --- /dev/null +++ b/src/test/compile-fail/coherence-bigint-param.rs @@ -0,0 +1,21 @@ +// Copyright 2014 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:coherence-lib.rs + +extern crate "coherence-lib" as lib; +use lib::Remote1; + +pub struct BigInt; + +impl<T> Remote1<BigInt> for T { } +//~^ ERROR type parameter `T` must also appear + +fn main() { } diff --git a/src/test/compile-fail/coherence-iterator-vec-any-elem.rs b/src/test/compile-fail/coherence-iterator-vec-any-elem.rs new file mode 100644 index 00000000000..2ed7a6db7ae --- /dev/null +++ b/src/test/compile-fail/coherence-iterator-vec-any-elem.rs @@ -0,0 +1,21 @@ +// Copyright 2014 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:coherence-lib.rs + +extern crate "coherence-lib" as lib; +use lib::Remote1; + +struct Foo<T>(T); + +impl<T,U> Remote1<U> for Foo<T> { } +//~^ ERROR type parameter `U` must also appear + +fn main() { } diff --git a/src/test/compile-fail/coherence-lone-type-parameter.rs b/src/test/compile-fail/coherence-lone-type-parameter.rs new file mode 100644 index 00000000000..0223dacd8ec --- /dev/null +++ b/src/test/compile-fail/coherence-lone-type-parameter.rs @@ -0,0 +1,18 @@ +// Copyright 2014 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:coherence-lib.rs + +extern crate "coherence-lib" as lib; +use lib::Remote; + +impl<T> Remote for T { } //~ ERROR E0117 + +fn main() { } diff --git a/src/test/compile-fail/coherence-overlapping-pairs.rs b/src/test/compile-fail/coherence-overlapping-pairs.rs new file mode 100644 index 00000000000..d42bd529b66 --- /dev/null +++ b/src/test/compile-fail/coherence-overlapping-pairs.rs @@ -0,0 +1,21 @@ +// Copyright 2014 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:coherence-lib.rs + +extern crate "coherence-lib" as lib; +use lib::Remote; + +struct Foo; + +impl<T> Remote for lib::Pair<T,Foo> { } +//~^ ERROR type parameter `T` must also appear + +fn main() { } diff --git a/src/test/compile-fail/coherence-pair-covered-uncovered.rs b/src/test/compile-fail/coherence-pair-covered-uncovered.rs new file mode 100644 index 00000000000..09895ec11db --- /dev/null +++ b/src/test/compile-fail/coherence-pair-covered-uncovered.rs @@ -0,0 +1,21 @@ +// Copyright 2014 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:coherence-lib.rs + +extern crate "coherence-lib" as lib; +use lib::{Remote, Pair}; + +struct Local<T>(T); + +impl<T,U> Remote for Pair<T,Local<U>> { } +//~^ ERROR type parameter `T` must also appear + +fn main() { } diff --git a/src/test/compile-fail/comm-not-freeze-receiver.rs b/src/test/compile-fail/comm-not-freeze-receiver.rs index 8cb4b6328c4..2e535b39509 100644 --- a/src/test/compile-fail/comm-not-freeze-receiver.rs +++ b/src/test/compile-fail/comm-not-freeze-receiver.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::sync::mpsc::Receiver; + fn test<T: Sync>() {} fn main() { diff --git a/src/test/compile-fail/comm-not-freeze.rs b/src/test/compile-fail/comm-not-freeze.rs index 8c17895eb8a..1b1c43e4793 100644 --- a/src/test/compile-fail/comm-not-freeze.rs +++ b/src/test/compile-fail/comm-not-freeze.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::sync::mpsc::Sender; + fn test<T: Sync>() {} fn main() { diff --git a/src/test/compile-fail/dst-sized-trait-param.rs b/src/test/compile-fail/dst-sized-trait-param.rs index 750b475adb2..ea5becbf229 100644 --- a/src/test/compile-fail/dst-sized-trait-param.rs +++ b/src/test/compile-fail/dst-sized-trait-param.rs @@ -12,7 +12,7 @@ // parameter, the corresponding value must be sized. Also that the // self type must be sized if appropriate. -trait Foo<T> { fn take(self, x: &T) { } } // Note: T is sized +trait Foo<T> : Sized { fn take(self, x: &T) { } } // Note: T is sized impl Foo<[int]> for uint { } //~^ ERROR the trait `core::kinds::Sized` is not implemented for the type `[int]` diff --git a/src/test/compile-fail/infinite-autoderef.rs b/src/test/compile-fail/infinite-autoderef.rs index e4c6fa7d47f..ab770c099e1 100644 --- a/src/test/compile-fail/infinite-autoderef.rs +++ b/src/test/compile-fail/infinite-autoderef.rs @@ -10,11 +10,15 @@ // error-pattern: reached the recursion limit while auto-dereferencing +#![feature(associated_types)] + use std::ops::Deref; struct Foo; -impl Deref<Foo> for Foo { +impl Deref for Foo { + type Target = Foo; + fn deref(&self) -> &Foo { self } diff --git a/src/test/compile-fail/issue-12041.rs b/src/test/compile-fail/issue-12041.rs index 1878b5f5dea..094f6d64edc 100644 --- a/src/test/compile-fail/issue-12041.rs +++ b/src/test/compile-fail/issue-12041.rs @@ -8,9 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::sync::mpsc::channel; +use std::thread::Thread; + fn main() { let (tx, rx) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| -> () { loop { let tx = tx; //~^ ERROR: use of moved value: `tx` diff --git a/src/test/compile-fail/issue-16709.rs b/src/test/compile-fail/issue-16709.rs index fc15801eb75..327f50ee059 100644 --- a/src/test/compile-fail/issue-16709.rs +++ b/src/test/compile-fail/issue-16709.rs @@ -11,6 +11,8 @@ use std::ptr; use std::raw; +trait Slice {} + fn main() { unsafe { let nil: *const u8 = ptr::null(); diff --git a/src/test/compile-fail/issue-18566.rs b/src/test/compile-fail/issue-18566.rs index f64d8fee2d8..491707a9e31 100644 --- a/src/test/compile-fail/issue-18566.rs +++ b/src/test/compile-fail/issue-18566.rs @@ -8,8 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(associated_types)] + +use std::ops::Deref; + struct MyPtr<'a>(&'a mut uint); -impl<'a> Deref<uint> for MyPtr<'a> { +impl<'a> Deref for MyPtr<'a> { + type Target = uint; + fn deref<'b>(&'b self) -> &'b uint { self.0 } } diff --git a/src/test/run-fail/panic-non-utf8.rs b/src/test/compile-fail/issue-18819.rs index 8b013199369..32a51ee065b 100644 --- a/src/test/run-fail/panic-non-utf8.rs +++ b/src/test/compile-fail/issue-18819.rs @@ -1,5 +1,4 @@ - -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -9,18 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Previously failed formating invalid utf8. -// cc #16877 +#![feature(associated_types)] + +trait Foo { + type Item; +} + +struct X; -// error-pattern:panicked at 'hello�' +impl Foo for X { + type Item = bool; +} -struct Foo; -impl std::fmt::Show for Foo { - fn fmt(&self, fmtr:&mut std::fmt::Formatter) -> std::fmt::Result { - // Purge invalid utf8: 0xff - fmtr.write(&[104, 101, 108, 108, 111, 0xff]) - } +fn print_x(_: &Foo, extra: &str) { + println!("{}", extra); } + fn main() { - panic!("{}", Foo) + print_x(X); //~error this function takes 2 parameters but 1 parameter was supplied } diff --git a/src/test/compile-fail/issue-18959.rs b/src/test/compile-fail/issue-18959.rs index 3d126790335..1a792eb6e76 100644 --- a/src/test/compile-fail/issue-18959.rs +++ b/src/test/compile-fail/issue-18959.rs @@ -21,6 +21,6 @@ impl Foo for Thing { fn main() { let mut thing = Thing; - let test: &Bar = &mut thing; //~ ERROR cannot convert to a trait object because trait `Foo` + let test: &Bar = &mut thing; //~ ERROR cannot convert to a trait object foo(test); } diff --git a/src/test/compile-fail/issue-19883.rs b/src/test/compile-fail/issue-19883.rs new file mode 100644 index 00000000000..196a04db18a --- /dev/null +++ b/src/test/compile-fail/issue-19883.rs @@ -0,0 +1,35 @@ +// 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. + +#![feature(associated_types)] + +trait From<Src> { + type Output; + + fn from(src: Src) -> <Self as From<Src>>::Output; +} + +trait To { + // This is a typo, the return type should be `<Dst as From<Self>>::Output` + fn to<Dst: From<Self>>( + self + //~^ error: the trait `core::kinds::Sized` is not implemented + ) -> + <Dst as From<Self>>::Dst + //~^ error: the trait `core::kinds::Sized` is not implemented + { + From::from( + //~^ error: the trait `core::kinds::Sized` is not implemented + self + ) + } +} + +fn main() {} diff --git a/src/test/compile-fail/issue-20005.rs b/src/test/compile-fail/issue-20005.rs new file mode 100644 index 00000000000..d9520583ca5 --- /dev/null +++ b/src/test/compile-fail/issue-20005.rs @@ -0,0 +1,29 @@ +// 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. + +#![feature(associated_types)] + +trait From<Src> { + type Result; + + fn from(src: Src) -> Self::Result; +} + +trait To { + fn to<Dst>( + self //~ error: the trait `core::kinds::Sized` is not implemented + ) -> <Dst as From<Self>>::Result where Dst: From<Self> { + From::from( //~ error: the trait `core::kinds::Sized` is not implemented + self + ) + } +} + +fn main() {} diff --git a/src/test/compile-fail/issue-20313.rs b/src/test/compile-fail/issue-20313.rs new file mode 100644 index 00000000000..dfb23c05036 --- /dev/null +++ b/src/test/compile-fail/issue-20313.rs @@ -0,0 +1,17 @@ +// Copyright 2014 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. + +extern { + #[link_name = "llvm.sqrt.f32"] + fn sqrt(x: f32) -> f32; //~ ERROR linking to LLVM intrinsics is experimental +} + +fn main(){ +} diff --git a/src/test/compile-fail/issue-3702-2.rs b/src/test/compile-fail/issue-3702-2.rs index 54100d543dd..1e80fd7a7e9 100644 --- a/src/test/compile-fail/issue-3702-2.rs +++ b/src/test/compile-fail/issue-3702-2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::num::ToPrimitive; + trait Add { fn to_int(&self) -> int; fn add_dynamic(&self, other: &Add) -> int; diff --git a/src/test/compile-fail/issue-5543.rs b/src/test/compile-fail/issue-5543.rs index bbd41b28f03..f970cdb1b83 100644 --- a/src/test/compile-fail/issue-5543.rs +++ b/src/test/compile-fail/issue-5543.rs @@ -15,5 +15,4 @@ fn main() { let r: Box<Foo> = box 5; let _m: Box<Foo> = r as Box<Foo>; //~^ ERROR `core::kinds::Sized` is not implemented for the type `Foo` - //~| ERROR `Foo` is not implemented for the type `Foo` } diff --git a/src/test/compile-fail/object-safety-by-value-self.rs b/src/test/compile-fail/object-safety-by-value-self.rs new file mode 100644 index 00000000000..5ebcc8516ca --- /dev/null +++ b/src/test/compile-fail/object-safety-by-value-self.rs @@ -0,0 +1,47 @@ +// Copyright 2014 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. + +// Check that we correctly prevent users from making trait objects +// from traits with a `fn(self)` method. + +trait Bar { + fn bar(self); +} + +trait Baz { + fn baz(self: Self); +} + +fn make_bar<T:Bar>(t: &T) -> &Bar { + t + //~^ ERROR `Bar` is not object-safe + //~| NOTE method `bar` has a receiver type of `Self` +} + +fn make_bar_explicit<T:Bar>(t: &T) -> &Bar { + t as &Bar + //~^ ERROR `Bar` is not object-safe + //~| NOTE method `bar` has a receiver type of `Self` +} + +fn make_baz<T:Baz>(t: &T) -> &Baz { + t + //~^ ERROR `Baz` is not object-safe + //~| NOTE method `baz` has a receiver type of `Self` +} + +fn make_baz_explicit<T:Baz>(t: &T) -> &Baz { + t as &Baz + //~^ ERROR `Baz` is not object-safe + //~| NOTE method `baz` has a receiver type of `Self` +} + +fn main() { +} diff --git a/src/test/compile-fail/object-safety-generics.rs b/src/test/compile-fail/object-safety-generics.rs new file mode 100644 index 00000000000..0ca706404c1 --- /dev/null +++ b/src/test/compile-fail/object-safety-generics.rs @@ -0,0 +1,31 @@ +// Copyright 2014 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. + +// Check that we correctly prevent users from making trait objects +// from traits with generic methods. + +trait Bar { + fn bar<T>(&self, t: T); +} + +fn make_bar<T:Bar>(t: &T) -> &Bar { + t + //~^ ERROR `Bar` is not object-safe + //~| NOTE method `bar` has generic type parameters +} + +fn make_bar_explicit<T:Bar>(t: &T) -> &Bar { + t as &Bar + //~^ ERROR `Bar` is not object-safe + //~| NOTE method `bar` has generic type parameters +} + +fn main() { +} diff --git a/src/test/compile-fail/object-safety-mentions-Self.rs b/src/test/compile-fail/object-safety-mentions-Self.rs new file mode 100644 index 00000000000..df0f44c1391 --- /dev/null +++ b/src/test/compile-fail/object-safety-mentions-Self.rs @@ -0,0 +1,47 @@ +// Copyright 2014 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. + +// Check that we correctly prevent users from making trait objects +// form traits that make use of `Self` in an argument or return position. + +trait Bar { + fn bar(&self, x: &Self); +} + +trait Baz { + fn bar(&self) -> Self; +} + +fn make_bar<T:Bar>(t: &T) -> &Bar { + t + //~^ ERROR `Bar` is not object-safe + //~| NOTE method `bar` references the `Self` type in its arguments or return type +} + +fn make_bar_explicit<T:Bar>(t: &T) -> &Bar { + t as &Bar + //~^ ERROR `Bar` is not object-safe + //~| NOTE method `bar` references the `Self` type in its arguments or return type +} + +fn make_baz<T:Baz>(t: &T) -> &Baz { + t + //~^ ERROR `Baz` is not object-safe + //~| NOTE method `bar` references the `Self` type in its arguments or return type +} + +fn make_baz_explicit<T:Baz>(t: &T) -> &Baz { + t as &Baz + //~^ ERROR `Baz` is not object-safe + //~| NOTE method `bar` references the `Self` type in its arguments or return type +} + +fn main() { +} diff --git a/src/test/compile-fail/object-safety-no-static.rs b/src/test/compile-fail/object-safety-no-static.rs new file mode 100644 index 00000000000..6a010d49692 --- /dev/null +++ b/src/test/compile-fail/object-safety-no-static.rs @@ -0,0 +1,31 @@ +// Copyright 2014 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. + +// Check that we correctly prevent users from making trait objects +// from traits with static methods. + +trait Foo { + fn foo(); +} + +fn foo_implicit<T:Foo+'static>(b: Box<T>) -> Box<Foo+'static> { + b + //~^ ERROR cannot convert to a trait object + //~| NOTE method `foo` has no receiver +} + +fn foo_explicit<T:Foo+'static>(b: Box<T>) -> Box<Foo+'static> { + b as Box<Foo> + //~^ ERROR cannot convert to a trait object + //~| NOTE method `foo` has no receiver +} + +fn main() { +} diff --git a/src/test/compile-fail/object-safety-sized-2.rs b/src/test/compile-fail/object-safety-sized-2.rs new file mode 100644 index 00000000000..3a02461bbb2 --- /dev/null +++ b/src/test/compile-fail/object-safety-sized-2.rs @@ -0,0 +1,33 @@ +// Copyright 2014 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. + +// Check that we correctly prevent users from making trait objects +// from traits where `Self : Sized`. + +trait Bar + where Self : Sized +{ + fn bar<T>(&self, t: T); +} + +fn make_bar<T:Bar>(t: &T) -> &Bar { + t + //~^ ERROR `Bar` is not object-safe + //~| NOTE the trait cannot require that `Self : Sized` +} + +fn make_bar_explicit<T:Bar>(t: &T) -> &Bar { + t as &Bar + //~^ ERROR `Bar` is not object-safe + //~| NOTE the trait cannot require that `Self : Sized` +} + +fn main() { +} diff --git a/src/test/compile-fail/object-safety-sized.rs b/src/test/compile-fail/object-safety-sized.rs new file mode 100644 index 00000000000..bc214f6f3d9 --- /dev/null +++ b/src/test/compile-fail/object-safety-sized.rs @@ -0,0 +1,31 @@ +// Copyright 2014 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. + +// Check that we correctly prevent users from making trait objects +// from traits where `Self : Sized`. + +trait Bar : Sized { + fn bar<T>(&self, t: T); +} + +fn make_bar<T:Bar>(t: &T) -> &Bar { + t + //~^ ERROR `Bar` is not object-safe + //~| NOTE the trait cannot require that `Self : Sized` +} + +fn make_bar_explicit<T:Bar>(t: &T) -> &Bar { + t as &Bar + //~^ ERROR `Bar` is not object-safe + //~| NOTE the trait cannot require that `Self : Sized` +} + +fn main() { +} diff --git a/src/test/compile-fail/opt-out-copy-bad.rs b/src/test/compile-fail/opt-out-copy-bad.rs index 80f8a154d58..4aae8fa87da 100644 --- a/src/test/compile-fail/opt-out-copy-bad.rs +++ b/src/test/compile-fail/opt-out-copy-bad.rs @@ -9,6 +9,8 @@ // except according to those terms. #![feature(opt_out_copy)] +//~^ WARNING feature is deprecated +//~| WARNING feature is deprecated // Test that when using the `opt-out-copy` feature we still consider // destructors to be non-movable diff --git a/src/test/compile-fail/regions-infer-bound-from-trait-self.rs b/src/test/compile-fail/regions-infer-bound-from-trait-self.rs index 25fd20b6ec5..aeb003ca5d0 100644 --- a/src/test/compile-fail/regions-infer-bound-from-trait-self.rs +++ b/src/test/compile-fail/regions-infer-bound-from-trait-self.rs @@ -23,12 +23,12 @@ fn check_bound<'a,A:'a>(x: Inv<'a>, a: A) { } // In these case, `Self` inherits `'static`. -trait InheritsFromStatic : 'static { +trait InheritsFromStatic : Sized + 'static { fn foo1<'a>(self, x: Inv<'a>) { check_bound(x, self) } } -trait InheritsFromStaticIndirectly : Static { +trait InheritsFromStaticIndirectly : Sized + Static { fn foo1<'a>(self, x: Inv<'a>) { check_bound(x, self) } @@ -37,13 +37,13 @@ trait InheritsFromStaticIndirectly : Static { // In these case, `Self` inherits `'a`. -trait InheritsFromIs<'a> : 'a { +trait InheritsFromIs<'a> : Sized + 'a { fn foo(self, x: Inv<'a>) { check_bound(x, self) } } -trait InheritsFromIsIndirectly<'a> : Is<'a> { +trait InheritsFromIsIndirectly<'a> : Sized + Is<'a> { fn foo(self, x: Inv<'a>) { check_bound(x, self) } @@ -51,7 +51,7 @@ trait InheritsFromIsIndirectly<'a> : Is<'a> { // In this case, `Self` inherits nothing. -trait InheritsFromNothing<'a> { +trait InheritsFromNothing<'a> : Sized { fn foo(self, x: Inv<'a>) { check_bound(x, self) //~^ ERROR parameter type `Self` may not live long enough diff --git a/src/test/compile-fail/std-uncopyable-atomics.rs b/src/test/compile-fail/std-uncopyable-atomics.rs index c0122b8a2a9..501187ca9e5 100644 --- a/src/test/compile-fail/std-uncopyable-atomics.rs +++ b/src/test/compile-fail/std-uncopyable-atomics.rs @@ -16,11 +16,11 @@ use std::sync::atomic::*; use std::ptr; fn main() { - let x = INIT_ATOMIC_BOOL; + let x = ATOMIC_BOOL_INIT; let x = *&x; //~ ERROR: cannot move out of dereference - let x = INIT_ATOMIC_INT; + let x = ATOMIC_INT_INIT; let x = *&x; //~ ERROR: cannot move out of dereference - let x = INIT_ATOMIC_UINT; + let x = ATOMIC_UINT_INIT; let x = *&x; //~ ERROR: cannot move out of dereference let x: AtomicPtr<uint> = AtomicPtr::new(ptr::null_mut()); let x = *&x; //~ ERROR: cannot move out of dereference diff --git a/src/test/compile-fail/trait-matching-lifetimes.rs b/src/test/compile-fail/trait-matching-lifetimes.rs index f1b30166b5e..333730e0c4b 100644 --- a/src/test/compile-fail/trait-matching-lifetimes.rs +++ b/src/test/compile-fail/trait-matching-lifetimes.rs @@ -16,7 +16,7 @@ struct Foo<'a,'b> { y: &'b int, } -trait Tr { +trait Tr : Sized { fn foo(x: Self) {} } diff --git a/src/test/compile-fail/trait-objects.rs b/src/test/compile-fail/trait-objects.rs deleted file mode 100644 index 88b907a5cb9..00000000000 --- a/src/test/compile-fail/trait-objects.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2014 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. - -trait Foo { - fn foo(self); -} - -trait Bar { - fn bar(&self, x: &Self); -} - -trait Baz { - fn baz<T>(&self, x: &T); -} - -impl Foo for int { - fn foo(self) {} -} - -impl Bar for int { - fn bar(&self, _x: &int) {} -} - -impl Baz for int { - fn baz<T>(&self, _x: &T) {} -} - -fn main() { - let _: &Foo = &42i; //~ ERROR cannot convert to a trait object - let _: &Bar = &42i; //~ ERROR cannot convert to a trait object - let _: &Baz = &42i; //~ ERROR cannot convert to a trait object - - let _ = &42i as &Foo; //~ ERROR cannot convert to a trait object - let _ = &42i as &Bar; //~ ERROR cannot convert to a trait object - let _ = &42i as &Baz; //~ ERROR cannot convert to a trait object -} diff --git a/src/test/compile-fail/trait-safety-fn-body.rs b/src/test/compile-fail/trait-safety-fn-body.rs index d174092e4d0..f894e2ee28e 100644 --- a/src/test/compile-fail/trait-safety-fn-body.rs +++ b/src/test/compile-fail/trait-safety-fn-body.rs @@ -11,7 +11,7 @@ // Check that an unsafe impl does not imply that unsafe actions are // legal in the methods. -unsafe trait UnsafeTrait { +unsafe trait UnsafeTrait : Sized { fn foo(self) { } } diff --git a/src/test/compile-fail/type-params-in-different-spaces-2.rs b/src/test/compile-fail/type-params-in-different-spaces-2.rs index 9be64bf5346..3a4cc9e874e 100644 --- a/src/test/compile-fail/type-params-in-different-spaces-2.rs +++ b/src/test/compile-fail/type-params-in-different-spaces-2.rs @@ -11,7 +11,7 @@ // Test static calls to make sure that we align the Self and input // type parameters on a trait correctly. -trait Tr<T> { +trait Tr<T> : Sized { fn op(T) -> Self; } diff --git a/src/test/compile-fail/type-params-in-different-spaces-3.rs b/src/test/compile-fail/type-params-in-different-spaces-3.rs index a3d69d53ba9..c113e1b7815 100644 --- a/src/test/compile-fail/type-params-in-different-spaces-3.rs +++ b/src/test/compile-fail/type-params-in-different-spaces-3.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Tr { +trait Tr : Sized { fn test<X>(u: X) -> Self { u //~ ERROR mismatched types } diff --git a/src/test/compile-fail/unop-move-semantics.rs b/src/test/compile-fail/unop-move-semantics.rs index ccdc7b833e7..c458c539c07 100644 --- a/src/test/compile-fail/unop-move-semantics.rs +++ b/src/test/compile-fail/unop-move-semantics.rs @@ -10,6 +10,8 @@ // Test that move restrictions are enforced on overloaded unary operations +use std::ops::Not; + fn move_then_borrow<T: Not<T> + Clone>(x: T) { !x; diff --git a/src/test/compile-fail/unsendable-class.rs b/src/test/compile-fail/unsendable-class.rs index cd5918e2f47..993df8e59f3 100644 --- a/src/test/compile-fail/unsendable-class.rs +++ b/src/test/compile-fail/unsendable-class.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::sync::mpsc::channel; // Test that a class with an unsendable field can't be // sent diff --git a/src/test/compile-fail/unsized4.rs b/src/test/compile-fail/unsized4.rs index 0537fc1f94a..f9ece8e6843 100644 --- a/src/test/compile-fail/unsized4.rs +++ b/src/test/compile-fail/unsized4.rs @@ -10,8 +10,7 @@ // Test that bounds are sized-compatible. -trait T {} - +trait T : Sized {} fn f<Sized? Y: T>() { //~^ERROR incompatible bounds on `Y`, bound `T` does not allow unsized type } diff --git a/src/test/compile-fail/variance-trait-matching-2.rs b/src/test/compile-fail/variance-trait-matching-2.rs index ed4fdc52572..cae7a4cefad 100644 --- a/src/test/compile-fail/variance-trait-matching-2.rs +++ b/src/test/compile-fail/variance-trait-matching-2.rs @@ -10,17 +10,17 @@ extern crate serialize; -use std::io; +use std::fmt; use serialize::{Encodable, Encoder}; pub fn buffer_encode<'a, - T:Encodable<serialize::json::Encoder<'a>,io::IoError>>( + T:Encodable<serialize::json::Encoder<'a>,fmt::Error>>( to_encode_object: &T) - -> Vec<u8> { - let mut m = Vec::new(); + -> String { + let mut m = String::new(); { let mut encoder = - serialize::json::Encoder::new(&mut m as &mut io::Writer); + serialize::json::Encoder::new(&mut m); //~^ ERROR `m` does not live long enough to_encode_object.encode(&mut encoder); } diff --git a/src/test/compile-fail/wrong-mul-method-signature.rs b/src/test/compile-fail/wrong-mul-method-signature.rs index b5e4cac7555..bde5b853078 100644 --- a/src/test/compile-fail/wrong-mul-method-signature.rs +++ b/src/test/compile-fail/wrong-mul-method-signature.rs @@ -13,6 +13,8 @@ // (In this case the mul method should take &f64 and not f64) // See: #11450 +use std::ops::Mul; + struct Vec1 { x: f64 } diff --git a/src/test/debuginfo/issue7712.rs b/src/test/debuginfo/issue7712.rs index 948048ec272..94458a7fb4b 100644 --- a/src/test/debuginfo/issue7712.rs +++ b/src/test/debuginfo/issue7712.rs @@ -11,7 +11,7 @@ // compile-flags:--debuginfo=1 // min-lldb-version: 310 -pub trait TraitWithDefaultMethod { +pub trait TraitWithDefaultMethod : Sized { fn method(self) { () } diff --git a/src/test/debuginfo/self-in-default-method.rs b/src/test/debuginfo/self-in-default-method.rs index f8ef5b3d2fc..87884d2f956 100644 --- a/src/test/debuginfo/self-in-default-method.rs +++ b/src/test/debuginfo/self-in-default-method.rs @@ -118,7 +118,7 @@ struct Struct { x: int } -trait Trait { +trait Trait : Sized { fn self_by_ref(&self, arg1: int, arg2: int) -> int { zzz(); // #break arg1 + arg2 diff --git a/src/test/debuginfo/self-in-generic-default-method.rs b/src/test/debuginfo/self-in-generic-default-method.rs index c2594df7d35..62b5e6872ee 100644 --- a/src/test/debuginfo/self-in-generic-default-method.rs +++ b/src/test/debuginfo/self-in-generic-default-method.rs @@ -118,7 +118,7 @@ struct Struct { x: int } -trait Trait { +trait Trait : Sized { fn self_by_ref<T>(&self, arg1: int, arg2: T) -> int { zzz(); // #break diff --git a/src/test/debuginfo/unreachable-locals.rs b/src/test/debuginfo/unreachable-locals.rs new file mode 100644 index 00000000000..c15dcd1958f --- /dev/null +++ b/src/test/debuginfo/unreachable-locals.rs @@ -0,0 +1,86 @@ +// Copyright 2013-2014 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. + +// ignore-android: FIXME(#10381) +// min-lldb-version: 310 + +// compile-flags:-g + +#![allow(unused_variables)] +#![omit_gdb_pretty_printer_section] + +// No need to actually run the debugger, just make sure that the compiler can +// handle locals in unreachable code. + +fn after_return() { + return; + let x = "0"; + let (ref y,z) = (1i32, 2u32); + match (20i32, 'c') { + (a, ref b) => {} + } + for a in [111i32].iter() {} +} + +fn after_panic() { + panic!(); + let x = "0"; + let (ref y,z) = (1i32, 2u32); + match (20i32, 'c') { + (a, ref b) => {} + } + for a in [111i32].iter() {} +} + +fn after_diverging_function() { + diverge(); + let x = "0"; + let (ref y,z) = (1i32, 2u32); + match (20i32, 'c') { + (a, ref b) => {} + } + for a in [111i32].iter() {} +} + +fn after_break() { + loop { + break; + let x = "0"; + let (ref y,z) = (1i32, 2u32); + match (20i32, 'c') { + (a, ref b) => {} + } + for a in [111i32].iter() {} + } +} + +fn after_continue() { + for _ in range(0, 10i32) { + break; + let x = "0"; + let (ref y,z) = (1i32, 2u32); + match (20i32, 'c') { + (a, ref b) => {} + } + for a in [111i32].iter() {} + } +} + +fn main() { + after_return(); + after_panic(); + after_diverging_function(); + after_break(); + after_continue(); +} + +fn diverge() -> ! { + panic!(); +} diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index c2ebd764ad6..35bd22880ce 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -4,7 +4,7 @@ #[phase(plugin, link)] extern crate "std" as std; #[prelude_import] -use std::prelude::*; +use std::prelude::v1::*; // Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. diff --git a/src/test/run-pass/issue-7320.rs b/src/test/pretty/let.rs index c7087f8e3a8..736ea3a0d10 100644 --- a/src/test/run-pass/issue-7320.rs +++ b/src/test/pretty/let.rs @@ -8,11 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pp-exact -trait Foo { - fn foo(self: Box<Self>) { bar(self as Box<Foo>); } -} +// Check that `let x: _ = 0;` does not print as `let x = 0;`. -fn bar(_b: Box<Foo>) { } +fn main() { + let x: _ = 0; -fn main() {} + let _ = x; +} diff --git a/src/test/run-make/compiler-lookup-paths/Makefile b/src/test/run-make/compiler-lookup-paths/Makefile index 032e0882ff8..154e46c0edc 100644 --- a/src/test/run-make/compiler-lookup-paths/Makefile +++ b/src/test/run-make/compiler-lookup-paths/Makefile @@ -6,25 +6,25 @@ all: $(TMPDIR)/libnative.a mv $(TMPDIR)/libnative.a $(TMPDIR)/native $(RUSTC) a.rs mv $(TMPDIR)/liba.rlib $(TMPDIR)/crate - $(RUSTC) b.rs -L $(TMPDIR)/crate:native && exit 1 || exit 0 - $(RUSTC) b.rs -L $(TMPDIR)/crate:dependency && exit 1 || exit 0 - $(RUSTC) b.rs -L $(TMPDIR)/crate:crate - $(RUSTC) b.rs -L $(TMPDIR)/crate - $(RUSTC) c.rs -L $(TMPDIR)/crate:native && exit 1 || exit 0 - $(RUSTC) c.rs -L $(TMPDIR)/crate:crate && exit 1 || exit 0 - $(RUSTC) c.rs -L $(TMPDIR)/crate:dependency - $(RUSTC) c.rs -L $(TMPDIR)/crate - $(RUSTC) d.rs -L $(TMPDIR)/native:dependency && exit 1 || exit 0 - $(RUSTC) d.rs -L $(TMPDIR)/native:crate && exit 1 || exit 0 - $(RUSTC) d.rs -L $(TMPDIR)/native:native - $(RUSTC) d.rs -L $(TMPDIR)/native + $(RUSTC) b.rs -L native=$(TMPDIR)/crate && exit 1 || exit 0 + $(RUSTC) b.rs -L dependency=$(TMPDIR)/crate && exit 1 || exit 0 + $(RUSTC) b.rs -L crate=$(TMPDIR)/crate + $(RUSTC) b.rs -L all=$(TMPDIR)/crate + $(RUSTC) c.rs -L native=$(TMPDIR)/crate && exit 1 || exit 0 + $(RUSTC) c.rs -L crate=$(TMPDIR)/crate && exit 1 || exit 0 + $(RUSTC) c.rs -L dependency=$(TMPDIR)/crate + $(RUSTC) c.rs -L all=$(TMPDIR)/crate + $(RUSTC) d.rs -L dependency=$(TMPDIR)/native && exit 1 || exit 0 + $(RUSTC) d.rs -L crate=$(TMPDIR)/native && exit 1 || exit 0 + $(RUSTC) d.rs -L native=$(TMPDIR)/native + $(RUSTC) d.rs -L all=$(TMPDIR)/native mkdir -p $(TMPDIR)/e1 mkdir -p $(TMPDIR)/e2 $(RUSTC) e.rs -o $(TMPDIR)/e1/libe.rlib $(RUSTC) e.rs -o $(TMPDIR)/e2/libe.rlib $(RUSTC) f.rs -L $(TMPDIR)/e1 -L $(TMPDIR)/e2 && exit 1 || exit 0 - $(RUSTC) f.rs -L $(TMPDIR)/e1:crate -L $(TMPDIR)/e2 && exit 1 || exit 0 - $(RUSTC) f.rs -L $(TMPDIR)/e1:crate -L $(TMPDIR)/e2:crate && exit 1 || exit 0 - $(RUSTC) f.rs -L $(TMPDIR)/e1:native -L $(TMPDIR)/e2 - $(RUSTC) f.rs -L $(TMPDIR)/e1:dependency -L $(TMPDIR)/e2 - $(RUSTC) f.rs -L $(TMPDIR)/e1:dependency -L $(TMPDIR)/e2:crate + $(RUSTC) f.rs -L crate=$(TMPDIR)/e1 -L $(TMPDIR)/e2 && exit 1 || exit 0 + $(RUSTC) f.rs -L crate=$(TMPDIR)/e1 -L crate=$(TMPDIR)/e2 && exit 1 || exit 0 + $(RUSTC) f.rs -L native=$(TMPDIR)/e1 -L $(TMPDIR)/e2 + $(RUSTC) f.rs -L dependency=$(TMPDIR)/e1 -L $(TMPDIR)/e2 + $(RUSTC) f.rs -L dependency=$(TMPDIR)/e1 -L crate=$(TMPDIR)/e2 diff --git a/src/test/run-make/manual-link/Makefile b/src/test/run-make/manual-link/Makefile index d2a02adc9d4..d0536956152 100644 --- a/src/test/run-make/manual-link/Makefile +++ b/src/test/run-make/manual-link/Makefile @@ -1,7 +1,7 @@ -include ../tools.mk all: $(TMPDIR)/libbar.a - $(RUSTC) foo.rs -lbar:static + $(RUSTC) foo.rs -lstatic=bar $(RUSTC) main.rs $(call RUN,main) diff --git a/src/test/run-pass/associated-types-conditional-dispatch.rs b/src/test/run-pass/associated-types-conditional-dispatch.rs new file mode 100644 index 00000000000..3b53203d218 --- /dev/null +++ b/src/test/run-pass/associated-types-conditional-dispatch.rs @@ -0,0 +1,73 @@ +// Copyright 2014 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. + +// Test that we evaluate projection predicates to winnow out +// candidates during trait selection and method resolution (#20296). +// If we don't properly winnow out candidates based on the output type +// `Target=[A]`, then the impl marked with `(*)` is seen to conflict +// with all the others. + +#![feature(associated_types, default_type_params)] + +use std::ops::Deref; + +pub trait MyEq<Sized? U=Self> for Sized? { + fn eq(&self, u: &U) -> bool; +} + +impl<A, B> MyEq<[B]> for [A] + where A : MyEq<B> +{ + fn eq(&self, other: &[B]) -> bool { + self.len() == other.len() && + self.iter().zip(other.iter()) + .all(|(a, b)| MyEq::eq(a, b)) + } +} + +// (*) This impl conflicts with everything unless the `Target=[A]` +// constraint is considered. +impl<'a, A, B, Lhs> MyEq<[B; 0]> for Lhs + where A: MyEq<B>, Lhs: Deref<Target=[A]> +{ + fn eq(&self, other: &[B; 0]) -> bool { + MyEq::eq(&**self, other.as_slice()) + } +} + +struct DerefWithHelper<H, T> { + pub helper: H +} + +trait Helper<T> { + fn helper_borrow(&self) -> &T; +} + +impl<T> Helper<T> for Option<T> { + fn helper_borrow(&self) -> &T { + self.as_ref().unwrap() + } +} + +impl<T, H: Helper<T>> Deref for DerefWithHelper<H, T> { + type Target = T; + + fn deref(&self) -> &T { + self.helper.helper_borrow() + } +} + +pub fn check<T: MyEq>(x: T, y: T) -> bool { + let d: DerefWithHelper<Option<T>, T> = DerefWithHelper { helper: Some(x) }; + d.eq(&y) +} + +pub fn main() { +} diff --git a/src/test/run-pass/associated-types-impl-redirect.rs b/src/test/run-pass/associated-types-impl-redirect.rs index a28cf346336..ce7f5dde2ad 100644 --- a/src/test/run-pass/associated-types-impl-redirect.rs +++ b/src/test/run-pass/associated-types-impl-redirect.rs @@ -19,6 +19,7 @@ #![feature(associated_types, lang_items, unboxed_closures)] #![no_implicit_prelude] +use std::kinds::Sized; use std::option::Option::{None, Some, mod}; trait Iterator { @@ -27,7 +28,7 @@ trait Iterator { fn next(&mut self) -> Option<Self::Item>; } -trait IteratorExt: Iterator { +trait IteratorExt: Iterator + Sized { fn by_ref(&mut self) -> ByRef<Self> { ByRef(self) } diff --git a/src/test/run-pass/associated-types-projection-bound-in-supertraits.rs b/src/test/run-pass/associated-types-projection-bound-in-supertraits.rs index 83686d92a7c..92daee5225d 100644 --- a/src/test/run-pass/associated-types-projection-bound-in-supertraits.rs +++ b/src/test/run-pass/associated-types-projection-bound-in-supertraits.rs @@ -21,7 +21,7 @@ trait Not { fn not(self) -> Self::Result; } -trait Int: Not<Result=Self> { +trait Int: Not<Result=Self> + Sized { fn count_ones(self) -> uint; fn count_zeros(self) -> uint { // neither works diff --git a/src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs b/src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs index 062d37556ec..7afaf290424 100644 --- a/src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs +++ b/src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs @@ -19,6 +19,7 @@ #![feature(associated_types, lang_items, unboxed_closures)] #![no_implicit_prelude] +use std::kinds::Sized; use std::option::Option::{None, Some, mod}; trait Iterator { @@ -27,7 +28,7 @@ trait Iterator { fn next(&mut self) -> Option<Self::Item>; } -trait IteratorExt: Iterator { +trait IteratorExt: Iterator + Sized { fn by_ref(&mut self) -> ByRef<Self> { ByRef(self) } diff --git a/src/test/run-pass/bool.rs b/src/test/run-pass/bool.rs index 238d0ecdca7..b3c4802530e 100644 --- a/src/test/run-pass/bool.rs +++ b/src/test/run-pass/bool.rs @@ -10,6 +10,9 @@ // Basic boolean tests +use std::cmp::Ordering::{Equal, Greater, Less}; +use std::ops::{BitAnd, BitOr, BitXor}; + fn main() { assert_eq!(false.eq(&true), false); assert_eq!(false == false, true); diff --git a/src/test/run-pass/bug-7183-generics.rs b/src/test/run-pass/bug-7183-generics.rs index 8c4d10a2d59..bf8d303f341 100644 --- a/src/test/run-pass/bug-7183-generics.rs +++ b/src/test/run-pass/bug-7183-generics.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Speak { +trait Speak : Sized { fn say(&self, s:&str) -> String; fn hi(&self) -> String { hello(self) } } diff --git a/src/test/run-pass/builtin-superkinds-capabilities-transitive.rs b/src/test/run-pass/builtin-superkinds-capabilities-transitive.rs index 2abc58d8a49..365670db6f9 100644 --- a/src/test/run-pass/builtin-superkinds-capabilities-transitive.rs +++ b/src/test/run-pass/builtin-superkinds-capabilities-transitive.rs @@ -14,6 +14,8 @@ // a Send. Basically this just makes sure rustc is using // each_bound_trait_and_supertraits in type_contents correctly. +use std::sync::mpsc::{channel, Sender}; + trait Bar : Send { } trait Foo : Bar { } @@ -21,11 +23,11 @@ impl <T: Send> Foo for T { } impl <T: Send> Bar for T { } fn foo<T: Foo>(val: T, chan: Sender<T>) { - chan.send(val); + chan.send(val).unwrap(); } pub fn main() { let (tx, rx) = channel(); foo(31337i, tx); - assert!(rx.recv() == 31337i); + assert!(rx.recv().unwrap() == 31337i); } diff --git a/src/test/run-pass/builtin-superkinds-capabilities-xc.rs b/src/test/run-pass/builtin-superkinds-capabilities-xc.rs index efea4ffe9be..126088d7f9d 100644 --- a/src/test/run-pass/builtin-superkinds-capabilities-xc.rs +++ b/src/test/run-pass/builtin-superkinds-capabilities-xc.rs @@ -15,6 +15,8 @@ // even when using them cross-crate. extern crate trait_superkinds_in_metadata; + +use std::sync::mpsc::{channel, Sender, Receiver}; use trait_superkinds_in_metadata::{RequiresRequiresShareAndSend, RequiresShare}; #[derive(PartialEq)] @@ -24,11 +26,11 @@ impl <T: Sync> RequiresShare for X<T> { } impl <T: Sync+Send> RequiresRequiresShareAndSend for X<T> { } fn foo<T: RequiresRequiresShareAndSend>(val: T, chan: Sender<T>) { - chan.send(val); + chan.send(val).unwrap(); } pub fn main() { let (tx, rx): (Sender<X<int>>, Receiver<X<int>>) = channel(); foo(X(31337i), tx); - assert!(rx.recv() == X(31337i)); + assert!(rx.recv().unwrap() == X(31337i)); } diff --git a/src/test/run-pass/builtin-superkinds-capabilities.rs b/src/test/run-pass/builtin-superkinds-capabilities.rs index fb3e1b02728..7f4a2398f54 100644 --- a/src/test/run-pass/builtin-superkinds-capabilities.rs +++ b/src/test/run-pass/builtin-superkinds-capabilities.rs @@ -12,16 +12,18 @@ // builtin-kinds, e.g., if a trait requires Send to implement, then // at usage site of that trait, we know we have the Send capability. +use std::sync::mpsc::{channel, Sender, Receiver}; + trait Foo : Send { } impl <T: Send> Foo for T { } fn foo<T: Foo>(val: T, chan: Sender<T>) { - chan.send(val); + chan.send(val).unwrap(); } pub fn main() { let (tx, rx): (Sender<int>, Receiver<int>) = channel(); foo(31337i, tx); - assert!(rx.recv() == 31337i); + assert!(rx.recv().unwrap() == 31337i); } diff --git a/src/test/run-pass/builtin-superkinds-self-type.rs b/src/test/run-pass/builtin-superkinds-self-type.rs index 1c156f6551c..d0db2542ccc 100644 --- a/src/test/run-pass/builtin-superkinds-self-type.rs +++ b/src/test/run-pass/builtin-superkinds-self-type.rs @@ -11,9 +11,11 @@ // Tests the ability for the Self type in default methods to use // capabilities granted by builtin kinds as supertraits. -trait Foo : Send { +use std::sync::mpsc::{Sender, channel}; + +trait Foo : Send + Sized { fn foo(self, tx: Sender<Self>) { - tx.send(self); + tx.send(self).unwrap(); } } @@ -22,5 +24,5 @@ impl <T: Send> Foo for T { } pub fn main() { let (tx, rx) = channel(); 1193182i.foo(tx); - assert!(rx.recv() == 1193182i); + assert!(rx.recv().unwrap() == 1193182i); } diff --git a/src/test/run-pass/c-stack-returning-int64.rs b/src/test/run-pass/c-stack-returning-int64.rs index 597e067b8b6..c95cf0bfdee 100644 --- a/src/test/run-pass/c-stack-returning-int64.rs +++ b/src/test/run-pass/c-stack-returning-int64.rs @@ -12,6 +12,8 @@ extern crate libc; +use std::c_str::ToCStr; + mod mlibc { use libc::{c_char, c_long, c_longlong}; diff --git a/src/test/run-pass/capturing-logging.rs b/src/test/run-pass/capturing-logging.rs index f2df5ef38c3..3f6d6a02c79 100644 --- a/src/test/run-pass/capturing-logging.rs +++ b/src/test/run-pass/capturing-logging.rs @@ -17,8 +17,10 @@ extern crate log; use log::{set_logger, Logger, LogRecord}; +use std::sync::mpsc::channel; use std::fmt; use std::io::{ChanReader, ChanWriter}; +use std::thread::Thread; struct MyWriter(ChanWriter); @@ -32,7 +34,7 @@ impl Logger for MyWriter { fn main() { let (tx, rx) = channel(); let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx)); - spawn(move|| { + let _t = Thread::spawn(move|| { set_logger(box MyWriter(w) as Box<Logger+Send>); debug!("debug"); info!("info"); diff --git a/src/test/run-pass/cci_capture_clause.rs b/src/test/run-pass/cci_capture_clause.rs index c4bf8131506..8b2947ba3ee 100644 --- a/src/test/run-pass/cci_capture_clause.rs +++ b/src/test/run-pass/cci_capture_clause.rs @@ -16,5 +16,5 @@ extern crate cci_capture_clause; pub fn main() { - cci_capture_clause::foo(()).recv() + cci_capture_clause::foo(()).recv().unwrap(); } diff --git a/src/test/run-pass/closure-bounds-can-capture-chan.rs b/src/test/run-pass/closure-bounds-can-capture-chan.rs index cdcdad47ea4..816b28c3a9a 100644 --- a/src/test/run-pass/closure-bounds-can-capture-chan.rs +++ b/src/test/run-pass/closure-bounds-can-capture-chan.rs @@ -10,7 +10,7 @@ #![feature(unboxed_closures)] -use std::comm; +use std::sync::mpsc::channel; fn foo<F:FnOnce()+Send>(blk: F) { blk(); @@ -19,7 +19,7 @@ fn foo<F:FnOnce()+Send>(blk: F) { pub fn main() { let (tx, rx) = channel(); foo(move || { - tx.send(()); + tx.send(()).unwrap(); }); - rx.recv(); + rx.recv().unwrap(); } diff --git a/src/test/run-pass/cmp-default.rs b/src/test/run-pass/cmp-default.rs index cfba87c3f69..fd040d10910 100644 --- a/src/test/run-pass/cmp-default.rs +++ b/src/test/run-pass/cmp-default.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::cmp::Ordering; + // Test default methods in PartialOrd and PartialEq // struct Fool(bool); diff --git a/src/test/run-pass/coherence-bigint-int.rs b/src/test/run-pass/coherence-bigint-int.rs new file mode 100644 index 00000000000..1e90453980f --- /dev/null +++ b/src/test/run-pass/coherence-bigint-int.rs @@ -0,0 +1,20 @@ +// Copyright 2014 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:coherence-lib.rs + +extern crate "coherence-lib" as lib; +use lib::Remote1; + +pub struct BigInt; + +impl Remote1<BigInt> for int { } + +fn main() { } diff --git a/src/test/run-pass/coherence-bigint-vecint.rs b/src/test/run-pass/coherence-bigint-vecint.rs new file mode 100644 index 00000000000..b100455eb33 --- /dev/null +++ b/src/test/run-pass/coherence-bigint-vecint.rs @@ -0,0 +1,20 @@ +// Copyright 2014 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:coherence-lib.rs + +extern crate "coherence-lib" as lib; +use lib::Remote1; + +pub struct BigInt; + +impl Remote1<BigInt> for Vec<int> { } + +fn main() { } diff --git a/src/test/run-pass/trait-object-safety.rs b/src/test/run-pass/coherence-blanket.rs index ed7284a8353..e02117d1ca2 100644 --- a/src/test/run-pass/trait-object-safety.rs +++ b/src/test/run-pass/coherence-blanket.rs @@ -8,19 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Check that object-safe methods are identified as such. +// aux-build:coherence-lib.rs -trait Tr { - fn foo(&self); -} - -struct St; +extern crate "coherence-lib" as lib; +use lib::Remote1; -impl Tr for St { - fn foo(&self) {} +pub trait Local { + fn foo(&self) { } } -fn main() { - let s: &Tr = &St; - s.foo(); -} +impl<T> Local for T { } + +fn main() { } diff --git a/src/test/run-pass/coherence-covered-type-parameter.rs b/src/test/run-pass/coherence-covered-type-parameter.rs new file mode 100644 index 00000000000..27f1f2dafb0 --- /dev/null +++ b/src/test/run-pass/coherence-covered-type-parameter.rs @@ -0,0 +1,20 @@ +// Copyright 2014 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:coherence-lib.rs + +extern crate "coherence-lib" as lib; +use lib::Remote; + +struct Foo<T>(T); + +impl<T> Remote for Foo<T> { } + +fn main() { } diff --git a/src/test/run-pass/coherence-iterator-vec.rs b/src/test/run-pass/coherence-iterator-vec.rs new file mode 100644 index 00000000000..7077503f73f --- /dev/null +++ b/src/test/run-pass/coherence-iterator-vec.rs @@ -0,0 +1,20 @@ +// Copyright 2014 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:coherence-lib.rs + +extern crate "coherence-lib" as lib; +use lib::Remote1; + +struct Foo<T>(T); + +impl<T> Remote1<T> for Foo<T> { } + +fn main() { } diff --git a/src/test/run-pass/coherence-local-1.rs b/src/test/run-pass/coherence-local-1.rs new file mode 100644 index 00000000000..a9bc3dc0e2f --- /dev/null +++ b/src/test/run-pass/coherence-local-1.rs @@ -0,0 +1,20 @@ +// Copyright 2014 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:coherence-lib.rs + +extern crate "coherence-lib" as lib; +use lib::Remote; + +struct Local; + +impl Remote for Vec<Local> { } + +fn main() { } diff --git a/src/test/run-pass/coherence-local-2.rs b/src/test/run-pass/coherence-local-2.rs new file mode 100644 index 00000000000..07a830cb1ac --- /dev/null +++ b/src/test/run-pass/coherence-local-2.rs @@ -0,0 +1,20 @@ +// Copyright 2014 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:coherence-lib.rs + +extern crate "coherence-lib" as lib; +use lib::Remote; + +struct Local<T>(T); + +impl<T> Remote for Vec<Local<T>> { } + +fn main() { } diff --git a/src/test/run-pass/colorful-write-macros.rs b/src/test/run-pass/colorful-write-macros.rs index bbb049eb960..d2caecdf05b 100644 --- a/src/test/run-pass/colorful-write-macros.rs +++ b/src/test/run-pass/colorful-write-macros.rs @@ -15,7 +15,6 @@ use std::io::MemWriter; use std::fmt; -use std::fmt::FormatWriter; struct Foo<'a> { writer: &'a mut (Writer+'a), @@ -24,8 +23,8 @@ struct Foo<'a> { struct Bar; -impl fmt::FormatWriter for Bar { - fn write(&mut self, _: &[u8]) -> fmt::Result { +impl fmt::Writer for Bar { + fn write_str(&mut self, _: &str) -> fmt::Result { Ok(()) } } @@ -41,5 +40,8 @@ fn main() { println!("ok"); let mut s = Bar; - write!(&mut s, "test"); + { + use std::fmt::Writer; + write!(&mut s, "test"); + } } diff --git a/src/test/run-pass/comm.rs b/src/test/run-pass/comm.rs index edd4d5642b5..5cfc692aae4 100644 --- a/src/test/run-pass/comm.rs +++ b/src/test/run-pass/comm.rs @@ -9,11 +9,12 @@ // except according to those terms. use std::task; +use std::sync::mpsc::{channel, Sender}; pub fn main() { let (tx, rx) = channel(); let _t = task::spawn(move|| { child(&tx) }); - let y = rx.recv(); + let y = rx.recv().unwrap(); println!("received"); println!("{}", y); assert_eq!(y, 10); @@ -21,6 +22,6 @@ pub fn main() { fn child(c: &Sender<int>) { println!("sending"); - c.send(10); + c.send(10).unwrap(); println!("value sent"); } diff --git a/src/test/run-pass/const-str-ptr.rs b/src/test/run-pass/const-str-ptr.rs index d6f0296619a..e0e8ca5618e 100644 --- a/src/test/run-pass/const-str-ptr.rs +++ b/src/test/run-pass/const-str-ptr.rs @@ -9,6 +9,7 @@ // except according to those terms. use std::{str, string}; +use std::c_str::ToCStr; const A: [u8; 2] = ['h' as u8, 'i' as u8]; const B: &'static [u8; 2] = &A; diff --git a/src/test/run-pass/core-run-destroy.rs b/src/test/run-pass/core-run-destroy.rs index a0fa2d178b9..c1db8a6eb13 100644 --- a/src/test/run-pass/core-run-destroy.rs +++ b/src/test/run-pass/core-run-destroy.rs @@ -23,6 +23,8 @@ extern crate libc; use std::io::{Process, Command, timer}; use std::time::Duration; use std::str; +use std::sync::mpsc::channel; +use std::thread::Thread; macro_rules! succeed( ($e:expr) => ( match $e { Ok(..) => {}, Err(e) => panic!("panic: {}", e) } @@ -84,15 +86,15 @@ pub fn test_destroy_actually_kills(force: bool) { let (tx, rx1) = channel(); let mut t = timer::Timer::new().unwrap(); let rx2 = t.oneshot(Duration::milliseconds(1000)); - spawn(move|| { + Thread::spawn(move|| { select! { - () = rx2.recv() => unsafe { libc::exit(1) }, - () = rx1.recv() => {} + _ = rx2.recv() => unsafe { libc::exit(1) }, + _ = rx1.recv() => {} } - }); + }).detach(); match p.wait().unwrap() { ExitStatus(..) => panic!("expected a signal"), - ExitSignal(..) => tx.send(()), + ExitSignal(..) => tx.send(()).unwrap(), } } diff --git a/src/test/run-pass/default-method-supertrait-vtable.rs b/src/test/run-pass/default-method-supertrait-vtable.rs index 1b2b17f9917..727cada21fa 100644 --- a/src/test/run-pass/default-method-supertrait-vtable.rs +++ b/src/test/run-pass/default-method-supertrait-vtable.rs @@ -21,7 +21,7 @@ trait Y { } -trait Z: Y { +trait Z: Y + Sized { fn x(self) -> int { require_y(self) } diff --git a/src/test/run-pass/deref-mut-on-ref.rs b/src/test/run-pass/deref-mut-on-ref.rs index dcf7c483b2c..f43be177862 100644 --- a/src/test/run-pass/deref-mut-on-ref.rs +++ b/src/test/run-pass/deref-mut-on-ref.rs @@ -10,7 +10,9 @@ // Test that `&mut T` implements `DerefMut<T>` -fn inc<T:DerefMut<int>>(mut t: T) { +use std::ops::{Deref, DerefMut}; + +fn inc<T: Deref<Target=int> + DerefMut>(mut t: T) { *t += 1; } diff --git a/src/test/run-pass/deref-on-ref.rs b/src/test/run-pass/deref-on-ref.rs index 27e7d8f3ba2..e95d942c8cf 100644 --- a/src/test/run-pass/deref-on-ref.rs +++ b/src/test/run-pass/deref-on-ref.rs @@ -10,7 +10,9 @@ // Test that `&T` and `&mut T` implement `Deref<T>` -fn deref<U:Copy,T:Deref<U>>(t: T) -> U { +use std::ops::Deref; + +fn deref<U:Copy,T:Deref<Target=U>>(t: T) -> U { *t } diff --git a/src/test/run-pass/deriving-cmp-shortcircuit.rs b/src/test/run-pass/deriving-cmp-shortcircuit.rs index 0a139667c0e..bc55b9132c8 100644 --- a/src/test/run-pass/deriving-cmp-shortcircuit.rs +++ b/src/test/run-pass/deriving-cmp-shortcircuit.rs @@ -12,6 +12,8 @@ // where possible, by having a type that panics when compared as the // second element, so this passes iff the instances shortcircuit. +use std::cmp::Ordering; + pub struct FailCmp; impl PartialEq for FailCmp { fn eq(&self, _: &FailCmp) -> bool { panic!("eq") } diff --git a/src/test/run-pass/deriving-encodable-decodable-box.rs b/src/test/run-pass/deriving-encodable-decodable-box.rs index b0c5d88c48e..b7be14321fd 100644 --- a/src/test/run-pass/deriving-encodable-decodable-box.rs +++ b/src/test/run-pass/deriving-encodable-decodable-box.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(old_orphan_check)] + extern crate serialize; use serialize::{Encodable, Decodable}; diff --git a/src/test/run-pass/deriving-encodable-decodable-cell-refcell.rs b/src/test/run-pass/deriving-encodable-decodable-cell-refcell.rs index 1176cc303b7..3b2c1d9f27c 100644 --- a/src/test/run-pass/deriving-encodable-decodable-cell-refcell.rs +++ b/src/test/run-pass/deriving-encodable-decodable-cell-refcell.rs @@ -11,6 +11,8 @@ // This briefly tests the capability of `Cell` and `RefCell` to implement the // `Encodable` and `Decodable` traits via `#[derive(Encodable, Decodable)]` +#![feature(old_orphan_check)] + extern crate serialize; use std::cell::{Cell, RefCell}; diff --git a/src/test/run-pass/deriving-global.rs b/src/test/run-pass/deriving-global.rs index 80a6829986d..849733ecc1f 100644 --- a/src/test/run-pass/deriving-global.rs +++ b/src/test/run-pass/deriving-global.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(old_orphan_check)] + extern crate serialize; extern crate rand; diff --git a/src/test/run-pass/deriving-zero.rs b/src/test/run-pass/deriving-zero.rs index 71f0acea0bf..a6c0a592c77 100644 --- a/src/test/run-pass/deriving-zero.rs +++ b/src/test/run-pass/deriving-zero.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use std::ops::Add; use std::num::Zero; #[derive(Zero)] diff --git a/src/test/run-pass/drop-trait-enum.rs b/src/test/run-pass/drop-trait-enum.rs index 16ad2b8e21a..381404d2e21 100644 --- a/src/test/run-pass/drop-trait-enum.rs +++ b/src/test/run-pass/drop-trait-enum.rs @@ -9,6 +9,7 @@ // except according to those terms. use std::task; +use std::sync::mpsc::{channel, Sender}; #[derive(PartialEq, Show)] enum Message { @@ -22,7 +23,7 @@ struct SendOnDrop { impl Drop for SendOnDrop { fn drop(&mut self) { - self.sender.send(Message::Dropped); + self.sender.send(Message::Dropped).unwrap(); } } @@ -36,10 +37,10 @@ impl Drop for Foo { fn drop(&mut self) { match self { &Foo::SimpleVariant(ref mut sender) => { - sender.send(Message::DestructorRan); + sender.send(Message::DestructorRan).unwrap(); } &Foo::NestedVariant(_, _, ref mut sender) => { - sender.send(Message::DestructorRan); + sender.send(Message::DestructorRan).unwrap(); } &Foo::FailingVariant { .. } => { panic!("Failed"); @@ -53,23 +54,23 @@ pub fn main() { { let v = Foo::SimpleVariant(sender); } - assert_eq!(receiver.recv(), Message::DestructorRan); - assert_eq!(receiver.recv_opt().ok(), None); + assert_eq!(receiver.recv().unwrap(), Message::DestructorRan); + assert_eq!(receiver.recv().ok(), None); let (sender, receiver) = channel(); { let v = Foo::NestedVariant(box 42u, SendOnDrop { sender: sender.clone() }, sender); } - assert_eq!(receiver.recv(), Message::DestructorRan); - assert_eq!(receiver.recv(), Message::Dropped); - assert_eq!(receiver.recv_opt().ok(), None); + assert_eq!(receiver.recv().unwrap(), Message::DestructorRan); + assert_eq!(receiver.recv().unwrap(), Message::Dropped); + assert_eq!(receiver.recv().ok(), None); let (sender, receiver) = channel(); task::spawn(move|| { let v = Foo::FailingVariant { on_drop: SendOnDrop { sender: sender } }; }); - assert_eq!(receiver.recv(), Message::Dropped); - assert_eq!(receiver.recv_opt().ok(), None); + assert_eq!(receiver.recv().unwrap(), Message::Dropped); + assert_eq!(receiver.recv().ok(), None); let (sender, receiver) = channel(); { @@ -82,11 +83,11 @@ pub fn main() { v = Foo::FailingVariant { on_drop: SendOnDrop { sender: sender } }; }); } - assert_eq!(receiver.recv(), Message::DestructorRan); - assert_eq!(receiver.recv(), Message::Dropped); - assert_eq!(receiver.recv(), Message::DestructorRan); - assert_eq!(receiver.recv(), Message::Dropped); - assert_eq!(receiver.recv(), Message::DestructorRan); - assert_eq!(receiver.recv(), Message::Dropped); - assert_eq!(receiver.recv_opt().ok(), None); + assert_eq!(receiver.recv().unwrap(), Message::DestructorRan); + assert_eq!(receiver.recv().unwrap(), Message::Dropped); + assert_eq!(receiver.recv().unwrap(), Message::DestructorRan); + assert_eq!(receiver.recv().unwrap(), Message::Dropped); + assert_eq!(receiver.recv().unwrap(), Message::DestructorRan); + assert_eq!(receiver.recv().unwrap(), Message::Dropped); + assert_eq!(receiver.recv().ok(), None); } diff --git a/src/test/run-pass/dst-deref-mut.rs b/src/test/run-pass/dst-deref-mut.rs index c2707a1ae6e..0e0ed1f436c 100644 --- a/src/test/run-pass/dst-deref-mut.rs +++ b/src/test/run-pass/dst-deref-mut.rs @@ -10,17 +10,23 @@ // Test that a custom deref with a fat pointer return type does not ICE +#![feature(associated_types)] + +use std::ops::{Deref, DerefMut}; + pub struct Arr { ptr: Box<[uint]> } -impl Deref<[uint]> for Arr { +impl Deref for Arr { + type Target = [uint]; + fn deref(&self) -> &[uint] { panic!(); } } -impl DerefMut<[uint]> for Arr { +impl DerefMut for Arr { fn deref_mut(&mut self) -> &mut [uint] { &mut *self.ptr } diff --git a/src/test/run-pass/dst-deref.rs b/src/test/run-pass/dst-deref.rs index 43b7d116d30..a39670a27b9 100644 --- a/src/test/run-pass/dst-deref.rs +++ b/src/test/run-pass/dst-deref.rs @@ -10,11 +10,17 @@ // Test that a custom deref with a fat pointer return type does not ICE +#![feature(associated_types)] + +use std::ops::Deref; + pub struct Arr { ptr: Box<[uint]> } -impl Deref<[uint]> for Arr { +impl Deref for Arr { + type Target = [uint]; + fn deref(&self) -> &[uint] { &*self.ptr } diff --git a/src/test/run-pass/fixup-deref-mut.rs b/src/test/run-pass/fixup-deref-mut.rs index d2812ce1d2c..8fb3893e5de 100644 --- a/src/test/run-pass/fixup-deref-mut.rs +++ b/src/test/run-pass/fixup-deref-mut.rs @@ -8,18 +8,24 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(associated_types)] + +use std::ops::{Deref, DerefMut}; + // Generic unique/owned smaht pointer. struct Own<T> { value: *mut T } -impl<T> Deref<T> for Own<T> { +impl<T> Deref for Own<T> { + type Target = T; + fn deref<'a>(&'a self) -> &'a T { unsafe { &*self.value } } } -impl<T> DerefMut<T> for Own<T> { +impl<T> DerefMut for Own<T> { fn deref_mut<'a>(&'a mut self) -> &'a mut T { unsafe { &mut *self.value } } diff --git a/src/test/run-pass/foreign-fn-linkname.rs b/src/test/run-pass/foreign-fn-linkname.rs index 750c0c8ed68..8a75fdd685d 100644 --- a/src/test/run-pass/foreign-fn-linkname.rs +++ b/src/test/run-pass/foreign-fn-linkname.rs @@ -11,10 +11,10 @@ // ignore-fast doesn't like extern crate extern crate libc; +use std::c_str::ToCStr; mod mlibc { - extern crate libc; - use self::libc::{c_char, size_t}; + use libc::{c_char, size_t}; extern { #[link_name = "strlen"] diff --git a/src/test/run-pass/hashmap-memory.rs b/src/test/run-pass/hashmap-memory.rs index a92b361dd33..162d7f10255 100644 --- a/src/test/run-pass/hashmap-memory.rs +++ b/src/test/run-pass/hashmap-memory.rs @@ -9,9 +9,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -extern crate collections; - /** A somewhat reduced test case to expose some Valgrind issues. @@ -24,6 +21,7 @@ pub fn map(filename: String, emit: map_reduce::putter) { mod map_reduce { use std::collections::HashMap; + use std::sync::mpsc::{channel, Sender}; use std::str; use std::task; @@ -52,16 +50,16 @@ mod map_reduce { } let (tx, rx) = channel(); println!("sending find_reducer"); - ctrl.send(ctrl_proto::find_reducer(key.as_bytes().to_vec(), tx)); + ctrl.send(ctrl_proto::find_reducer(key.as_bytes().to_vec(), tx)).unwrap(); println!("receiving"); - let c = rx.recv(); + let c = rx.recv().unwrap(); println!("{}", c); im.insert(key, c); } let ctrl_clone = ctrl.clone(); ::map(input, |a,b| emit(&mut intermediates, ctrl.clone(), a, b) ); - ctrl_clone.send(ctrl_proto::mapper_done); + ctrl_clone.send(ctrl_proto::mapper_done).unwrap(); } pub fn map_reduce(inputs: Vec<String>) { @@ -79,7 +77,7 @@ mod map_reduce { let mut num_mappers = inputs.len() as int; while num_mappers > 0 { - match rx.recv() { + match rx.recv().unwrap() { ctrl_proto::mapper_done => { num_mappers -= 1; } ctrl_proto::find_reducer(k, cc) => { let mut c; @@ -88,7 +86,7 @@ mod map_reduce { Some(&_c) => { c = _c; } None => { c = 0; } } - cc.send(c); + cc.send(c).unwrap(); } } } diff --git a/src/test/run-pass/ifmt.rs b/src/test/run-pass/ifmt.rs index fa62699a303..1efae89f665 100644 --- a/src/test/run-pass/ifmt.rs +++ b/src/test/run-pass/ifmt.rs @@ -16,7 +16,6 @@ #![allow(unused_must_use)] use std::fmt; -use std::io; struct A; struct B; @@ -24,17 +23,17 @@ struct C; impl fmt::LowerHex for A { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write("aloha".as_bytes()) + f.write_str("aloha") } } impl fmt::UpperHex for B { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write("adios".as_bytes()) + f.write_str("adios") } } impl fmt::Show for C { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad_integral(true, "☃", "123".as_bytes()) + f.pad_integral(true, "☃", "123") } } @@ -160,18 +159,18 @@ pub fn main() { // Basic test to make sure that we can invoke the `write!` macro with an // io::Writer instance. fn test_write() { - let mut buf = Vec::new(); - write!(&mut buf as &mut io::Writer, "{}", 3i); + use std::fmt::Writer; + let mut buf = String::new(); + write!(&mut buf, "{}", 3i); { - let w = &mut buf as &mut io::Writer; + let w = &mut buf; write!(w, "{foo}", foo=4i); write!(w, "{}", "hello"); writeln!(w, "{}", "line"); writeln!(w, "{foo}", foo="bar"); } - let s = String::from_utf8(buf).unwrap(); - t!(s, "34helloline\nbar\n"); + t!(buf, "34helloline\nbar\n"); } // Just make sure that the macros are defined, there's not really a lot that we @@ -187,14 +186,15 @@ fn test_print() { // Just make sure that the macros are defined, there's not really a lot that we // can do with them just yet (to test the output) fn test_format_args() { - let mut buf = Vec::new(); + use std::fmt::Writer; + let mut buf = String::new(); { - let w = &mut buf as &mut io::Writer; + let w = &mut buf; write!(w, "{}", format_args!("{}", 1i)); write!(w, "{}", format_args!("test")); write!(w, "{}", format_args!("{test}", test=3i)); } - let s = String::from_utf8(buf).unwrap(); + let s = buf; t!(s, "1test3"); let s = fmt::format(format_args!("hello {}", "world")); diff --git a/src/test/run-pass/issue-11881.rs b/src/test/run-pass/issue-11881.rs index 9008e8468f4..24deb7c2e4b 100644 --- a/src/test/run-pass/issue-11881.rs +++ b/src/test/run-pass/issue-11881.rs @@ -8,11 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(old_orphan_check)] + extern crate rbml; extern crate serialize; use std::io; -use std::io::{IoError, IoResult, SeekStyle}; +use std::fmt; +use std::io::{IoResult, SeekStyle}; use std::slice; use serialize::{Encodable, Encoder}; @@ -37,16 +40,15 @@ enum WireProtocol { // ... } -fn encode_json<'a, - T: Encodable<json::Encoder<'a>, - std::io::IoError>>(val: &T, - wr: &'a mut SeekableMemWriter) { - let mut encoder = json::Encoder::new(wr); - val.encode(&mut encoder); +fn encode_json< + T: for<'a> Encodable<json::Encoder<'a>, + fmt::Error>>(val: &T, + wr: &mut SeekableMemWriter) { + write!(wr, "{}", json::as_json(val)); } fn encode_rbml<'a, T: Encodable<writer::Encoder<'a, SeekableMemWriter>, - std::io::IoError>>(val: &T, + io::IoError>>(val: &T, wr: &'a mut SeekableMemWriter) { let mut encoder = writer::Encoder::new(wr); val.encode(&mut encoder); diff --git a/src/test/run-pass/issue-13264.rs b/src/test/run-pass/issue-13264.rs index c416d30f776..00b508ab92c 100644 --- a/src/test/run-pass/issue-13264.rs +++ b/src/test/run-pass/issue-13264.rs @@ -8,11 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(associated_types)] + +use std::ops::Deref; + struct Root { jsref: JSRef } -impl Deref<JSRef> for Root { +impl Deref for Root { + type Target = JSRef; + fn deref<'a>(&'a self) -> &'a JSRef { &self.jsref } @@ -23,7 +29,9 @@ struct JSRef { node: *const Node } -impl Deref<Node> for JSRef { +impl Deref for JSRef { + type Target = Node; + fn deref<'a>(&'a self) -> &'a Node { self.get() } diff --git a/src/test/run-pass/issue-13494.rs b/src/test/run-pass/issue-13494.rs index be851ddefc6..b9339c1cc0d 100644 --- a/src/test/run-pass/issue-13494.rs +++ b/src/test/run-pass/issue-13494.rs @@ -11,22 +11,25 @@ // This test may not always fail, but it can be flaky if the race it used to // expose is still present. +use std::sync::mpsc::{channel, Sender, Receiver}; +use std::thread::Thread; + fn helper(rx: Receiver<Sender<()>>) { for tx in rx.iter() { - let _ = tx.send_opt(()); + let _ = tx.send(()); } } fn main() { let (tx, rx) = channel(); - spawn(move|| { helper(rx) }); + let _t = Thread::spawn(move|| { helper(rx) }).detach(); let (snd, rcv) = channel::<int>(); for _ in range(1i, 100000i) { - snd.send(1i); + snd.send(1i).unwrap(); let (tx2, rx2) = channel(); - tx.send(tx2); + tx.send(tx2).unwrap(); select! { - () = rx2.recv() => (), + _ = rx2.recv() => (), _ = rcv.recv() => () } } diff --git a/src/test/run-pass/issue-14021.rs b/src/test/run-pass/issue-14021.rs index 612ed6b70b4..509459a2ab3 100644 --- a/src/test/run-pass/issue-14021.rs +++ b/src/test/run-pass/issue-14021.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(old_orphan_check)] extern crate serialize; diff --git a/src/test/run-pass/issue-15734.rs b/src/test/run-pass/issue-15734.rs index ea5bd550d53..e99b1dc5bef 100644 --- a/src/test/run-pass/issue-15734.rs +++ b/src/test/run-pass/issue-15734.rs @@ -8,6 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// If `Index` used an associated type for its output, this test would +// work more smoothly. +#![feature(old_orphan_check)] + +use std::ops::Index; + struct Mat<T> { data: Vec<T>, cols: uint, } impl<T> Mat<T> { diff --git a/src/test/run-pass/issue-15924.rs b/src/test/run-pass/issue-15924.rs index 8d5b928964d..1ab8deda383 100644 --- a/src/test/run-pass/issue-15924.rs +++ b/src/test/run-pass/issue-15924.rs @@ -12,7 +12,7 @@ extern crate serialize; -use std::io::IoError; +use std::fmt; use serialize::{Encoder, Encodable}; use serialize::json; @@ -21,7 +21,7 @@ struct Foo<T> { } #[unsafe_destructor] -impl<'a, T: Encodable<json::Encoder<'a>, IoError>> Drop for Foo<T> { +impl<T: for<'a> Encodable<json::Encoder<'a>, fmt::Error>> Drop for Foo<T> { fn drop(&mut self) { json::encode(&self.v); } diff --git a/src/test/run-pass/issue-16560.rs b/src/test/run-pass/issue-16560.rs index f329e7eed0d..b2b819a1103 100644 --- a/src/test/run-pass/issue-16560.rs +++ b/src/test/run-pass/issue-16560.rs @@ -10,6 +10,7 @@ #![feature(unboxed_closures)] +use std::thread::Thread; use std::mem; fn main() { @@ -19,7 +20,7 @@ fn main() { // Check that both closures are capturing by value assert_eq!(1, mem::size_of_val(&closure)); - spawn(move|| { + Thread::spawn(move|| { let ok = closure; - }) + }).join().ok().unwrap(); } diff --git a/src/test/run-pass/issue-16774.rs b/src/test/run-pass/issue-16774.rs index ebc879d82fb..45cfabcd872 100644 --- a/src/test/run-pass/issue-16774.rs +++ b/src/test/run-pass/issue-16774.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(unboxed_closures)] +#![feature(associated_types, unboxed_closures)] + +use std::ops::{Deref, DerefMut}; struct X(Box<int>); @@ -23,14 +25,16 @@ impl Drop for X { } } -impl Deref<int> for X { +impl Deref for X { + type Target = int; + fn deref(&self) -> &int { let &X(box ref x) = self; x } } -impl DerefMut<int> for X { +impl DerefMut for X { fn deref_mut(&mut self) -> &mut int { let &X(box ref mut x) = self; x diff --git a/src/test/run-pass/issue-17718.rs b/src/test/run-pass/issue-17718.rs index 90a102222ba..10ad0f620e9 100644 --- a/src/test/run-pass/issue-17718.rs +++ b/src/test/run-pass/issue-17718.rs @@ -15,7 +15,7 @@ extern crate "issue-17718" as other; use std::sync::atomic; const C1: uint = 1; -const C2: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT; +const C2: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT; const C3: fn() = foo; const C4: uint = C1 * C1 + C1 / C1; const C5: &'static uint = &C4; @@ -25,7 +25,7 @@ const C6: uint = { }; static S1: uint = 3; -static S2: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT; +static S2: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT; mod test { static A: uint = 4; diff --git a/src/test/run-pass/issue-17732.rs b/src/test/run-pass/issue-17732.rs new file mode 100644 index 00000000000..45d3b53132d --- /dev/null +++ b/src/test/run-pass/issue-17732.rs @@ -0,0 +1,18 @@ +// 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. + +#![feature(associated_types)] +trait Person { + type string; +} + +struct Someone<P: Person>; + +fn main() {} diff --git a/src/test/run-pass/issue-19479.rs b/src/test/run-pass/issue-19479.rs new file mode 100644 index 00000000000..b3354530a0c --- /dev/null +++ b/src/test/run-pass/issue-19479.rs @@ -0,0 +1,23 @@ +// 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. + +#![feature(associated_types)] +trait Base {} +trait AssocA { + type X: Base; +} +trait AssocB { + type Y: Base; +} +impl<T: AssocA> AssocB for T { + type Y = <T as AssocA>::X; +} + +fn main() {} diff --git a/src/test/run-pass/issue-19631.rs b/src/test/run-pass/issue-19631.rs new file mode 100644 index 00000000000..d036bab99f8 --- /dev/null +++ b/src/test/run-pass/issue-19631.rs @@ -0,0 +1,23 @@ +// 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. + +#![feature(associated_types)] + +trait PoolManager { + type C; +} + +struct InnerPool<M> { + manager: M, +} + +impl<M> InnerPool<M> where M: PoolManager {} + +fn main() {} diff --git a/src/test/run-pass/issue-19632.rs b/src/test/run-pass/issue-19632.rs new file mode 100644 index 00000000000..9bc74e50173 --- /dev/null +++ b/src/test/run-pass/issue-19632.rs @@ -0,0 +1,21 @@ +// 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. + +#![feature(associated_types)] + +trait PoolManager { + type C; +} + +struct InnerPool<M: PoolManager> { + manager: M, +} + +fn main() {} diff --git a/src/test/run-pass/issue-19850.rs b/src/test/run-pass/issue-19850.rs new file mode 100644 index 00000000000..cd56fe18689 --- /dev/null +++ b/src/test/run-pass/issue-19850.rs @@ -0,0 +1,30 @@ +// 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. + +// Test that `<Type as Trait>::Output` and `Self::Output` are accepted as type annotations in let +// bindings + +#![feature(associated_types)] + +trait Int { + fn one() -> Self; + fn leading_zeros(self) -> uint; +} + +trait Foo { + type T : Int; + + fn test(&self) { + let r: <Self as Foo>::T = Int::one(); + let r: Self::T = Int::one(); + } +} + +fn main() {} diff --git a/src/test/run-pass/issue-20009.rs b/src/test/run-pass/issue-20009.rs new file mode 100644 index 00000000000..535538793d1 --- /dev/null +++ b/src/test/run-pass/issue-20009.rs @@ -0,0 +1,22 @@ +// 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. + +// Check that associated types are `Sized` + +#![feature(associated_types)] + +trait Trait { + type Output; + + fn is_sized(&self) -> Self::Output; + fn wasnt_sized(&self) -> Self::Output { loop {} } +} + +fn main() {} diff --git a/src/test/run-pass/issue-20313.rs b/src/test/run-pass/issue-20313.rs new file mode 100644 index 00000000000..47791ceecb6 --- /dev/null +++ b/src/test/run-pass/issue-20313.rs @@ -0,0 +1,18 @@ +// Copyright 2014 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. +#![feature(link_llvm_intrinsics)] + +extern { + #[link_name = "llvm.sqrt.f32"] + fn sqrt(x: f32) -> f32; +} + +fn main(){ +} diff --git a/src/test/run-pass/issue-20389.rs b/src/test/run-pass/issue-20389.rs new file mode 100644 index 00000000000..0ef14149c94 --- /dev/null +++ b/src/test/run-pass/issue-20389.rs @@ -0,0 +1,22 @@ +// 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:issue_20389.rs + +#![feature(associated_types)] +extern crate issue_20389; + +struct Foo; + +impl issue_20389::T for Foo { + type C = (); +} + +fn main() {} diff --git a/src/test/run-pass/issue-3609.rs b/src/test/run-pass/issue-3609.rs index f17f9411d15..a02dbb6035b 100644 --- a/src/test/run-pass/issue-3609.rs +++ b/src/test/run-pass/issue-3609.rs @@ -11,6 +11,7 @@ #![feature(default_type_params)] use std::task; +use std::sync::mpsc::Sender; use std::thunk::Invoke; type RingBuffer = Vec<f64> ; diff --git a/src/test/run-pass/issue-3743.rs b/src/test/run-pass/issue-3743.rs index 80d3d29bc00..cb4f1b7d20f 100644 --- a/src/test/run-pass/issue-3743.rs +++ b/src/test/run-pass/issue-3743.rs @@ -8,6 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// If `Mul` used an associated type for its output, this test would +// work more smoothly. +#![feature(old_orphan_check)] + +use std::ops::Mul; + struct Vec2 { x: f64, y: f64 diff --git a/src/test/run-pass/issue-3979-generics.rs b/src/test/run-pass/issue-3979-generics.rs index 86cdd6135ec..93c72e2e350 100644 --- a/src/test/run-pass/issue-3979-generics.rs +++ b/src/test/run-pass/issue-3979-generics.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::ops::Add; + trait Positioned<S> { fn SetX(&mut self, S); fn X(&self) -> S; diff --git a/src/test/run-pass/issue-4446.rs b/src/test/run-pass/issue-4446.rs index daa80aec28c..30e1a14ecff 100644 --- a/src/test/run-pass/issue-4446.rs +++ b/src/test/run-pass/issue-4446.rs @@ -9,13 +9,15 @@ // except according to those terms. use std::io::println; +use std::sync::mpsc::channel; +use std::thread::Thread; pub fn main() { let (tx, rx) = channel(); - tx.send("hello, world"); + tx.send("hello, world").unwrap(); - spawn(move|| { - println(rx.recv()); - }); + Thread::spawn(move|| { + println(rx.recv().unwrap()); + }).join().ok().unwrap(); } diff --git a/src/test/run-pass/issue-4448.rs b/src/test/run-pass/issue-4448.rs index 3ea968c416f..7e53722726f 100644 --- a/src/test/run-pass/issue-4448.rs +++ b/src/test/run-pass/issue-4448.rs @@ -8,14 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::task; +use std::sync::mpsc::channel; +use std::thread::Thread; pub fn main() { let (tx, rx) = channel::<&'static str>(); - task::spawn(move|| { - assert_eq!(rx.recv(), "hello, world"); + let t = Thread::spawn(move|| { + assert_eq!(rx.recv().unwrap(), "hello, world"); }); - tx.send("hello, world"); + tx.send("hello, world").unwrap(); + t.join().ok().unwrap(); } diff --git a/src/test/run-pass/issue-7784.rs b/src/test/run-pass/issue-7784.rs index b936eb322fc..43785edc2eb 100644 --- a/src/test/run-pass/issue-7784.rs +++ b/src/test/run-pass/issue-7784.rs @@ -10,6 +10,8 @@ #![feature(advanced_slice_patterns)] +use std::ops::Add; + fn foo<T: Add<T, T> + Clone>([x, y, z]: [T; 3]) -> (T, T, T) { (x.clone(), x.clone() + y.clone(), x + y + z) } diff --git a/src/test/run-pass/issue-8171-default-method-self-inherit-builtin-trait.rs b/src/test/run-pass/issue-8171-default-method-self-inherit-builtin-trait.rs index aaf2ecb7129..3238c24163e 100644 --- a/src/test/run-pass/issue-8171-default-method-self-inherit-builtin-trait.rs +++ b/src/test/run-pass/issue-8171-default-method-self-inherit-builtin-trait.rs @@ -16,7 +16,7 @@ fn require_send<T: Send>(_: T){} -trait TragicallySelfIsNotSend: Send { +trait TragicallySelfIsNotSend: Send + Sized { fn x(self) { require_send(self); } diff --git a/src/test/run-pass/issue-8827.rs b/src/test/run-pass/issue-8827.rs index 7397ad74495..39695a8339f 100644 --- a/src/test/run-pass/issue-8827.rs +++ b/src/test/run-pass/issue-8827.rs @@ -8,37 +8,40 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::thread::Thread; +use std::sync::mpsc::{channel, Receiver}; + fn periodical(n: int) -> Receiver<bool> { let (chan, port) = channel(); - spawn(move|| { + Thread::spawn(move|| { loop { for _ in range(1, n) { - match chan.send_opt(false) { + match chan.send(false) { Ok(()) => {} Err(..) => break, } } - match chan.send_opt(true) { + match chan.send(true) { Ok(()) => {} Err(..) => break } } - }); + }).detach(); return port; } fn integers() -> Receiver<int> { let (chan, port) = channel(); - spawn(move|| { + Thread::spawn(move|| { let mut i = 1; loop { - match chan.send_opt(i) { + match chan.send(i) { Ok(()) => {} Err(..) => break, } i = i + 1; } - }); + }).detach(); return port; } @@ -47,7 +50,7 @@ fn main() { let threes = periodical(3); let fives = periodical(5); for _ in range(1i, 100i) { - match (ints.recv(), threes.recv(), fives.recv()) { + match (ints.recv().unwrap(), threes.recv().unwrap(), fives.recv().unwrap()) { (_, true, true) => println!("FizzBuzz"), (_, true, false) => println!("Fizz"), (_, false, true) => println!("Buzz"), diff --git a/src/test/run-pass/issue-9396.rs b/src/test/run-pass/issue-9396.rs index 588e0c1cf16..34bb50c5cf6 100644 --- a/src/test/run-pass/issue-9396.rs +++ b/src/test/run-pass/issue-9396.rs @@ -8,22 +8,23 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::comm; +use std::sync::mpsc::{TryRecvError, channel}; use std::io::timer::Timer; +use std::thread::Thread; use std::time::Duration; pub fn main() { let (tx, rx) = channel(); - spawn(move||{ + let _t = Thread::spawn(move||{ let mut timer = Timer::new().unwrap(); timer.sleep(Duration::milliseconds(10)); - tx.send(()); + tx.send(()).unwrap(); }); loop { match rx.try_recv() { Ok(()) => break, - Err(comm::Empty) => {} - Err(comm::Disconnected) => unreachable!() + Err(TryRecvError::Empty) => {} + Err(TryRecvError::Disconnected) => unreachable!() } } } diff --git a/src/test/run-pass/ivec-tag.rs b/src/test/run-pass/ivec-tag.rs index 1f7edcf43b8..a9a50b9ef25 100644 --- a/src/test/run-pass/ivec-tag.rs +++ b/src/test/run-pass/ivec-tag.rs @@ -9,11 +9,12 @@ // except according to those terms. use std::task; +use std::sync::mpsc::{channel, Sender}; fn producer(tx: &Sender<Vec<u8>>) { tx.send( vec!(1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8, 10u8, 11u8, 12u8, - 13u8)); + 13u8)).unwrap(); } pub fn main() { @@ -22,5 +23,5 @@ pub fn main() { producer(&tx) }); - let _data: Vec<u8> = rx.recv(); + let _data: Vec<u8> = rx.recv().unwrap(); } diff --git a/src/test/run-pass/logging-only-prints-once.rs b/src/test/run-pass/logging-only-prints-once.rs index 1e05c05cc0d..509afff3d13 100644 --- a/src/test/run-pass/logging-only-prints-once.rs +++ b/src/test/run-pass/logging-only-prints-once.rs @@ -13,6 +13,7 @@ use std::cell::Cell; use std::fmt; +use std::thread::Thread; struct Foo(Cell<int>); @@ -26,13 +27,10 @@ impl fmt::Show for Foo { } pub fn main() { - let (tx, rx) = channel(); - spawn(move|| { + Thread::spawn(move|| { let mut f = Foo(Cell::new(0)); println!("{}", f); let Foo(ref mut f) = f; assert!(f.get() == 1); - tx.send(()); - }); - rx.recv(); + }).join().ok().unwrap(); } diff --git a/src/test/run-pass/macro-with-braces-in-expr-position.rs b/src/test/run-pass/macro-with-braces-in-expr-position.rs index 024dc4c03e1..a6e579ddff3 100644 --- a/src/test/run-pass/macro-with-braces-in-expr-position.rs +++ b/src/test/run-pass/macro-with-braces-in-expr-position.rs @@ -10,11 +10,13 @@ #![feature(macro_rules)] +use std::thread::Thread; + macro_rules! expr (($e: expr) => { $e }); macro_rules! spawn { ($($code: tt)*) => { - expr!(spawn(move|| {$($code)*})) + expr!(Thread::spawn(move|| {$($code)*}).detach()) } } diff --git a/src/test/run-pass/match-with-ret-arm.rs b/src/test/run-pass/match-with-ret-arm.rs index 2109f7ef1ea..2cba1dec2dc 100644 --- a/src/test/run-pass/match-with-ret-arm.rs +++ b/src/test/run-pass/match-with-ret-arm.rs @@ -9,6 +9,7 @@ // except according to those terms. use std::uint; +use std::str::from_str; pub fn main() { // sometimes we have had trouble finding diff --git a/src/test/run-pass/method-self-arg-trait.rs b/src/test/run-pass/method-self-arg-trait.rs index 36dfe83a9eb..29d100beb06 100644 --- a/src/test/run-pass/method-self-arg-trait.rs +++ b/src/test/run-pass/method-self-arg-trait.rs @@ -16,7 +16,7 @@ struct Foo; impl Copy for Foo {} -trait Bar { +trait Bar : Sized { fn foo1(&self); fn foo2(self); fn foo3(self: Box<Self>); diff --git a/src/test/run-pass/numeric-method-autoexport.rs b/src/test/run-pass/numeric-method-autoexport.rs index f8184d248ff..b4d079d79d6 100644 --- a/src/test/run-pass/numeric-method-autoexport.rs +++ b/src/test/run-pass/numeric-method-autoexport.rs @@ -15,6 +15,9 @@ // necessary. Testing the methods of the impls is done within the source // file for each numeric type. +use std::ops::Add; +use std::num::ToPrimitive; + pub fn main() { // ints // num diff --git a/src/test/run-pass/out-of-stack-new-thread-no-split.rs b/src/test/run-pass/out-of-stack-new-thread-no-split.rs index 674d0dc86da..7aac2d705a8 100644 --- a/src/test/run-pass/out-of-stack-new-thread-no-split.rs +++ b/src/test/run-pass/out-of-stack-new-thread-no-split.rs @@ -17,6 +17,7 @@ use std::io::process::Command; use std::os; +use std::thread::Thread; // lifted from the test module // Inlining to avoid llvm turning the recursive functions into tail calls, @@ -36,12 +37,7 @@ fn main() { let args = os::args(); let args = args.as_slice(); if args.len() > 1 && args[1].as_slice() == "recurse" { - let (tx, rx) = channel(); - spawn(move|| { - recurse(); - tx.send(()); - }); - rx.recv(); + let _t = Thread::spawn(recurse); } else { let recurse = Command::new(args[0].as_slice()).arg("recurse").output().unwrap(); assert!(!recurse.status.success()); diff --git a/src/test/run-pass/overloaded-autoderef-count.rs b/src/test/run-pass/overloaded-autoderef-count.rs index baf1b1b0237..e9eb924d449 100644 --- a/src/test/run-pass/overloaded-autoderef-count.rs +++ b/src/test/run-pass/overloaded-autoderef-count.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(associated_types)] + use std::cell::Cell; use std::ops::{Deref, DerefMut}; @@ -32,14 +34,16 @@ impl<T> DerefCounter<T> { } } -impl<T> Deref<T> for DerefCounter<T> { +impl<T> Deref for DerefCounter<T> { + type Target = T; + fn deref(&self) -> &T { self.count_imm.set(self.count_imm.get() + 1); &self.value } } -impl<T> DerefMut<T> for DerefCounter<T> { +impl<T> DerefMut for DerefCounter<T> { fn deref_mut(&mut self) -> &mut T { self.count_mut += 1; &mut self.value diff --git a/src/test/run-pass/overloaded-autoderef-indexing.rs b/src/test/run-pass/overloaded-autoderef-indexing.rs index 5c4befcd0c8..6d8d09b321e 100644 --- a/src/test/run-pass/overloaded-autoderef-indexing.rs +++ b/src/test/run-pass/overloaded-autoderef-indexing.rs @@ -8,11 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(associated_types)] + +use std::ops::Deref; + struct DerefArray<'a, T:'a> { inner: &'a [T] } -impl<'a, T> Deref<&'a [T]> for DerefArray<'a, T> { +impl<'a, T> Deref for DerefArray<'a, T> { + type Target = &'a [T]; + fn deref<'b>(&'b self) -> &'b &'a [T] { &self.inner } diff --git a/src/test/run-pass/overloaded-autoderef-order.rs b/src/test/run-pass/overloaded-autoderef-order.rs index f0daf371ca7..cafb665fc37 100644 --- a/src/test/run-pass/overloaded-autoderef-order.rs +++ b/src/test/run-pass/overloaded-autoderef-order.rs @@ -8,7 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(associated_types)] + use std::rc::Rc; +use std::ops::Deref; struct DerefWrapper<X, Y> { x: X, @@ -23,13 +26,17 @@ impl<X, Y> DerefWrapper<X, Y> { } } -impl<X, Y> Deref<Y> for DerefWrapper<X, Y> { +impl<X, Y> Deref for DerefWrapper<X, Y> { + type Target = Y; + fn deref(&self) -> &Y { &self.y } } mod priv_test { + use std::ops::Deref; + pub struct DerefWrapperHideX<X, Y> { x: X, pub y: Y @@ -46,7 +53,9 @@ mod priv_test { } } - impl<X, Y> Deref<Y> for DerefWrapperHideX<X, Y> { + impl<X, Y> Deref for DerefWrapperHideX<X, Y> { + type Target = Y; + fn deref(&self) -> &Y { &self.y } diff --git a/src/test/run-pass/overloaded-autoderef-vtable.rs b/src/test/run-pass/overloaded-autoderef-vtable.rs index f71afb96507..23efba15749 100644 --- a/src/test/run-pass/overloaded-autoderef-vtable.rs +++ b/src/test/run-pass/overloaded-autoderef-vtable.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(associated_types)] + use std::ops::Deref; struct DerefWithHelper<H, T> { @@ -24,7 +26,9 @@ impl<T> Helper<T> for Option<T> { } } -impl<T, H: Helper<T>> Deref<T> for DerefWithHelper<H, T> { +impl<T, H: Helper<T>> Deref for DerefWithHelper<H, T> { + type Target = T; + fn deref(&self) -> &T { self.helper.helper_borrow() } diff --git a/src/test/run-pass/overloaded-autoderef.rs b/src/test/run-pass/overloaded-autoderef.rs index 344b27ef35f..949a7b158d4 100644 --- a/src/test/run-pass/overloaded-autoderef.rs +++ b/src/test/run-pass/overloaded-autoderef.rs @@ -10,7 +10,7 @@ use std::cell::RefCell; use std::rc::Rc; -use std::string::String; +use std::num::ToPrimitive; #[derive(PartialEq, Show)] struct Point { @@ -31,7 +31,6 @@ pub fn main() { assert_eq!((i_value, *i.borrow()), (2, 5)); let s = Rc::new("foo".to_string()); - assert!(s.equiv(&("foo"))); assert_eq!(s.as_slice(), "foo"); let mut_s = Rc::new(RefCell::new(String::from_str("foo"))); diff --git a/src/test/run-pass/overloaded-calls-param-vtables.rs b/src/test/run-pass/overloaded-calls-param-vtables.rs index 2e8ec3916bd..bdaccee65d7 100644 --- a/src/test/run-pass/overloaded-calls-param-vtables.rs +++ b/src/test/run-pass/overloaded-calls-param-vtables.rs @@ -13,10 +13,11 @@ #![feature(unboxed_closures)] use std::ops::Fn; +use std::ops::Add; -struct G; +struct G<A>; -impl<'a, A: Add<int, int>> Fn<(A,), int> for G { +impl<'a, A: Add<int, int>> Fn<(A,), int> for G<A> { extern "rust-call" fn call(&self, (arg,): (A,)) -> int { arg.add(1) } diff --git a/src/test/run-pass/overloaded-deref-count.rs b/src/test/run-pass/overloaded-deref-count.rs index 7645500c02f..b6fb38d5cc2 100644 --- a/src/test/run-pass/overloaded-deref-count.rs +++ b/src/test/run-pass/overloaded-deref-count.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(associated_types)] + use std::cell::Cell; use std::ops::{Deref, DerefMut}; use std::vec::Vec; @@ -32,14 +34,16 @@ impl<T> DerefCounter<T> { } } -impl<T> Deref<T> for DerefCounter<T> { +impl<T> Deref for DerefCounter<T> { + type Target = T; + fn deref(&self) -> &T { self.count_imm.set(self.count_imm.get() + 1); &self.value } } -impl<T> DerefMut<T> for DerefCounter<T> { +impl<T> DerefMut for DerefCounter<T> { fn deref_mut(&mut self) -> &mut T { self.count_mut += 1; &mut self.value diff --git a/src/test/run-pass/overloaded-index-autoderef.rs b/src/test/run-pass/overloaded-index-autoderef.rs index d51956da894..dcb0c40c608 100644 --- a/src/test/run-pass/overloaded-index-autoderef.rs +++ b/src/test/run-pass/overloaded-index-autoderef.rs @@ -10,6 +10,8 @@ // Test overloaded indexing combined with autoderef. +use std::ops::{Index, IndexMut}; + struct Foo { x: int, y: int, diff --git a/src/test/run-pass/overloaded-index-in-field.rs b/src/test/run-pass/overloaded-index-in-field.rs index e8b0408ca0d..1c06ed64fc7 100644 --- a/src/test/run-pass/overloaded-index-in-field.rs +++ b/src/test/run-pass/overloaded-index-in-field.rs @@ -11,6 +11,8 @@ // Test using overloaded indexing when the "map" is stored in a // field. This caused problems at some point. +use std::ops::Index; + struct Foo { x: int, y: int, diff --git a/src/test/run-pass/overloaded-index.rs b/src/test/run-pass/overloaded-index.rs index 23bebfa35d7..fdf7e7e2cbb 100644 --- a/src/test/run-pass/overloaded-index.rs +++ b/src/test/run-pass/overloaded-index.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::ops::{Index, IndexMut}; + struct Foo { x: int, y: int, diff --git a/src/test/run-pass/rename-directory.rs b/src/test/run-pass/rename-directory.rs index b5cee20232b..c7aa405b513 100644 --- a/src/test/run-pass/rename-directory.rs +++ b/src/test/run-pass/rename-directory.rs @@ -14,6 +14,7 @@ extern crate libc; use std::io::TempDir; +use std::c_str::ToCStr; use std::io::fs::PathExtensions; use std::io::fs; use std::io; diff --git a/src/test/run-pass/running-with-no-runtime.rs b/src/test/run-pass/running-with-no-runtime.rs index 4cf8c52f2bb..0aeade935da 100644 --- a/src/test/run-pass/running-with-no-runtime.rs +++ b/src/test/run-pass/running-with-no-runtime.rs @@ -10,12 +10,12 @@ use std::io::process::{Command, ProcessOutput}; use std::os; -use std::str; +use std::rt::unwind::try; use std::rt; +use std::str; +use std::thread::Thread; use std::thunk::Thunk; -use std::rt::unwind::try; - #[start] fn start(argc: int, argv: *const *const u8) -> int { if argc > 1 { @@ -25,8 +25,7 @@ fn start(argc: int, argv: *const *const u8) -> int { 2 => println!("foo"), 3 => assert!(try(|| {}).is_ok()), 4 => assert!(try(|| panic!()).is_err()), - 5 => assert!(try(|| spawn(move|| {})).is_err()), - 6 => assert!(Command::new("test").spawn().is_err()), + 5 => assert!(Command::new("test").spawn().is_err()), _ => panic!() } } @@ -50,8 +49,6 @@ fn start(argc: int, argv: *const *const u8) -> int { pass(Command::new(me).arg(x).output().unwrap()); let x: &[u8] = &[5u8]; pass(Command::new(me).arg(x).output().unwrap()); - let x: &[u8] = &[6u8]; - pass(Command::new(me).arg(x).output().unwrap()); 0 } diff --git a/src/test/run-pass/rust-log-filter.rs b/src/test/run-pass/rust-log-filter.rs index 88d30318f2a..2612483ded4 100644 --- a/src/test/run-pass/rust-log-filter.rs +++ b/src/test/run-pass/rust-log-filter.rs @@ -14,6 +14,9 @@ #[phase(plugin,link)] extern crate log; +use std::sync::mpsc::{channel, Sender, Receiver}; +use std::thread::Thread; + pub struct ChannelLogger { tx: Sender<String> } @@ -27,14 +30,14 @@ impl ChannelLogger { impl log::Logger for ChannelLogger { fn log(&mut self, record: &log::LogRecord) { - self.tx.send(format!("{}", record.args)); + self.tx.send(format!("{}", record.args)).unwrap(); } } pub fn main() { let (logger, rx) = ChannelLogger::new(); - spawn(move|| { + let _t = Thread::spawn(move|| { log::set_logger(logger); // our regex is "f.o" @@ -46,9 +49,9 @@ pub fn main() { info!("f1o"); }); - assert_eq!(rx.recv().as_slice(), "foo"); - assert_eq!(rx.recv().as_slice(), "foo bar"); - assert_eq!(rx.recv().as_slice(), "bar foo"); - assert_eq!(rx.recv().as_slice(), "f1o"); - assert!(rx.recv_opt().is_err()); + assert_eq!(rx.recv().unwrap().as_slice(), "foo"); + assert_eq!(rx.recv().unwrap().as_slice(), "foo bar"); + assert_eq!(rx.recv().unwrap().as_slice(), "bar foo"); + assert_eq!(rx.recv().unwrap().as_slice(), "f1o"); + assert!(rx.recv().is_err()); } diff --git a/src/test/run-pass/self-in-mut-slot-default-method.rs b/src/test/run-pass/self-in-mut-slot-default-method.rs index b4a46f34015..bced8012b68 100644 --- a/src/test/run-pass/self-in-mut-slot-default-method.rs +++ b/src/test/run-pass/self-in-mut-slot-default-method.rs @@ -13,7 +13,7 @@ struct X { a: int } -trait Changer { +trait Changer : Sized { fn change(mut self) -> Self { self.set_to(55); self diff --git a/src/test/run-pass/send-resource.rs b/src/test/run-pass/send-resource.rs index 6001c360ab9..7fd9706bd0f 100644 --- a/src/test/run-pass/send-resource.rs +++ b/src/test/run-pass/send-resource.rs @@ -9,6 +9,7 @@ // except according to those terms. use std::task; +use std::sync::mpsc::channel; struct test { f: int, @@ -29,10 +30,10 @@ pub fn main() { task::spawn(move|| { let (tx2, rx2) = channel(); - tx.send(tx2); + tx.send(tx2).unwrap(); - let _r = rx2.recv(); + let _r = rx2.recv().unwrap(); }); - rx.recv().send(test(42)); + rx.recv().unwrap().send(test(42)).unwrap(); } diff --git a/src/test/run-pass/send-type-inference.rs b/src/test/run-pass/send-type-inference.rs index 508bd99d77d..ae992a0a358 100644 --- a/src/test/run-pass/send-type-inference.rs +++ b/src/test/run-pass/send-type-inference.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::sync::mpsc::{channel, Sender}; + // tests that ctrl's type gets inferred properly struct Command<K, V> { key: K, diff --git a/src/test/run-pass/send_str_hashmap.rs b/src/test/run-pass/send_str_hashmap.rs index 1b0f2ec0a32..bfeff58b802 100644 --- a/src/test/run-pass/send_str_hashmap.rs +++ b/src/test/run-pass/send_str_hashmap.rs @@ -11,8 +11,8 @@ extern crate collections; use std::collections::HashMap; -use std::option::Option::Some; use std::str::SendStr; +use std::borrow::IntoCow; pub fn main() { let mut map: HashMap<SendStr, uint> = HashMap::new(); diff --git a/src/test/run-pass/send_str_treemap.rs b/src/test/run-pass/send_str_treemap.rs index 24480d85272..8c70738de48 100644 --- a/src/test/run-pass/send_str_treemap.rs +++ b/src/test/run-pass/send_str_treemap.rs @@ -11,9 +11,8 @@ extern crate collections; use self::collections::BTreeMap; -use std::option::Option::Some; use std::str::SendStr; -use std::string::ToString; +use std::borrow::IntoCow; pub fn main() { let mut map: BTreeMap<SendStr, uint> = BTreeMap::new(); diff --git a/src/test/run-pass/sendable-class.rs b/src/test/run-pass/sendable-class.rs index 007a83d2c88..8691d5e875b 100644 --- a/src/test/run-pass/sendable-class.rs +++ b/src/test/run-pass/sendable-class.rs @@ -10,6 +10,8 @@ // Test that a class with only sendable fields can be sent +use std::sync::mpsc::channel; + struct foo { i: int, j: char, diff --git a/src/test/run-pass/spawn-types.rs b/src/test/run-pass/spawn-types.rs index 9b533c69f32..1c86e3e6ea2 100644 --- a/src/test/run-pass/spawn-types.rs +++ b/src/test/run-pass/spawn-types.rs @@ -15,6 +15,7 @@ */ use std::task; +use std::sync::mpsc::{channel, Sender}; type ctx = Sender<int>; diff --git a/src/test/run-pass/supertrait-default-generics.rs b/src/test/run-pass/supertrait-default-generics.rs index 873941395fe..4465561f874 100644 --- a/src/test/run-pass/supertrait-default-generics.rs +++ b/src/test/run-pass/supertrait-default-generics.rs @@ -10,6 +10,8 @@ // There is some other borrowck bug, so we make the stuff not mut. +use std::ops::Add; + trait Positioned<S> { fn SetX(&mut self, S); fn X(&self) -> S; diff --git a/src/test/run-pass/task-comm-0.rs b/src/test/run-pass/task-comm-0.rs index 9e3511ba603..de077ffd190 100644 --- a/src/test/run-pass/task-comm-0.rs +++ b/src/test/run-pass/task-comm-0.rs @@ -8,28 +8,28 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use std::task; +use std::sync::mpsc::{channel, Sender}; pub fn main() { test05(); } fn test05_start(tx : &Sender<int>) { - tx.send(10); + tx.send(10).unwrap(); println!("sent 10"); - tx.send(20); + tx.send(20).unwrap(); println!("sent 20"); - tx.send(30); + tx.send(30).unwrap(); println!("sent 30"); } fn test05() { let (tx, rx) = channel(); task::spawn(move|| { test05_start(&tx) }); - let mut value: int = rx.recv(); + let mut value: int = rx.recv().unwrap(); println!("{}", value); - value = rx.recv(); + value = rx.recv().unwrap(); println!("{}", value); - value = rx.recv(); + value = rx.recv().unwrap(); println!("{}", value); assert_eq!(value, 30); } diff --git a/src/test/run-pass/task-comm-10.rs b/src/test/run-pass/task-comm-10.rs index dd3c90991f6..93dca923b6b 100644 --- a/src/test/run-pass/task-comm-10.rs +++ b/src/test/run-pass/task-comm-10.rs @@ -8,19 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use std::task; +use std::sync::mpsc::{channel, Sender}; fn start(tx: &Sender<Sender<String>>) { let (tx2, rx) = channel(); - tx.send(tx2); + tx.send(tx2).unwrap(); let mut a; let mut b; - a = rx.recv(); + a = rx.recv().unwrap(); assert!(a == "A".to_string()); println!("{}", a); - b = rx.recv(); + b = rx.recv().unwrap(); assert!(b == "B".to_string()); println!("{}", b); } @@ -29,8 +29,8 @@ pub fn main() { let (tx, rx) = channel(); let _child = task::spawn(move|| { start(&tx) }); - let mut c = rx.recv(); - c.send("A".to_string()); - c.send("B".to_string()); + let mut c = rx.recv().unwrap(); + c.send("A".to_string()).unwrap(); + c.send("B".to_string()).unwrap(); task::deschedule(); } diff --git a/src/test/run-pass/task-comm-11.rs b/src/test/run-pass/task-comm-11.rs index aefc91df4e7..8168e84e426 100644 --- a/src/test/run-pass/task-comm-11.rs +++ b/src/test/run-pass/task-comm-11.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use std::sync::mpsc::{channel, Sender}; use std::task; fn start(tx: &Sender<Sender<int>>) { diff --git a/src/test/run-pass/task-comm-13.rs b/src/test/run-pass/task-comm-13.rs index c6c0691b749..bb92ef38728 100644 --- a/src/test/run-pass/task-comm-13.rs +++ b/src/test/run-pass/task-comm-13.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use std::sync::mpsc::{channel, Sender}; use std::task; fn start(tx: &Sender<int>, start: int, number_of_messages: int) { diff --git a/src/test/run-pass/task-comm-14.rs b/src/test/run-pass/task-comm-14.rs index 0e483813665..d63cbd5c8ba 100644 --- a/src/test/run-pass/task-comm-14.rs +++ b/src/test/run-pass/task-comm-14.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use std::sync::mpsc::{channel, Sender}; use std::task; pub fn main() { diff --git a/src/test/run-pass/task-comm-15.rs b/src/test/run-pass/task-comm-15.rs index 3095c2098ff..7c652ddc406 100644 --- a/src/test/run-pass/task-comm-15.rs +++ b/src/test/run-pass/task-comm-15.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use std::sync::mpsc::{channel, Sender}; use std::task; fn start(tx: &Sender<int>, i0: int) { diff --git a/src/test/run-pass/task-comm-16.rs b/src/test/run-pass/task-comm-16.rs index ec41019846b..065777bd961 100644 --- a/src/test/run-pass/task-comm-16.rs +++ b/src/test/run-pass/task-comm-16.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::sync::mpsc::channel; use std::cmp; // Tests of ports and channels on various types @@ -16,9 +17,9 @@ fn test_rec() { let (tx, rx) = channel(); let r0: R = R {val0: 0, val1: 1u8, val2: '2'}; - tx.send(r0); + tx.send(r0).unwrap(); let mut r1: R; - r1 = rx.recv(); + r1 = rx.recv().unwrap(); assert_eq!(r1.val0, 0); assert_eq!(r1.val1, 1u8); assert_eq!(r1.val2, '2'); @@ -27,8 +28,8 @@ fn test_rec() { fn test_vec() { let (tx, rx) = channel(); let v0: Vec<int> = vec!(0, 1, 2); - tx.send(v0); - let v1 = rx.recv(); + tx.send(v0).unwrap(); + let v1 = rx.recv().unwrap(); assert_eq!(v1[0], 0); assert_eq!(v1[1], 1); assert_eq!(v1[2], 2); @@ -37,8 +38,8 @@ fn test_vec() { fn test_str() { let (tx, rx) = channel(); let s0 = "test".to_string(); - tx.send(s0); - let s1 = rx.recv(); + tx.send(s0).unwrap(); + let s1 = rx.recv().unwrap(); assert_eq!(s1.as_bytes()[0], 't' as u8); assert_eq!(s1.as_bytes()[1], 'e' as u8); assert_eq!(s1.as_bytes()[2], 's' as u8); @@ -81,28 +82,28 @@ impl cmp::PartialEq for t { fn test_tag() { let (tx, rx) = channel(); - tx.send(t::tag1); - tx.send(t::tag2(10)); - tx.send(t::tag3(10, 11u8, 'A')); + tx.send(t::tag1).unwrap(); + tx.send(t::tag2(10)).unwrap(); + tx.send(t::tag3(10, 11u8, 'A')).unwrap(); let mut t1: t; - t1 = rx.recv(); + t1 = rx.recv().unwrap(); assert_eq!(t1, t::tag1); - t1 = rx.recv(); + t1 = rx.recv().unwrap(); assert_eq!(t1, t::tag2(10)); - t1 = rx.recv(); + t1 = rx.recv().unwrap(); assert_eq!(t1, t::tag3(10, 11u8, 'A')); } fn test_chan() { let (tx1, rx1) = channel(); let (tx2, rx2) = channel(); - tx1.send(tx2); - let tx2 = rx1.recv(); + tx1.send(tx2).unwrap(); + let tx2 = rx1.recv().unwrap(); // Does the transmitted channel still work? - tx2.send(10); + tx2.send(10).unwrap(); let mut i: int; - i = rx2.recv(); + i = rx2.recv().unwrap(); assert_eq!(i, 10); } diff --git a/src/test/run-pass/task-comm-3.rs b/src/test/run-pass/task-comm-3.rs index 73f6eb563c1..a002a597481 100644 --- a/src/test/run-pass/task-comm-3.rs +++ b/src/test/run-pass/task-comm-3.rs @@ -11,6 +11,7 @@ // no-pretty-expanded FIXME #15189 use std::thread::Thread; +use std::sync::mpsc::{channel, Sender}; pub fn main() { println!("===== WITHOUT THREADS ====="); test00(); } @@ -19,7 +20,7 @@ fn test00_start(ch: &Sender<int>, message: int, count: int) { let mut i: int = 0; while i < count { println!("Sending Message"); - ch.send(message + 0); + ch.send(message + 0).unwrap(); i = i + 1; } println!("Ending test00_start"); @@ -53,7 +54,7 @@ fn test00() { for _r in results.iter() { i = 0; while i < number_of_messages { - let value = rx.recv(); + let value = rx.recv().unwrap(); sum += value; i = i + 1; } diff --git a/src/test/run-pass/task-comm-4.rs b/src/test/run-pass/task-comm-4.rs index 2e2b1fbff0f..1f1b750aa57 100644 --- a/src/test/run-pass/task-comm-4.rs +++ b/src/test/run-pass/task-comm-4.rs @@ -10,42 +10,44 @@ #![allow(dead_assignment)] +use std::sync::mpsc::channel; + pub fn main() { test00(); } fn test00() { let mut r: int = 0; let mut sum: int = 0; let (tx, rx) = channel(); - tx.send(1); - tx.send(2); - tx.send(3); - tx.send(4); - r = rx.recv(); + tx.send(1).unwrap(); + tx.send(2).unwrap(); + tx.send(3).unwrap(); + tx.send(4).unwrap(); + r = rx.recv().unwrap(); sum += r; println!("{}", r); - r = rx.recv(); + r = rx.recv().unwrap(); sum += r; println!("{}", r); - r = rx.recv(); + r = rx.recv().unwrap(); sum += r; println!("{}", r); - r = rx.recv(); + r = rx.recv().unwrap(); sum += r; println!("{}", r); - tx.send(5); - tx.send(6); - tx.send(7); - tx.send(8); - r = rx.recv(); + tx.send(5).unwrap(); + tx.send(6).unwrap(); + tx.send(7).unwrap(); + tx.send(8).unwrap(); + r = rx.recv().unwrap(); sum += r; println!("{}", r); - r = rx.recv(); + r = rx.recv().unwrap(); sum += r; println!("{}", r); - r = rx.recv(); + r = rx.recv().unwrap(); sum += r; println!("{}", r); - r = rx.recv(); + r = rx.recv().unwrap(); sum += r; println!("{}", r); assert_eq!(sum, 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8); diff --git a/src/test/run-pass/task-comm-5.rs b/src/test/run-pass/task-comm-5.rs index e51e14f7fbe..039308d5cfe 100644 --- a/src/test/run-pass/task-comm-5.rs +++ b/src/test/run-pass/task-comm-5.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::sync::mpsc::channel; + pub fn main() { test00(); } fn test00() { @@ -16,8 +18,8 @@ fn test00() { let (tx, rx) = channel(); let number_of_messages: int = 1000; let mut i: int = 0; - while i < number_of_messages { tx.send(i + 0); i += 1; } + while i < number_of_messages { tx.send(i + 0).unwrap(); i += 1; } i = 0; - while i < number_of_messages { sum += rx.recv(); i += 1; } + while i < number_of_messages { sum += rx.recv().unwrap(); i += 1; } assert_eq!(sum, number_of_messages * (number_of_messages - 1) / 2); } diff --git a/src/test/run-pass/task-comm-6.rs b/src/test/run-pass/task-comm-6.rs index e783cd9b6be..7cdfddcdeb1 100644 --- a/src/test/run-pass/task-comm-6.rs +++ b/src/test/run-pass/task-comm-6.rs @@ -10,6 +10,8 @@ #![allow(dead_assignment)] +use std::sync::mpsc::channel; + pub fn main() { test00(); } fn test00() { @@ -23,21 +25,21 @@ fn test00() { let number_of_messages: int = 1000; let mut i: int = 0; while i < number_of_messages { - tx0.send(i + 0); - tx1.send(i + 0); - tx2.send(i + 0); - tx3.send(i + 0); + tx0.send(i + 0).unwrap(); + tx1.send(i + 0).unwrap(); + tx2.send(i + 0).unwrap(); + tx3.send(i + 0).unwrap(); i += 1; } i = 0; while i < number_of_messages { - r = rx.recv(); + r = rx.recv().unwrap(); sum += r; - r = rx.recv(); + r = rx.recv().unwrap(); sum += r; - r = rx.recv(); + r = rx.recv().unwrap(); sum += r; - r = rx.recv(); + r = rx.recv().unwrap(); sum += r; i += 1; } diff --git a/src/test/run-pass/task-comm-7.rs b/src/test/run-pass/task-comm-7.rs index 9d8caa42626..054090eca39 100644 --- a/src/test/run-pass/task-comm-7.rs +++ b/src/test/run-pass/task-comm-7.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #![allow(dead_assignment)] +use std::sync::mpsc::{channel, Sender}; use std::task; pub fn main() { test00(); } @@ -18,7 +18,7 @@ pub fn main() { test00(); } fn test00_start(c: &Sender<int>, start: int, number_of_messages: int) { let mut i: int = 0; - while i < number_of_messages { c.send(start + i); i += 1; } + while i < number_of_messages { c.send(start + i).unwrap(); i += 1; } } fn test00() { @@ -46,13 +46,13 @@ fn test00() { let mut i: int = 0; while i < number_of_messages { - r = rx.recv(); + r = rx.recv().unwrap(); sum += r; - r = rx.recv(); + r = rx.recv().unwrap(); sum += r; - r = rx.recv(); + r = rx.recv().unwrap(); sum += r; - r = rx.recv(); + r = rx.recv().unwrap(); sum += r; i += 1; } diff --git a/src/test/run-pass/task-comm-9.rs b/src/test/run-pass/task-comm-9.rs index 69d70050437..d9faf6ee4e4 100644 --- a/src/test/run-pass/task-comm-9.rs +++ b/src/test/run-pass/task-comm-9.rs @@ -9,12 +9,13 @@ // except according to those terms. use std::thread::Thread; +use std::sync::mpsc::{channel, Sender}; pub fn main() { test00(); } fn test00_start(c: &Sender<int>, number_of_messages: int) { let mut i: int = 0; - while i < number_of_messages { c.send(i + 0); i += 1; } + while i < number_of_messages { c.send(i + 0).unwrap(); i += 1; } } fn test00() { @@ -29,7 +30,7 @@ fn test00() { let mut i: int = 0; while i < number_of_messages { - sum += rx.recv(); + sum += rx.recv().unwrap(); println!("{}", r); i += 1; } diff --git a/src/test/run-pass/task-comm-chan-nil.rs b/src/test/run-pass/task-comm-chan-nil.rs index 3ea17898ead..78a42632001 100644 --- a/src/test/run-pass/task-comm-chan-nil.rs +++ b/src/test/run-pass/task-comm-chan-nil.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::sync::mpsc::channel; + // rustboot can't transmit nils across channels because they don't have // any size, but rustc currently can because they do have size. Whether // or not this is desirable I don't know, but here's a regression test. pub fn main() { let (tx, rx) = channel(); - tx.send(()); - let n: () = rx.recv(); + tx.send(()).unwrap(); + let n: () = rx.recv().unwrap(); assert_eq!(n, ()); } diff --git a/src/test/run-pass/task-spawn-move-and-copy.rs b/src/test/run-pass/task-spawn-move-and-copy.rs index 8d6b6005a63..623a30eda1a 100644 --- a/src/test/run-pass/task-spawn-move-and-copy.rs +++ b/src/test/run-pass/task-spawn-move-and-copy.rs @@ -9,6 +9,7 @@ // except according to those terms. use std::task; +use std::sync::mpsc::channel; pub fn main() { let (tx, rx) = channel::<uint>(); @@ -18,9 +19,9 @@ pub fn main() { task::spawn(move || { let x_in_child = &(*x) as *const int as uint; - tx.send(x_in_child); + tx.send(x_in_child).unwrap(); }); - let x_in_child = rx.recv(); + let x_in_child = rx.recv().unwrap(); assert_eq!(x_in_parent, x_in_child); } diff --git a/src/test/run-pass/task-stderr.rs b/src/test/run-pass/task-stderr.rs index ddeffcdf722..a7eabe0edb3 100644 --- a/src/test/run-pass/task-stderr.rs +++ b/src/test/run-pass/task-stderr.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::sync::mpsc::channel; use std::io::{ChanReader, ChanWriter}; use std::thread; diff --git a/src/test/run-pass/tcp-accept-stress.rs b/src/test/run-pass/tcp-accept-stress.rs index 780cf234466..07f71fe580e 100644 --- a/src/test/run-pass/tcp-accept-stress.rs +++ b/src/test/run-pass/tcp-accept-stress.rs @@ -13,8 +13,10 @@ // quite quickly and it takes a few seconds for the sockets to get // recycled. +use std::sync::mpsc::channel; use std::io::{TcpListener, Listener, Acceptor, EndOfFile, TcpStream}; use std::sync::{atomic, Arc}; +use std::thread::Thread; static N: uint = 8; static M: uint = 20; @@ -35,7 +37,7 @@ fn test() { let a = a.clone(); let cnt = cnt.clone(); let srv_tx = srv_tx.clone(); - spawn(move|| { + Thread::spawn(move|| { let mut a = a; loop { match a.accept() { @@ -49,17 +51,17 @@ fn test() { } } srv_tx.send(()); - }); + }).detach(); } for _ in range(0, N) { let cli_tx = cli_tx.clone(); - spawn(move|| { + Thread::spawn(move|| { for _ in range(0, M) { let _s = TcpStream::connect(addr).unwrap(); } cli_tx.send(()); - }); + }).detach(); } drop((cli_tx, srv_tx)); diff --git a/src/test/run-pass/tcp-connect-timeouts.rs b/src/test/run-pass/tcp-connect-timeouts.rs index 2d087406fd6..38a762d5803 100644 --- a/src/test/run-pass/tcp-connect-timeouts.rs +++ b/src/test/run-pass/tcp-connect-timeouts.rs @@ -26,6 +26,7 @@ use std::io::*; use std::io::test::*; use std::io; use std::time::Duration; +use std::sync::mpsc::channel; #[cfg_attr(target_os = "freebsd", ignore)] fn eventual_timeout() { @@ -35,10 +36,10 @@ fn eventual_timeout() { let (_tx2, rx2) = channel::<()>(); std::task::spawn(move|| { let _l = TcpListener::bind(addr).unwrap().listen(); - tx1.send(()); - let _ = rx2.recv_opt(); + tx1.send(()).unwrap(); + let _ = rx2.recv(); }); - rx1.recv(); + rx1.recv().unwrap(); let mut v = Vec::new(); for _ in range(0u, 10000) { diff --git a/src/test/run-pass/tcp-stress.rs b/src/test/run-pass/tcp-stress.rs index b3391669d35..62b61c153c7 100644 --- a/src/test/run-pass/tcp-stress.rs +++ b/src/test/run-pass/tcp-stress.rs @@ -17,24 +17,25 @@ extern crate log; extern crate libc; +use std::sync::mpsc::channel; use std::io::net::tcp::{TcpListener, TcpStream}; use std::io::{Acceptor, Listener}; -use std::thread::Builder; +use std::thread::{Builder, Thread}; use std::time::Duration; fn main() { // This test has a chance to time out, try to not let it time out - spawn(move|| { + Thread::spawn(move|| -> () { use std::io::timer; timer::sleep(Duration::milliseconds(30 * 1000)); println!("timed out!"); unsafe { libc::exit(1) } - }); + }).detach(); let (tx, rx) = channel(); - spawn(move|| { + Thread::spawn(move || -> () { let mut listener = TcpListener::bind("127.0.0.1:0").unwrap(); - tx.send(listener.socket_name().unwrap()); + tx.send(listener.socket_name().unwrap()).unwrap(); let mut acceptor = listener.listen(); loop { let mut stream = match acceptor.accept() { @@ -47,8 +48,8 @@ fn main() { stream.read_byte(); stream.write(&[2]); } - }); - let addr = rx.recv(); + }).detach(); + let addr = rx.recv().unwrap(); let (tx, rx) = channel(); for _ in range(0u, 1000) { @@ -63,7 +64,7 @@ fn main() { }, Err(e) => debug!("{}", e) } - tx.send(()); + tx.send(()).unwrap(); }).detach(); } @@ -71,7 +72,7 @@ fn main() { // server just runs infinitely. drop(tx); for _ in range(0u, 1000) { - rx.recv(); + rx.recv().unwrap(); } unsafe { libc::exit(0) } } diff --git a/src/test/run-pass/tempfile.rs b/src/test/run-pass/tempfile.rs index a866f497b86..9e67095bb30 100644 --- a/src/test/run-pass/tempfile.rs +++ b/src/test/run-pass/tempfile.rs @@ -23,6 +23,7 @@ use std::io::{fs, TempDir}; use std::io; use std::os; use std::task; +use std::sync::mpsc::channel; fn test_tempdir() { let path = { @@ -38,11 +39,11 @@ fn test_rm_tempdir() { let (tx, rx) = channel(); let f = move|:| -> () { let tmp = TempDir::new("test_rm_tempdir").unwrap(); - tx.send(tmp.path().clone()); + tx.send(tmp.path().clone()).unwrap(); panic!("panic to unwind past `tmp`"); }; task::try(f); - let path = rx.recv(); + let path = rx.recv().unwrap(); assert!(!path.exists()); let tmp = TempDir::new("test_rm_tempdir").unwrap(); @@ -79,12 +80,12 @@ fn test_rm_tempdir_close() { let (tx, rx) = channel(); let f = move|:| -> () { let tmp = TempDir::new("test_rm_tempdir").unwrap(); - tx.send(tmp.path().clone()); + tx.send(tmp.path().clone()).unwrap(); tmp.close(); panic!("panic when unwinding past `tmp`"); }; task::try(f); - let path = rx.recv(); + let path = rx.recv().unwrap(); assert!(!path.exists()); let tmp = TempDir::new("test_rm_tempdir").unwrap(); diff --git a/src/test/run-pass/trait-bounds-in-arc.rs b/src/test/run-pass/trait-bounds-in-arc.rs index d2c1461d65d..0d2cb60c213 100644 --- a/src/test/run-pass/trait-bounds-in-arc.rs +++ b/src/test/run-pass/trait-bounds-in-arc.rs @@ -11,8 +11,8 @@ // Tests that a heterogeneous list of existential types can be put inside an Arc // and shared between tasks as long as all types fulfill Send. - use std::sync::Arc; +use std::sync::mpsc::channel; use std::task; trait Pet { diff --git a/src/test/run-pass/trait-impl.rs b/src/test/run-pass/trait-impl.rs index 216a7ef33f5..003686c0bbe 100644 --- a/src/test/run-pass/trait-impl.rs +++ b/src/test/run-pass/trait-impl.rs @@ -10,6 +10,10 @@ // Test calling methods on an impl for a bare trait. +// aux-build:traitimpl.rs +extern crate traitimpl; +use traitimpl::Bar; + static mut COUNT: uint = 1; trait T {} @@ -25,6 +29,9 @@ impl<'a> T+'a { impl T for int {} +struct Foo; +impl<'a> Bar<'a> for Foo {} + fn main() { let x: &T = &42i; @@ -33,4 +40,8 @@ fn main() { T::bar(); unsafe { assert!(COUNT == 12); } + + // Cross-crait case + let x: &Bar = &Foo; + x.bar(); } diff --git a/src/test/run-pass/trait-inheritance-overloading.rs b/src/test/run-pass/trait-inheritance-overloading.rs index 739c3e4bdb0..3748a31b302 100644 --- a/src/test/run-pass/trait-inheritance-overloading.rs +++ b/src/test/run-pass/trait-inheritance-overloading.rs @@ -9,6 +9,7 @@ // except according to those terms. use std::cmp::PartialEq; +use std::ops::{Add, Sub, Mul}; trait MyNum : Add<Self,Self> + Sub<Self,Self> + Mul<Self,Self> + PartialEq + Clone { } diff --git a/src/test/run-pass/trivial-message.rs b/src/test/run-pass/trivial-message.rs index 464ab135228..6bece8265c0 100644 --- a/src/test/run-pass/trivial-message.rs +++ b/src/test/run-pass/trivial-message.rs @@ -13,6 +13,8 @@ message. */ +use std::sync::mpsc::channel; + pub fn main() { let (tx, rx) = channel(); tx.send(42i); diff --git a/src/test/run-pass/unboxed-closures-call-sugar-object.rs b/src/test/run-pass/unboxed-closures-call-sugar-object.rs new file mode 100644 index 00000000000..2dec53cc13a --- /dev/null +++ b/src/test/run-pass/unboxed-closures-call-sugar-object.rs @@ -0,0 +1,25 @@ +// Copyright 2012 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. + +#![feature(unboxed_closures)] + +use std::ops::FnMut; + +fn make_adder(x: int) -> Box<FnMut(int)->int + 'static> { + box move |y| { x + y } +} + +pub fn main() { + let mut adder = make_adder(3); + let z = (*adder)(2); + println!("{}", z); + assert_eq!(z, 5); +} + diff --git a/src/test/run-pass/unboxed-closures-infer-argument-types-from-expected-bound.rs b/src/test/run-pass/unboxed-closures-infer-argument-types-from-expected-bound.rs index 465c324122a..fdd85b71cd2 100644 --- a/src/test/run-pass/unboxed-closures-infer-argument-types-from-expected-bound.rs +++ b/src/test/run-pass/unboxed-closures-infer-argument-types-from-expected-bound.rs @@ -13,6 +13,8 @@ #![feature(unboxed_closures)] +use std::num::ToPrimitive; + fn doit<T,F>(val: T, f: &F) where F : Fn(T) { diff --git a/src/test/run-pass/unboxed-closures-infer-argument-types-from-expected-object-type.rs b/src/test/run-pass/unboxed-closures-infer-argument-types-from-expected-object-type.rs index 440292d202e..cce8cd64a14 100644 --- a/src/test/run-pass/unboxed-closures-infer-argument-types-from-expected-object-type.rs +++ b/src/test/run-pass/unboxed-closures-infer-argument-types-from-expected-object-type.rs @@ -13,6 +13,8 @@ #![feature(unboxed_closures)] +use std::num::ToPrimitive; + fn doit<T>(val: T, f: &Fn(T)) { f.call((val,)) } pub fn main() { diff --git a/src/test/run-pass/unboxed-closures-infer-argument-types-with-bound-regions-from-expected-bound.rs b/src/test/run-pass/unboxed-closures-infer-argument-types-with-bound-regions-from-expected-bound.rs index b279eb5fbba..8497bf7f987 100644 --- a/src/test/run-pass/unboxed-closures-infer-argument-types-with-bound-regions-from-expected-bound.rs +++ b/src/test/run-pass/unboxed-closures-infer-argument-types-with-bound-regions-from-expected-bound.rs @@ -13,6 +13,8 @@ #![feature(unboxed_closures)] +use std::num::ToPrimitive; + fn doit<T,F>(val: T, f: &F) where F : Fn(&T) { diff --git a/src/test/run-pass/unique-send-2.rs b/src/test/run-pass/unique-send-2.rs index 672cd2d00e8..f88c458f2ed 100644 --- a/src/test/run-pass/unique-send-2.rs +++ b/src/test/run-pass/unique-send-2.rs @@ -9,9 +9,10 @@ // except according to those terms. use std::task; +use std::sync::mpsc::{channel, Sender}; fn child(tx: &Sender<Box<uint>>, i: uint) { - tx.send(box i); + tx.send(box i).unwrap(); } pub fn main() { @@ -28,7 +29,7 @@ pub fn main() { let mut actual = 0u; for _ in range(0u, n) { - let j = rx.recv(); + let j = rx.recv().unwrap(); actual += *j; } diff --git a/src/test/run-pass/unique-send.rs b/src/test/run-pass/unique-send.rs index 22b5a8cdaa4..afafb204c1c 100644 --- a/src/test/run-pass/unique-send.rs +++ b/src/test/run-pass/unique-send.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::sync::mpsc::channel; + pub fn main() { let (tx, rx) = channel(); - tx.send(box 100i); - let v = rx.recv(); + tx.send(box 100i).unwrap(); + let v = rx.recv().unwrap(); assert_eq!(v, box 100i); } diff --git a/src/test/run-pass/unwind-resource.rs b/src/test/run-pass/unwind-resource.rs index 9789deef636..943b2d3edd1 100644 --- a/src/test/run-pass/unwind-resource.rs +++ b/src/test/run-pass/unwind-resource.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use std::sync::mpsc::{channel, Sender}; use std::task; struct complainer { @@ -18,7 +18,7 @@ struct complainer { impl Drop for complainer { fn drop(&mut self) { println!("About to send!"); - self.tx.send(true); + self.tx.send(true).unwrap(); println!("Sent!"); } } @@ -39,5 +39,5 @@ pub fn main() { let (tx, rx) = channel(); task::spawn(move|| f(tx.clone())); println!("hiiiiiiiii"); - assert!(rx.recv()); + assert!(rx.recv().unwrap()); } diff --git a/src/test/run-pass/variadic-ffi.rs b/src/test/run-pass/variadic-ffi.rs index f8eef988561..ec320c1f8a3 100644 --- a/src/test/run-pass/variadic-ffi.rs +++ b/src/test/run-pass/variadic-ffi.rs @@ -9,7 +9,8 @@ // except according to those terms. extern crate libc; -use std::c_str::CString; + +use std::c_str::{CString, ToCStr}; use libc::{c_char, c_int}; // ignore-fast doesn't like extern crate diff --git a/src/test/run-pass/vector-sort-panic-safe.rs b/src/test/run-pass/vector-sort-panic-safe.rs index 08bd367917a..2da0ecd6d51 100644 --- a/src/test/run-pass/vector-sort-panic-safe.rs +++ b/src/test/run-pass/vector-sort-panic-safe.rs @@ -9,7 +9,7 @@ // except according to those terms. use std::task; -use std::sync::atomic::{AtomicUint, INIT_ATOMIC_UINT, Relaxed}; +use std::sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Relaxed}; use std::rand::{thread_rng, Rng, Rand}; const REPEATS: uint = 5; @@ -17,18 +17,18 @@ const MAX_LEN: uint = 32; static drop_counts: [AtomicUint; MAX_LEN] = // FIXME #5244: AtomicUint is not Copy. [ - INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, - INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, - INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, - INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, + ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, + ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, + ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, + ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, - INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, - INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, - INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, - INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, + ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, + ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, + ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, + ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ]; -static creation_count: AtomicUint = INIT_ATOMIC_UINT; +static creation_count: AtomicUint = ATOMIC_UINT_INIT; #[derive(Clone, PartialEq, PartialOrd, Eq, Ord)] struct DropCounter { x: uint, creation_id: uint } diff --git a/src/test/run-pass/wait-forked-but-failed-child.rs b/src/test/run-pass/wait-forked-but-failed-child.rs index 577e114945c..624b4176704 100644 --- a/src/test/run-pass/wait-forked-but-failed-child.rs +++ b/src/test/run-pass/wait-forked-but-failed-child.rs @@ -12,10 +12,10 @@ extern crate libc; use std::io::process::Command; use std::iter::IteratorExt; +use std::str::from_str; use libc::funcs::posix88::unistd; - // The output from "ps -A -o pid,ppid,args" should look like this: // PID PPID COMMAND // 1 0 /sbin/init |
