auto merge of #20436 : alexcrichton/rust/rollup, r=alexcrichton

This commit is contained in:
bors 2015-01-02 21:56:13 +00:00
commit c89417130f
488 changed files with 6757 additions and 4851 deletions

View File

@ -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

View File

@ -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: $$@)

View File

@ -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)))

View File

@ -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};

View File

@ -450,6 +450,8 @@ them.
~~~no_run
extern crate libc;
use std::c_str::ToCStr;
use std::ptr;
#[link(name = "readline")]

View File

@ -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 {

View File

@ -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.
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`.
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.
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:
## Scoped Method Resolution and Orphan `impl`s
```{rust,ignore}
mod shapes {
use std::f64::consts;
There are two restrictions for implementing traits that prevent this from
getting out of hand.
trait HasArea {
fn area(&self) -> f64;
}
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.
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,
};
println!("{}", c.area());
}
```
Now that we've moved the structs and traits into their own module, we get an
error:
```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 || {

View File

@ -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.

View File

@ -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

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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
}

View File

@ -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) {

View File

@ -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

View File

@ -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]

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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,23 +951,71 @@ 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
////////////////////////////////////////////////////////////////////////////////
/// Returns a copy of `v`.
#[inline]
fn to_vec(&self) -> Vec<T> where T: Clone {
let mut vector = Vec::with_capacity(self.len());
vector.push_all(self);
vector
}
/// 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> {
#[inline]
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> where T: Clone {
Permutations{
swaps: ElementSwaps::new(self.len()),
v: self.to_vec(),
}
}
fn clone_from_slice(&mut self, src: &[T]) -> uint where T: Clone {
core_slice::SliceExt::clone_from_slice(self, src)
}
#[inline]
fn sort(&mut self) where T: Ord {
self.sort_by(|a, b| a.cmp(b))
}
fn binary_search(&self, x: &T) -> Result<uint, uint> where T: Ord {
core_slice::SliceExt::binary_search(self, x)
}
fn next_permutation(&mut self) -> bool where T: Ord {
core_slice::SliceExt::next_permutation(self)
}
fn prev_permutation(&mut self) -> bool where T: Ord {
core_slice::SliceExt::prev_permutation(self)
}
fn position_elem(&self, t: &T) -> Option<uint> where T: PartialEq {
core_slice::SliceExt::position_elem(self, t)
}
fn rposition_elem(&self, t: &T) -> Option<uint> where T: PartialEq {
core_slice::SliceExt::rposition_elem(self, t)
}
fn contains(&self, x: &T) -> bool where T: PartialEq {
core_slice::SliceExt::contains(self, x)
}
fn starts_with(&self, needle: &[T]) -> bool where T: PartialEq {
core_slice::SliceExt::starts_with(self, needle)
}
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);
@ -802,204 +1024,9 @@ impl<T> BoxedSliceExt<T> for Box<[T]> {
}
}
/// 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> {
let mut vector = Vec::with_capacity(self.len());
vector.push_all(self);
vector
}
#[inline]
fn partitioned<F>(&self, f: F) -> (Vec<T>, Vec<T>) where F: FnMut(&T) -> bool {
self.iter().cloned().partition(f)
}
/// Returns an iterator over all permutations of a vector.
fn permutations(&self) -> Permutations<T> {
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)
}
}
/// 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);
/// 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>;
/// Deprecated: use `binary_search` instead.
#[deprecated = "use binary_search instead"]
fn binary_search_elem(&self, x: &T) -> Result<uint, uint> {
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;
/// 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;
}
#[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 binary_search(&self, x: &T) -> Result<uint, uint> {
core_slice::OrdSliceExt::binary_search(self, x)
}
fn next_permutation(&mut self) -> bool {
core_slice::OrdSliceExt::next_permutation(self)
}
fn prev_permutation(&mut self) -> bool {
core_slice::OrdSliceExt::prev_permutation(self)
}
}
////////////////////////////////////////////////////////////////////////////////
// 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;

View File

@ -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::*;

View File

@ -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);

View File

@ -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;

View File

@ -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[]) }

View File

@ -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;

View File

@ -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,

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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]) })
}

View File

@ -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
}
}

View File

@ -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)
}
}

View File

@ -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.

View File

@ -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;

View File

@ -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]

View File

@ -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 }
}

View File

@ -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"]

View File

@ -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};

View File

@ -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"]

View File

