mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-12 08:36:03 +00:00
auto merge of #20436 : alexcrichton/rust/rollup, r=alexcrichton
This commit is contained in:
commit
c89417130f
@ -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
|
||||
|
@ -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: $$@)
|
||||
|
@ -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)))
|
||||
|
@ -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};
|
||||
|
@ -450,6 +450,8 @@ them.
|
||||
|
||||
~~~no_run
|
||||
extern crate libc;
|
||||
|
||||
use std::c_str::ToCStr;
|
||||
use std::ptr;
|
||||
|
||||
#[link(name = "readline")]
|
||||
|
@ -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 {
|
||||
|
482
src/doc/guide.md
482
src/doc/guide.md
@ -26,7 +26,7 @@ in the `$`s, they just indicate the start of each command):
|
||||
curl -L https://static.rust-lang.org/rustup.sh | sudo sh
|
||||
```
|
||||
|
||||
If you're concerned about the [potential insecurity](http://curlpipesh.tumblr.com/) of using `curl | sudo sh`,
|
||||
If you're concerned about the [potential insecurity](http://curlpipesh.tumblr.com/) of using `curl | sudo sh`,
|
||||
please keep reading and see our disclaimer below. And feel free to use a two-step version of the installation and examine our installation script:
|
||||
|
||||
```bash
|
||||
@ -1106,13 +1106,21 @@ enum Ordering {
|
||||
```
|
||||
|
||||
An `Ordering` can only be _one_ of `Less`, `Equal`, or `Greater` at any given
|
||||
time. Here's an example:
|
||||
time.
|
||||
|
||||
Because `Ordering` is provided by the standard library, we can use the `use`
|
||||
keyword to use it in our code. We'll learn more about `use` later, but it's
|
||||
used to bring names into scope.
|
||||
|
||||
Here's an example of how to use `Ordering`:
|
||||
|
||||
```{rust}
|
||||
use std::cmp::Ordering;
|
||||
|
||||
fn cmp(a: int, b: int) -> Ordering {
|
||||
if a < b { Less }
|
||||
else if a > b { Greater }
|
||||
else { Equal }
|
||||
if a < b { Ordering::Less }
|
||||
else if a > b { Ordering::Greater }
|
||||
else { Ordering::Equal }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
@ -1121,28 +1129,35 @@ fn main() {
|
||||
|
||||
let ordering = cmp(x, y); // ordering: Ordering
|
||||
|
||||
if ordering == Less {
|
||||
if ordering == Ordering::Less {
|
||||
println!("less");
|
||||
} else if ordering == Greater {
|
||||
} else if ordering == Ordering::Greater {
|
||||
println!("greater");
|
||||
} else if ordering == Equal {
|
||||
} else if ordering == Ordering::Equal {
|
||||
println!("equal");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`cmp` is a function that compares two things, and returns an `Ordering`. We
|
||||
return either `Less`, `Greater`, or `Equal`, depending on if the two values
|
||||
are greater, less, or equal.
|
||||
There's a symbol here we haven't seen before: the double colon (`::`).
|
||||
This is used to indicate a namesapce. In this case, `Ordering` lives in
|
||||
the `cmp` submodule of the `std` module. We'll talk more about modules
|
||||
later in the guide. For now, all you need to know is that you can `use`
|
||||
things from the standard library if you need them.
|
||||
|
||||
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 || {
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
||||
|
@ -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]
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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::*;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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[]) }
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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]) })
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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]
|
||||
|
@ -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 }
|
||||
}
|
||||
|
||||
|
@ -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"]
|
||||
|
@ -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};
|
||||
|
@ -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"]
|
||||
|
@ -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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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]
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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() {
|
||||
|
@ -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;
|
||||
|
@ -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]
|
||||
|
@ -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() {
|
||||
|
@ -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() {
|
||||
|
@ -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));
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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};
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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};
|
||||
|
@ -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};
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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};
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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};
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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};
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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};
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -14,10 +14,10 @@ use super::SelectionContext;
|
||||
use super::{Obligation, ObligationCause};
|
||||
use super::util;
|
||||
|
||||
use middle::subst;
|
||||
use middle::subst::Subst;
|
||||
use middle::ty::{mod, Ty};
|
||||
use middle::infer::InferCtxt;
|
||||
use std::collections::HashSet;
|
||||
use std::rc::Rc;
|
||||
use syntax::ast;
|
||||
use syntax::codemap::DUMMY_SP;
|
||||
@ -52,9 +52,21 @@ pub fn impl_can_satisfy(infcx: &InferCtxt,
|
||||
selcx.evaluate_impl(impl2_def_id, &obligation)
|
||||
}
|
||||
|
||||
pub fn impl_is_local(tcx: &ty::ctxt,
|
||||
impl_def_id: ast::DefId)
|
||||
-> bool
|
||||
#[allow(missing_copy_implementations)]
|
||||
pub enum OrphanCheckErr {
|
||||
NoLocalInputType,
|
||||
UncoveredTypeParameter(ty::ParamTy),
|
||||
}
|
||||
|
||||
/// Checks the coherence orphan rules. `impl_def_id` should be the
|
||||
/// def-id of a trait impl. To pass, either the trait must be local, or else
|
||||
/// two conditions must be satisfied:
|
||||
///
|
||||
/// 1. At least one of the input types must involve a local type.
|
||||
/// 2. All type parameters must be covered by a local type.
|
||||
pub fn orphan_check(tcx: &ty::ctxt,
|
||||
impl_def_id: ast::DefId)
|
||||
-> Result<(), OrphanCheckErr>
|
||||
{
|
||||
debug!("impl_is_local({})", impl_def_id.repr(tcx));
|
||||
|
||||
@ -63,20 +75,40 @@ pub fn impl_is_local(tcx: &ty::ctxt,
|
||||
let trait_ref = ty::impl_trait_ref(tcx, impl_def_id).unwrap();
|
||||
debug!("trait_ref={}", trait_ref.repr(tcx));
|
||||
|
||||
// If the trait is local to the crate, ok.
|
||||
// If the *trait* is local to the crate, ok.
|
||||
if trait_ref.def_id.krate == ast::LOCAL_CRATE {
|
||||
debug!("trait {} is local to current crate",
|
||||
trait_ref.def_id.repr(tcx));
|
||||
return true;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Otherwise, at least one of the input types must be local to the
|
||||
// crate.
|
||||
trait_ref.input_types().iter().any(|&t| ty_is_local(tcx, t))
|
||||
// Check condition 1: at least one type must be local.
|
||||
if !trait_ref.input_types().iter().any(|&t| ty_reaches_local(tcx, t)) {
|
||||
return Err(OrphanCheckErr::NoLocalInputType);
|
||||
}
|
||||
|
||||
// Check condition 2: type parameters must be "covered" by a local type.
|
||||
let covered_params: HashSet<_> =
|
||||
trait_ref.input_types().iter()
|
||||
.flat_map(|&t| type_parameters_covered_by_ty(tcx, t).into_iter())
|
||||
.collect();
|
||||
let all_params: HashSet<_> =
|
||||
trait_ref.input_types().iter()
|
||||
.flat_map(|&t| type_parameters_reachable_from_ty(t).into_iter())
|
||||
.collect();
|
||||
for ¶m in all_params.difference(&covered_params) {
|
||||
return Err(OrphanCheckErr::UncoveredTypeParameter(param));
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
|
@ -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)),
|
||||
}
|
||||
}
|
||||
|
301
src/librustc/middle/traits/object_safety.rs
Normal file
301
src/librustc/middle/traits/object_safety.rs
Normal 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),
|
||||
}
|
||||
}
|
||||
}
|
@ -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:
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
112
src/librustc/middle/ty_walk.rs
Normal file
112
src/librustc/middle/ty_walk.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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) {
|
||||
|
@ -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)
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user