@ -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,6 +424,111 @@ impl<T> SliceExt<T> for [T] {
fn as_mut_ptr(&mut self) -> *mut T {
self.repr().data as *mut T
}
#[inline]
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> where T: PartialEq {
self.iter().rposition(|x| *x == *t)
}
#[inline]
fn contains(&self, x: &T) -> bool where T: PartialEq {
self.iter().any(|elt| *x == *elt)
}
#[inline]
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 where T: PartialEq {
let (m, n) = (self.len(), needle.len());
m >= n && needle == self[m-n..]
}
#[unstable]
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 where T: Ord {
// These cases only have 1 permutation each, so we can't do anything.
if self.len() < 2 { return false; }
// Step 1: Identify the longest, rightmost weakly decreasing part of the vector
let mut i = self.len() - 1;
while i > 0 && self[i-1] >= self[i] {
i -= 1;
}
// If that is the entire vector, this is the last-ordered permutation.
if i == 0 {
return false;
}
// Step 2: Find the rightmost element larger than the pivot (i-1)
let mut j = self.len() - 1;
while j >= i && self[j] <= self[i-1] {
j -= 1;
}
// Step 3: Swap that element with the pivot
self.swap(j, i-1);
// Step 4: Reverse the (previously) weakly decreasing part
self.slice_from_mut(i).reverse();
true
}
#[experimental]
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; }
// Step 1: Identify the longest, rightmost weakly increasing part of the vector
let mut i = self.len() - 1;
while i > 0 && self[i-1] <= self[i] {
i -= 1;
}
// If that is the entire vector, this is the first-ordered permutation.
if i == 0 {
return false;
}
// Step 2: Reverse the weakly increasing part
self.slice_from_mut(i).reverse();
// Step 3: Find the rightmost element equal to or bigger than the pivot (i-1)
let mut j = self.len() - 1;
while j >= i && self[j-1] < self[i-1] {
j -= 1;
}
// Step 4: Swap that element with the pivot
self.swap(i-1, j);
true
}
#[inline]
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);
for i in range(0, min) {
dst[i].clone_from(&src[i]);
}
min
}
}
impl<T> ops::Index<uint, T> for [T] {
@ -479,160 +604,6 @@ impl<T> ops::SliceMut<uint, [T]> for [T] {
}
}
/// 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> {
self.iter().position(|y| *x == *y)
}
#[inline]
fn rposition_elem(&self, t: &T) -> Option<uint> {
self.iter().rposition(|x| *x == *t)
}
#[inline]
fn contains(&self, x: &T) -> bool {
self.iter().any(|elt| *x == *elt)
}
#[inline]
fn starts_with(&self, needle: &[T]) -> bool {
let n = needle.len();
self.len() >= n && needle == self[..n]
}
#[inline]
fn ends_with(&self, needle: &[T]) -> bool {
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> {
self.binary_search_by(|p| p.cmp(x))
}
#[experimental]
fn next_permutation(&mut self) -> bool {
// These cases only have 1 permutation each, so we can't do anything.
if self.len() < 2 { return false; }
// Step 1: Identify the longest, rightmost weakly decreasing part of the vector
let mut i = self.len() - 1;
while i > 0 && self[i-1] >= self[i] {
i -= 1;
}
// If that is the entire vector, this is the last-ordered permutation.
if i == 0 {
return false;
}
// Step 2: Find the rightmost element larger than the pivot (i-1)
let mut j = self.len() - 1;
while j >= i && self[j] <= self[i-1] {
j -= 1;
}
// Step 3: Swap that element with the pivot
self.swap(j, i-1);
// Step 4: Reverse the (previously) weakly decreasing part
self.slice_from_mut(i).reverse();
true
}
#[experimental]
fn prev_permutation(&mut self) -> bool {
// These cases only have 1 permutation each, so we can't do anything.
if self.len() < 2 { return false; }
// Step 1: Identify the longest, rightmost weakly increasing part of the vector
let mut i = self.len() - 1;
while i > 0 && self[i-1] <= self[i] {
i -= 1;
}
// If that is the entire vector, this is the first-ordered permutation.
if i == 0 {
return false;
}
// Step 2: Reverse the weakly increasing part
self.slice_from_mut(i).reverse();
// Step 3: Find the rightmost element equal to or bigger than the pivot (i-1)
let mut j = self.len() - 1;
while j >= i && self[j-1] < self[i-1] {
j -= 1;
}
// Step 4: Swap that element with the pivot
self.swap(i-1, j);
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 {
let min = cmp::min(self.len(), src.len());
let dst = self.slice_to_mut(min);
let src = src.slice_to(min);
for i in range(0, min) {
dst[i].clone_from(&src[i]);
}
min
}
}
////////////////////////////////////////////////////////////////////////////////
// Common traits
////////////////////////////////////////////////////////////////////////////////

View File

@ -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]

View File

@ -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() {

View File

@ -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() {

View File

@ -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;

View File

@ -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]

View File

@ -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() {

View File

@ -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() {

View File

@ -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));

View File

@ -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");

View File

@ -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;

View File

@ -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())
}
}

View File

@ -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

View File

@ -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};

View File

@ -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;

View File

@ -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;

View File

@ -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};

View File

@ -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};

View File

@ -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;

View File

@ -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};

View File

@ -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

View File

@ -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);

View File

@ -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};

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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};

View File

@ -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,

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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};

View File

@ -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.

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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.

View File

@ -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);
}
}

View File

@ -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

View File

@ -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)
}

View File

@ -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 &param in all_params.difference(&covered_params) {
return Err(OrphanCheckErr::UncoveredTypeParameter(param));
}
return Ok(());
}
pub fn ty_is_local<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
debug!("ty_is_local({})", ty.repr(tcx));
fn ty_reaches_local<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
ty.walk().any(|t| ty_is_local_constructor(tcx, t))
}
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) => {
ty::ty_enum(def_id, _) |
ty::ty_struct(def_id, _) => {
def_id.krate == ast::LOCAL_CRATE
}
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_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, 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)
}
}
})
})
}
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()
}

View File

@ -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)),
}
}

View File

@ -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),
}
}
}

View File

@ -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:

View File

@ -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))
}

View File

@ -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 {

View File

@ -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>),
{
maybe_walk_ty(ty, |ty| { f(ty); true });
}
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);
}
}
}
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)
}
maybe_walk_ty_(ty, &mut f);
/// 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>),
{
for ty in ty_root.walk() {
f(ty);
}
}
/// 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();
}
}
}
// 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()
}
}

View File

@ -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)
}
}
}

View File

@ -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)
}
}
}
}

View File

@ -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) {

View File

@ -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)
};

View File

@ -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;

View File

@ -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())
}
}

View File

@ -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 {

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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> {

Some files were not shown because too many files have changed in this diff Show More