Auto merge of #23936 - pnkfelix:rollup, r=pnkfelix
This is an attempt to fix #23922
This commit is contained in:
commit
8943653624
|
@ -18,7 +18,6 @@
|
||||||
#![feature(std_misc)]
|
#![feature(std_misc)]
|
||||||
#![feature(test)]
|
#![feature(test)]
|
||||||
#![feature(path_ext)]
|
#![feature(path_ext)]
|
||||||
#![feature(convert)]
|
|
||||||
#![feature(str_char)]
|
#![feature(str_char)]
|
||||||
|
|
||||||
#![deny(warnings)]
|
#![deny(warnings)]
|
||||||
|
|
|
@ -977,7 +977,6 @@ An example of `use` declarations:
|
||||||
|
|
||||||
```
|
```
|
||||||
# #![feature(core)]
|
# #![feature(core)]
|
||||||
use std::iter::range_step;
|
|
||||||
use std::option::Option::{Some, None};
|
use std::option::Option::{Some, None};
|
||||||
use std::collections::hash_map::{self, HashMap};
|
use std::collections::hash_map::{self, HashMap};
|
||||||
|
|
||||||
|
@ -985,9 +984,6 @@ fn foo<T>(_: T){}
|
||||||
fn bar(map1: HashMap<String, usize>, map2: hash_map::HashMap<String, usize>){}
|
fn bar(map1: HashMap<String, usize>, map2: hash_map::HashMap<String, usize>){}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Equivalent to 'std::iter::range_step(0, 10, 2);'
|
|
||||||
range_step(0, 10, 2);
|
|
||||||
|
|
||||||
// Equivalent to 'foo(vec![std::option::Option::Some(1.0f64),
|
// Equivalent to 'foo(vec![std::option::Option::Some(1.0f64),
|
||||||
// std::option::Option::None]);'
|
// std::option::Option::None]);'
|
||||||
foo(vec![Some(1.0f64), None]);
|
foo(vec![Some(1.0f64), None]);
|
||||||
|
|
|
@ -42,5 +42,6 @@
|
||||||
* [Intrinsics](intrinsics.md)
|
* [Intrinsics](intrinsics.md)
|
||||||
* [Lang items](lang-items.md)
|
* [Lang items](lang-items.md)
|
||||||
* [Link args](link-args.md)
|
* [Link args](link-args.md)
|
||||||
|
* [Benchmark Tests](benchmark-tests.md)
|
||||||
* [Conclusion](conclusion.md)
|
* [Conclusion](conclusion.md)
|
||||||
* [Glossary](glossary.md)
|
* [Glossary](glossary.md)
|
||||||
|
|
|
@ -0,0 +1,152 @@
|
||||||
|
% Benchmark tests
|
||||||
|
|
||||||
|
Rust supports benchmark tests, which can test the performance of your
|
||||||
|
code. Let's make our `src/lib.rs` look like this (comments elided):
|
||||||
|
|
||||||
|
```{rust,ignore}
|
||||||
|
#![feature(test)]
|
||||||
|
|
||||||
|
extern crate test;
|
||||||
|
|
||||||
|
pub fn add_two(a: i32) -> i32 {
|
||||||
|
a + 2
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use test::Bencher;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_works() {
|
||||||
|
assert_eq!(4, add_two(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn bench_add_two(b: &mut Bencher) {
|
||||||
|
b.iter(|| add_two(2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Note the `test` feature gate, which enables this unstable feature.
|
||||||
|
|
||||||
|
We've imported the `test` crate, which contains our benchmarking support.
|
||||||
|
We have a new function as well, with the `bench` attribute. Unlike regular
|
||||||
|
tests, which take no arguments, benchmark tests take a `&mut Bencher`. This
|
||||||
|
`Bencher` provides an `iter` method, which takes a closure. This closure
|
||||||
|
contains the code we'd like to benchmark.
|
||||||
|
|
||||||
|
We can run benchmark tests with `cargo bench`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo bench
|
||||||
|
Compiling adder v0.0.1 (file:///home/steve/tmp/adder)
|
||||||
|
Running target/release/adder-91b3e234d4ed382a
|
||||||
|
|
||||||
|
running 2 tests
|
||||||
|
test tests::it_works ... ignored
|
||||||
|
test tests::bench_add_two ... bench: 1 ns/iter (+/- 0)
|
||||||
|
|
||||||
|
test result: ok. 0 passed; 0 failed; 1 ignored; 1 measured
|
||||||
|
```
|
||||||
|
|
||||||
|
Our non-benchmark test was ignored. You may have noticed that `cargo bench`
|
||||||
|
takes a bit longer than `cargo test`. This is because Rust runs our benchmark
|
||||||
|
a number of times, and then takes the average. Because we're doing so little
|
||||||
|
work in this example, we have a `1 ns/iter (+/- 0)`, but this would show
|
||||||
|
the variance if there was one.
|
||||||
|
|
||||||
|
Advice on writing benchmarks:
|
||||||
|
|
||||||
|
|
||||||
|
* Move setup code outside the `iter` loop; only put the part you want to measure inside
|
||||||
|
* Make the code do "the same thing" on each iteration; do not accumulate or change state
|
||||||
|
* Make the outer function idempotent too; the benchmark runner is likely to run
|
||||||
|
it many times
|
||||||
|
* Make the inner `iter` loop short and fast so benchmark runs are fast and the
|
||||||
|
calibrator can adjust the run-length at fine resolution
|
||||||
|
* Make the code in the `iter` loop do something simple, to assist in pinpointing
|
||||||
|
performance improvements (or regressions)
|
||||||
|
|
||||||
|
## Gotcha: optimizations
|
||||||
|
|
||||||
|
There's another tricky part to writing benchmarks: benchmarks compiled with
|
||||||
|
optimizations activated can be dramatically changed by the optimizer so that
|
||||||
|
the benchmark is no longer benchmarking what one expects. For example, the
|
||||||
|
compiler might recognize that some calculation has no external effects and
|
||||||
|
remove it entirely.
|
||||||
|
|
||||||
|
```{rust,ignore}
|
||||||
|
#![feature(test)]
|
||||||
|
|
||||||
|
extern crate test;
|
||||||
|
use test::Bencher;
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn bench_xor_1000_ints(b: &mut Bencher) {
|
||||||
|
b.iter(|| {
|
||||||
|
(0..1000).fold(0, |old, new| old ^ new);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
gives the following results
|
||||||
|
|
||||||
|
```text
|
||||||
|
running 1 test
|
||||||
|
test bench_xor_1000_ints ... bench: 0 ns/iter (+/- 0)
|
||||||
|
|
||||||
|
test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured
|
||||||
|
```
|
||||||
|
|
||||||
|
The benchmarking runner offers two ways to avoid this. Either, the closure that
|
||||||
|
the `iter` method receives can return an arbitrary value which forces the
|
||||||
|
optimizer to consider the result used and ensures it cannot remove the
|
||||||
|
computation entirely. This could be done for the example above by adjusting the
|
||||||
|
`b.iter` call to
|
||||||
|
|
||||||
|
```rust
|
||||||
|
# struct X;
|
||||||
|
# impl X { fn iter<T, F>(&self, _: F) where F: FnMut() -> T {} } let b = X;
|
||||||
|
b.iter(|| {
|
||||||
|
// note lack of `;` (could also use an explicit `return`).
|
||||||
|
(0..1000).fold(0, |old, new| old ^ new)
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, the other option is to call the generic `test::black_box` function, which
|
||||||
|
is an opaque "black box" to the optimizer and so forces it to consider any
|
||||||
|
argument as used.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
#![feature(test)]
|
||||||
|
|
||||||
|
extern crate test;
|
||||||
|
|
||||||
|
# fn main() {
|
||||||
|
# struct X;
|
||||||
|
# impl X { fn iter<T, F>(&self, _: F) where F: FnMut() -> T {} } let b = X;
|
||||||
|
b.iter(|| {
|
||||||
|
let n = test::black_box(1000);
|
||||||
|
|
||||||
|
(0..n).fold(0, |a, b| a ^ b)
|
||||||
|
})
|
||||||
|
# }
|
||||||
|
```
|
||||||
|
|
||||||
|
Neither of these read or modify the value, and are very cheap for small values.
|
||||||
|
Larger values can be passed indirectly to reduce overhead (e.g.
|
||||||
|
`black_box(&huge_struct)`).
|
||||||
|
|
||||||
|
Performing either of the above changes gives the following benchmarking results
|
||||||
|
|
||||||
|
```text
|
||||||
|
running 1 test
|
||||||
|
test bench_xor_1000_ints ... bench: 131 ns/iter (+/- 3)
|
||||||
|
|
||||||
|
test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured
|
||||||
|
```
|
||||||
|
|
||||||
|
However, the optimizer can still modify a testcase in an undesirable manner
|
||||||
|
even when using either of the above.
|
|
@ -280,13 +280,15 @@ it returns an `Result<T, E>`, and because this is just an example, we `unwrap()`
|
||||||
it to get a reference to the data. Real code would have more robust error handling
|
it to get a reference to the data. Real code would have more robust error handling
|
||||||
here. We're then free to mutate it, since we have the lock.
|
here. We're then free to mutate it, since we have the lock.
|
||||||
|
|
||||||
This timer bit is a bit awkward, however. We have picked a reasonable amount of
|
Lastly, while the threads are running, we wait on a short timer. But
|
||||||
time to wait, but it's entirely possible that we've picked too high, and that
|
this is not ideal: we may have picked a reasonable amount of time to
|
||||||
we could be taking less time. It's also possible that we've picked too low,
|
wait but it's more likely we'll either be waiting longer than
|
||||||
and that we aren't actually finishing this computation.
|
necessary or not long enough, depending on just how much time the
|
||||||
|
threads actually take to finish computing when the program runs.
|
||||||
|
|
||||||
Rust's standard library provides a few more mechanisms for two threads to
|
A more precise alternative to the timer would be to use one of the
|
||||||
synchronize with each other. Let's talk about one: channels.
|
mechanisms provided by the Rust standard library for synchronizing
|
||||||
|
threads with each other. Let's talk about one of them: channels.
|
||||||
|
|
||||||
## Channels
|
## Channels
|
||||||
|
|
||||||
|
|
|
@ -243,11 +243,12 @@ for num in nums.iter() {
|
||||||
```
|
```
|
||||||
|
|
||||||
These two basic iterators should serve you well. There are some more
|
These two basic iterators should serve you well. There are some more
|
||||||
advanced iterators, including ones that are infinite. Like `count`:
|
advanced iterators, including ones that are infinite. Like using range syntax
|
||||||
|
and `step_by`:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# #![feature(core)]
|
# #![feature(step_by)]
|
||||||
std::iter::count(1, 5);
|
(1..).step_by(5);
|
||||||
```
|
```
|
||||||
|
|
||||||
This iterator counts up from one, adding five each time. It will give
|
This iterator counts up from one, adding five each time. It will give
|
||||||
|
@ -292,11 +293,11 @@ just use `for` instead.
|
||||||
There are tons of interesting iterator adapters. `take(n)` will return an
|
There are tons of interesting iterator adapters. `take(n)` will return an
|
||||||
iterator over the next `n` elements of the original iterator, note that this
|
iterator over the next `n` elements of the original iterator, note that this
|
||||||
has no side effect on the original iterator. Let's try it out with our infinite
|
has no side effect on the original iterator. Let's try it out with our infinite
|
||||||
iterator from before, `count()`:
|
iterator from before:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# #![feature(core)]
|
# #![feature(step_by)]
|
||||||
for i in std::iter::count(1, 5).take(5) {
|
for i in (1..).step_by(5).take(5) {
|
||||||
println!("{}", i);
|
println!("{}", i);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -37,7 +37,7 @@ number of elements.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let x: Vec<u32> = vec![1, 2, 3];
|
let x: Vec<u32> = vec![1, 2, 3];
|
||||||
# assert_eq!(&[1,2,3], &x);
|
# assert_eq!(x, [1, 2, 3]);
|
||||||
```
|
```
|
||||||
|
|
||||||
This can't be an ordinary function, because it takes any number of arguments.
|
This can't be an ordinary function, because it takes any number of arguments.
|
||||||
|
@ -51,7 +51,7 @@ let x: Vec<u32> = {
|
||||||
temp_vec.push(3);
|
temp_vec.push(3);
|
||||||
temp_vec
|
temp_vec
|
||||||
};
|
};
|
||||||
# assert_eq!(&[1,2,3], &x);
|
# assert_eq!(x, [1, 2, 3]);
|
||||||
```
|
```
|
||||||
|
|
||||||
We can implement this shorthand, using a macro: [^actual]
|
We can implement this shorthand, using a macro: [^actual]
|
||||||
|
@ -73,7 +73,7 @@ macro_rules! vec {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
# fn main() {
|
# fn main() {
|
||||||
# assert_eq!([1,2,3], vec![1,2,3]);
|
# assert_eq!(vec![1,2,3], [1, 2, 3]);
|
||||||
# }
|
# }
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -477,7 +477,7 @@ forbidden in item signatures to allow reasoning about the types just based in
|
||||||
the item signature alone. However, for ergonomic reasons a very restricted
|
the item signature alone. However, for ergonomic reasons a very restricted
|
||||||
secondary inference algorithm called “lifetime elision” applies in function
|
secondary inference algorithm called “lifetime elision” applies in function
|
||||||
signatures. It infers only based on the signature components themselves and not
|
signatures. It infers only based on the signature components themselves and not
|
||||||
based on the body of the function, only infers lifetime paramters, and does
|
based on the body of the function, only infers lifetime parameters, and does
|
||||||
this with only three easily memorizable and unambiguous rules. This makes
|
this with only three easily memorizable and unambiguous rules. This makes
|
||||||
lifetime elision a shorthand for writing an item signature, while not hiding
|
lifetime elision a shorthand for writing an item signature, while not hiding
|
||||||
away the actual types involved as full local inference would if applied to it.
|
away the actual types involved as full local inference would if applied to it.
|
||||||
|
|
|
@ -430,149 +430,3 @@ documentation tests: the `_0` is generated for the module test, and `add_two_0`
|
||||||
for the function test. These will auto increment with names like `add_two_1` as
|
for the function test. These will auto increment with names like `add_two_1` as
|
||||||
you add more examples.
|
you add more examples.
|
||||||
|
|
||||||
# Benchmark tests
|
|
||||||
|
|
||||||
Rust also supports benchmark tests, which can test the performance of your
|
|
||||||
code. Let's make our `src/lib.rs` look like this (comments elided):
|
|
||||||
|
|
||||||
```{rust,ignore}
|
|
||||||
extern crate test;
|
|
||||||
|
|
||||||
pub fn add_two(a: i32) -> i32 {
|
|
||||||
a + 2
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use test::Bencher;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn it_works() {
|
|
||||||
assert_eq!(4, add_two(2));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
fn bench_add_two(b: &mut Bencher) {
|
|
||||||
b.iter(|| add_two(2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
We've imported the `test` crate, which contains our benchmarking support.
|
|
||||||
We have a new function as well, with the `bench` attribute. Unlike regular
|
|
||||||
tests, which take no arguments, benchmark tests take a `&mut Bencher`. This
|
|
||||||
`Bencher` provides an `iter` method, which takes a closure. This closure
|
|
||||||
contains the code we'd like to benchmark.
|
|
||||||
|
|
||||||
We can run benchmark tests with `cargo bench`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ cargo bench
|
|
||||||
Compiling adder v0.0.1 (file:///home/steve/tmp/adder)
|
|
||||||
Running target/release/adder-91b3e234d4ed382a
|
|
||||||
|
|
||||||
running 2 tests
|
|
||||||
test tests::it_works ... ignored
|
|
||||||
test tests::bench_add_two ... bench: 1 ns/iter (+/- 0)
|
|
||||||
|
|
||||||
test result: ok. 0 passed; 0 failed; 1 ignored; 1 measured
|
|
||||||
```
|
|
||||||
|
|
||||||
Our non-benchmark test was ignored. You may have noticed that `cargo bench`
|
|
||||||
takes a bit longer than `cargo test`. This is because Rust runs our benchmark
|
|
||||||
a number of times, and then takes the average. Because we're doing so little
|
|
||||||
work in this example, we have a `1 ns/iter (+/- 0)`, but this would show
|
|
||||||
the variance if there was one.
|
|
||||||
|
|
||||||
Advice on writing benchmarks:
|
|
||||||
|
|
||||||
|
|
||||||
* Move setup code outside the `iter` loop; only put the part you want to measure inside
|
|
||||||
* Make the code do "the same thing" on each iteration; do not accumulate or change state
|
|
||||||
* Make the outer function idempotent too; the benchmark runner is likely to run
|
|
||||||
it many times
|
|
||||||
* Make the inner `iter` loop short and fast so benchmark runs are fast and the
|
|
||||||
calibrator can adjust the run-length at fine resolution
|
|
||||||
* Make the code in the `iter` loop do something simple, to assist in pinpointing
|
|
||||||
performance improvements (or regressions)
|
|
||||||
|
|
||||||
## Gotcha: optimizations
|
|
||||||
|
|
||||||
There's another tricky part to writing benchmarks: benchmarks compiled with
|
|
||||||
optimizations activated can be dramatically changed by the optimizer so that
|
|
||||||
the benchmark is no longer benchmarking what one expects. For example, the
|
|
||||||
compiler might recognize that some calculation has no external effects and
|
|
||||||
remove it entirely.
|
|
||||||
|
|
||||||
```{rust,ignore}
|
|
||||||
extern crate test;
|
|
||||||
use test::Bencher;
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
fn bench_xor_1000_ints(b: &mut Bencher) {
|
|
||||||
b.iter(|| {
|
|
||||||
(0..1000).fold(0, |old, new| old ^ new);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
gives the following results
|
|
||||||
|
|
||||||
```text
|
|
||||||
running 1 test
|
|
||||||
test bench_xor_1000_ints ... bench: 0 ns/iter (+/- 0)
|
|
||||||
|
|
||||||
test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured
|
|
||||||
```
|
|
||||||
|
|
||||||
The benchmarking runner offers two ways to avoid this. Either, the closure that
|
|
||||||
the `iter` method receives can return an arbitrary value which forces the
|
|
||||||
optimizer to consider the result used and ensures it cannot remove the
|
|
||||||
computation entirely. This could be done for the example above by adjusting the
|
|
||||||
`b.iter` call to
|
|
||||||
|
|
||||||
```rust
|
|
||||||
# struct X;
|
|
||||||
# impl X { fn iter<T, F>(&self, _: F) where F: FnMut() -> T {} } let b = X;
|
|
||||||
b.iter(|| {
|
|
||||||
// note lack of `;` (could also use an explicit `return`).
|
|
||||||
(0..1000).fold(0, |old, new| old ^ new)
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
Or, the other option is to call the generic `test::black_box` function, which
|
|
||||||
is an opaque "black box" to the optimizer and so forces it to consider any
|
|
||||||
argument as used.
|
|
||||||
|
|
||||||
```rust
|
|
||||||
# #![feature(test)]
|
|
||||||
|
|
||||||
extern crate test;
|
|
||||||
|
|
||||||
# fn main() {
|
|
||||||
# struct X;
|
|
||||||
# impl X { fn iter<T, F>(&self, _: F) where F: FnMut() -> T {} } let b = X;
|
|
||||||
b.iter(|| {
|
|
||||||
let n = test::black_box(1000);
|
|
||||||
|
|
||||||
(0..n).fold(0, |a, b| a ^ b)
|
|
||||||
})
|
|
||||||
# }
|
|
||||||
```
|
|
||||||
|
|
||||||
Neither of these read or modify the value, and are very cheap for small values.
|
|
||||||
Larger values can be passed indirectly to reduce overhead (e.g.
|
|
||||||
`black_box(&huge_struct)`).
|
|
||||||
|
|
||||||
Performing either of the above changes gives the following benchmarking results
|
|
||||||
|
|
||||||
```text
|
|
||||||
running 1 test
|
|
||||||
test bench_xor_1000_ints ... bench: 131 ns/iter (+/- 3)
|
|
||||||
|
|
||||||
test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured
|
|
||||||
```
|
|
||||||
|
|
||||||
However, the optimizer can still modify a testcase in an undesirable manner
|
|
||||||
even when using either of the above.
|
|
||||||
|
|
|
@ -277,6 +277,29 @@ One last thing about traits: generic functions with a trait bound use
|
||||||
dispatched. What's that mean? Check out the chapter on [static and dynamic
|
dispatched. What's that mean? Check out the chapter on [static and dynamic
|
||||||
dispatch](static-and-dynamic-dispatch.html) for more.
|
dispatch](static-and-dynamic-dispatch.html) for more.
|
||||||
|
|
||||||
|
## Multiple trait bounds
|
||||||
|
|
||||||
|
You’ve seen that you can bound a generic type parameter with a trait:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
fn foo<T: Clone>(x: T) {
|
||||||
|
x.clone();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If you need more than one bound, you can use `+`:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
|
fn foo<T: Clone + Debug>(x: T) {
|
||||||
|
x.clone();
|
||||||
|
println!("{:?}", x);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`T` now needs to be both `Clone` as well as `Debug`.
|
||||||
|
|
||||||
## Where clause
|
## Where clause
|
||||||
|
|
||||||
Writing functions with only a few generic types and a small number of trait
|
Writing functions with only a few generic types and a small number of trait
|
||||||
|
|
|
@ -110,7 +110,7 @@ use heap::deallocate;
|
||||||
/// let child_numbers = shared_numbers.clone();
|
/// let child_numbers = shared_numbers.clone();
|
||||||
///
|
///
|
||||||
/// thread::spawn(move || {
|
/// thread::spawn(move || {
|
||||||
/// let local_numbers = child_numbers.as_slice();
|
/// let local_numbers = &child_numbers[..];
|
||||||
///
|
///
|
||||||
/// // Work with the local numbers
|
/// // Work with the local numbers
|
||||||
/// });
|
/// });
|
||||||
|
|
|
@ -51,13 +51,15 @@ use core::prelude::*;
|
||||||
use core::any::Any;
|
use core::any::Any;
|
||||||
use core::cmp::Ordering;
|
use core::cmp::Ordering;
|
||||||
use core::default::Default;
|
use core::default::Default;
|
||||||
use core::error::{Error, FromError};
|
use core::error::Error;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::hash::{self, Hash};
|
use core::hash::{self, Hash};
|
||||||
use core::mem;
|
use core::mem;
|
||||||
use core::ops::{Deref, DerefMut};
|
use core::ops::{Deref, DerefMut};
|
||||||
use core::ptr::Unique;
|
use core::ptr::{self, Unique};
|
||||||
use core::raw::TraitObject;
|
use core::raw::{TraitObject, Slice};
|
||||||
|
|
||||||
|
use heap;
|
||||||
|
|
||||||
/// A value that represents the heap. This is the default place that the `box`
|
/// A value that represents the heap. This is the default place that the `box`
|
||||||
/// keyword allocates into when no place is supplied.
|
/// keyword allocates into when no place is supplied.
|
||||||
|
@ -233,24 +235,10 @@ impl<T: ?Sized + Hash> Hash for Box<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extension methods for an owning `Any` trait object.
|
impl Box<Any> {
|
||||||
#[unstable(feature = "alloc",
|
|
||||||
reason = "this trait will likely disappear once compiler bugs blocking \
|
|
||||||
a direct impl on `Box<Any>` have been fixed ")]
|
|
||||||
// FIXME(#18737): this should be a direct impl on `Box<Any>`. If you're
|
|
||||||
// removing this please make sure that you can downcase on
|
|
||||||
// `Box<Any + Send>` as well as `Box<Any>`
|
|
||||||
pub trait BoxAny {
|
|
||||||
/// Returns the boxed value if it is of type `T`, or
|
|
||||||
/// `Err(Self)` if it isn't.
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
impl BoxAny for Box<Any> {
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any>> {
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any>> {
|
||||||
if self.is::<T>() {
|
if self.is::<T>() {
|
||||||
unsafe {
|
unsafe {
|
||||||
// Get the raw representation of the trait object
|
// Get the raw representation of the trait object
|
||||||
|
@ -267,10 +255,10 @@ impl BoxAny for Box<Any> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
impl Box<Any+Send> {
|
||||||
impl BoxAny for Box<Any+Send> {
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any>> {
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any>> {
|
||||||
<Box<Any>>::downcast(self)
|
<Box<Any>>::downcast(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -322,8 +310,48 @@ impl<I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for Box<I> {
|
||||||
impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for Box<I> {}
|
impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for Box<I> {}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<'a, E: Error + 'a> FromError<E> for Box<Error + 'a> {
|
impl<'a, E: Error + 'a> From<E> for Box<Error + 'a> {
|
||||||
fn from_error(err: E) -> Box<Error + 'a> {
|
fn from(err: E) -> Box<Error + 'a> {
|
||||||
Box::new(err)
|
Box::new(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, E: Error + Send + 'a> From<E> for Box<Error + Send + 'a> {
|
||||||
|
fn from(err: E) -> Box<Error + Send + 'a> {
|
||||||
|
Box::new(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, 'b> From<&'b str> for Box<Error + Send + 'a> {
|
||||||
|
fn from(err: &'b str) -> Box<Error + Send + 'a> {
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct StringError(Box<str>);
|
||||||
|
impl Error for StringError {
|
||||||
|
fn description(&self) -> &str { &self.0 }
|
||||||
|
}
|
||||||
|
impl fmt::Display for StringError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
self.0.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unfortunately `String` is located in libcollections, so we construct
|
||||||
|
// a `Box<str>` manually here.
|
||||||
|
unsafe {
|
||||||
|
let alloc = if err.len() == 0 {
|
||||||
|
0 as *mut u8
|
||||||
|
} else {
|
||||||
|
let ptr = heap::allocate(err.len(), 1);
|
||||||
|
if ptr.is_null() { ::oom(); }
|
||||||
|
ptr as *mut u8
|
||||||
|
};
|
||||||
|
ptr::copy(err.as_bytes().as_ptr(), alloc, err.len());
|
||||||
|
Box::new(StringError(mem::transmute(Slice {
|
||||||
|
data: alloc,
|
||||||
|
len: err.len(),
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ use core::clone::Clone;
|
||||||
|
|
||||||
use std::boxed;
|
use std::boxed;
|
||||||
use std::boxed::Box;
|
use std::boxed::Box;
|
||||||
use std::boxed::BoxAny;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_owned_clone() {
|
fn test_owned_clone() {
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
//! [sieve]: http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
|
//! [sieve]: http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! # #![feature(collections, core)]
|
//! # #![feature(collections, core, step_by)]
|
||||||
//! use std::collections::{BitSet, BitVec};
|
//! use std::collections::{BitSet, BitVec};
|
||||||
//! use std::num::Float;
|
//! use std::num::Float;
|
||||||
//! use std::iter;
|
//! use std::iter;
|
||||||
|
@ -60,7 +60,7 @@
|
||||||
//! if bv[i] {
|
//! if bv[i] {
|
||||||
//! // Mark all multiples of i as non-prime (any multiples below i * i
|
//! // Mark all multiples of i as non-prime (any multiples below i * i
|
||||||
//! // will have been marked as non-prime previously)
|
//! // will have been marked as non-prime previously)
|
||||||
//! for j in iter::range_step(i * i, max_prime, i) { bv.set(j, false) }
|
//! for j in (i * i..max_prime).step_by(i) { bv.set(j, false) }
|
||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
//! BitSet::from_bit_vec(bv)
|
//! BitSet::from_bit_vec(bv)
|
||||||
|
@ -1264,14 +1264,6 @@ impl BitSet {
|
||||||
BitSet { bit_vec: bit_vec }
|
BitSet { bit_vec: bit_vec }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deprecated: use `from_bit_vec`.
|
|
||||||
#[inline]
|
|
||||||
#[deprecated(since = "1.0.0", reason = "renamed to from_bit_vec")]
|
|
||||||
#[unstable(feature = "collections")]
|
|
||||||
pub fn from_bitv(bit_vec: BitVec) -> BitSet {
|
|
||||||
BitSet { bit_vec: bit_vec }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the capacity in bits for this bit vector. Inserting any
|
/// Returns the capacity in bits for this bit vector. Inserting any
|
||||||
/// element less than this amount will not trigger a resizing.
|
/// element less than this amount will not trigger a resizing.
|
||||||
///
|
///
|
||||||
|
|
|
@ -40,6 +40,24 @@ use self::Cow::*;
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub trait Borrow<Borrowed: ?Sized> {
|
pub trait Borrow<Borrowed: ?Sized> {
|
||||||
/// Immutably borrow from an owned value.
|
/// Immutably borrow from an owned value.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::borrow::Borrow;
|
||||||
|
///
|
||||||
|
/// fn check<T: Borrow<str>>(s: T) {
|
||||||
|
/// assert_eq!("Hello", s.borrow());
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// let s = "Hello".to_string();
|
||||||
|
///
|
||||||
|
/// check(s);
|
||||||
|
///
|
||||||
|
/// let s = "Hello";
|
||||||
|
///
|
||||||
|
/// check(s);
|
||||||
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn borrow(&self) -> &Borrowed;
|
fn borrow(&self) -> &Borrowed;
|
||||||
}
|
}
|
||||||
|
@ -50,6 +68,20 @@ pub trait Borrow<Borrowed: ?Sized> {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub trait BorrowMut<Borrowed: ?Sized> : Borrow<Borrowed> {
|
pub trait BorrowMut<Borrowed: ?Sized> : Borrow<Borrowed> {
|
||||||
/// Mutably borrow from an owned value.
|
/// Mutably borrow from an owned value.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::borrow::BorrowMut;
|
||||||
|
///
|
||||||
|
/// fn check<T: BorrowMut<[i32]>>(mut v: T) {
|
||||||
|
/// assert_eq!(&mut [1, 2, 3], v.borrow_mut());
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// let v = vec![1, 2, 3];
|
||||||
|
///
|
||||||
|
/// check(v);
|
||||||
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn borrow_mut(&mut self) -> &mut Borrowed;
|
fn borrow_mut(&mut self) -> &mut Borrowed;
|
||||||
}
|
}
|
||||||
|
@ -171,6 +203,18 @@ impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned {
|
||||||
/// Acquire a mutable reference to the owned form of the data.
|
/// Acquire a mutable reference to the owned form of the data.
|
||||||
///
|
///
|
||||||
/// Copies the data if it is not already owned.
|
/// Copies the data if it is not already owned.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::borrow::Cow;
|
||||||
|
///
|
||||||
|
/// let mut cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
|
||||||
|
///
|
||||||
|
/// let hello = cow.to_mut();
|
||||||
|
///
|
||||||
|
/// assert_eq!(hello, &[1, 2, 3]);
|
||||||
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {
|
pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {
|
||||||
match *self {
|
match *self {
|
||||||
|
@ -185,6 +229,18 @@ impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned {
|
||||||
/// Extract the owned data.
|
/// Extract the owned data.
|
||||||
///
|
///
|
||||||
/// Copies the data if it is not already owned.
|
/// Copies the data if it is not already owned.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::borrow::Cow;
|
||||||
|
///
|
||||||
|
/// let cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
|
||||||
|
///
|
||||||
|
/// let hello = cow.into_owned();
|
||||||
|
///
|
||||||
|
/// assert_eq!(vec![1, 2, 3], hello);
|
||||||
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn into_owned(self) -> <B as ToOwned>::Owned {
|
pub fn into_owned(self) -> <B as ToOwned>::Owned {
|
||||||
match self {
|
match self {
|
||||||
|
@ -192,26 +248,6 @@ impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned {
|
||||||
Owned(owned) => owned
|
Owned(owned) => owned
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this `Cow` wraps a borrowed value
|
|
||||||
#[deprecated(since = "1.0.0", reason = "match on the enum instead")]
|
|
||||||
#[unstable(feature = "std_misc")]
|
|
||||||
pub fn is_borrowed(&self) -> bool {
|
|
||||||
match *self {
|
|
||||||
Borrowed(_) => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if this `Cow` wraps an owned value
|
|
||||||
#[deprecated(since = "1.0.0", reason = "match on the enum instead")]
|
|
||||||
#[unstable(feature = "std_misc")]
|
|
||||||
pub fn is_owned(&self) -> bool {
|
|
||||||
match *self {
|
|
||||||
Owned(_) => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
|
@ -1134,8 +1134,7 @@ impl<'a, K: Ord, V> Entry<'a, K, V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "collections",
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
reason = "matches entry v3 specification, waiting for dust to settle")]
|
|
||||||
/// Ensures a value is in the entry by inserting the default if empty, and returns
|
/// Ensures a value is in the entry by inserting the default if empty, and returns
|
||||||
/// a mutable reference to the value in the entry.
|
/// a mutable reference to the value in the entry.
|
||||||
pub fn or_insert(self, default: V) -> &'a mut V {
|
pub fn or_insert(self, default: V) -> &'a mut V {
|
||||||
|
@ -1145,8 +1144,7 @@ impl<'a, K: Ord, V> Entry<'a, K, V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "collections",
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
reason = "matches entry v3 specification, waiting for dust to settle")]
|
|
||||||
/// Ensures a value is in the entry by inserting the result of the default function if empty,
|
/// Ensures a value is in the entry by inserting the result of the default function if empty,
|
||||||
/// and returns a mutable reference to the value in the entry.
|
/// and returns a mutable reference to the value in the entry.
|
||||||
pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
|
pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
|
||||||
|
|
|
@ -38,7 +38,6 @@
|
||||||
#![feature(unsafe_no_drop_flag, filling_drop)]
|
#![feature(unsafe_no_drop_flag, filling_drop)]
|
||||||
#![feature(step_by)]
|
#![feature(step_by)]
|
||||||
#![feature(str_char)]
|
#![feature(str_char)]
|
||||||
#![feature(convert)]
|
|
||||||
#![feature(slice_patterns)]
|
#![feature(slice_patterns)]
|
||||||
#![feature(debug_builders)]
|
#![feature(debug_builders)]
|
||||||
#![cfg_attr(test, feature(rand, rustc_private, test, hash, collections))]
|
#![cfg_attr(test, feature(rand, rustc_private, test, hash, collections))]
|
||||||
|
@ -68,22 +67,6 @@ pub use string::String;
|
||||||
pub use vec::Vec;
|
pub use vec::Vec;
|
||||||
pub use vec_map::VecMap;
|
pub use vec_map::VecMap;
|
||||||
|
|
||||||
#[deprecated(since = "1.0.0", reason = "renamed to vec_deque")]
|
|
||||||
#[unstable(feature = "collections")]
|
|
||||||
pub use vec_deque as ring_buf;
|
|
||||||
|
|
||||||
#[deprecated(since = "1.0.0", reason = "renamed to linked_list")]
|
|
||||||
#[unstable(feature = "collections")]
|
|
||||||
pub use linked_list as dlist;
|
|
||||||
|
|
||||||
#[deprecated(since = "1.0.0", reason = "renamed to bit_vec")]
|
|
||||||
#[unstable(feature = "collections")]
|
|
||||||
pub use bit_vec as bitv;
|
|
||||||
|
|
||||||
#[deprecated(since = "1.0.0", reason = "renamed to bit_set")]
|
|
||||||
#[unstable(feature = "collections")]
|
|
||||||
pub use bit_set as bitv_set;
|
|
||||||
|
|
||||||
// Needed for the vec! macro
|
// Needed for the vec! macro
|
||||||
pub use alloc::boxed;
|
pub use alloc::boxed;
|
||||||
|
|
||||||
|
@ -108,10 +91,6 @@ pub mod vec_map;
|
||||||
reason = "RFC 509")]
|
reason = "RFC 509")]
|
||||||
pub mod bit_vec {
|
pub mod bit_vec {
|
||||||
pub use bit::{BitVec, Iter};
|
pub use bit::{BitVec, Iter};
|
||||||
|
|
||||||
#[deprecated(since = "1.0.0", reason = "renamed to BitVec")]
|
|
||||||
#[unstable(feature = "collections")]
|
|
||||||
pub use bit::BitVec as Bitv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "collections",
|
#[unstable(feature = "collections",
|
||||||
|
@ -119,10 +98,6 @@ pub mod bit_vec {
|
||||||
pub mod bit_set {
|
pub mod bit_set {
|
||||||
pub use bit::{BitSet, Union, Intersection, Difference, SymmetricDifference};
|
pub use bit::{BitSet, Union, Intersection, Difference, SymmetricDifference};
|
||||||
pub use bit::SetIter as Iter;
|
pub use bit::SetIter as Iter;
|
||||||
|
|
||||||
#[deprecated(since = "1.0.0", reason = "renamed to BitSet")]
|
|
||||||
#[unstable(feature = "collections")]
|
|
||||||
pub use bit::BitSet as BitvSet;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
|
@ -32,10 +32,6 @@ use core::iter::{self, FromIterator, IntoIterator};
|
||||||
use core::mem;
|
use core::mem;
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
|
|
||||||
#[deprecated(since = "1.0.0", reason = "renamed to LinkedList")]
|
|
||||||
#[unstable(feature = "collections")]
|
|
||||||
pub use LinkedList as DList;
|
|
||||||
|
|
||||||
/// A doubly-linked list.
|
/// A doubly-linked list.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct LinkedList<T> {
|
pub struct LinkedList<T> {
|
||||||
|
@ -252,6 +248,7 @@ impl<T> LinkedList<T> {
|
||||||
/// }
|
/// }
|
||||||
/// println!("{}", b.len()); // prints 0
|
/// println!("{}", b.len()); // prints 0
|
||||||
/// ```
|
/// ```
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn append(&mut self, other: &mut LinkedList<T>) {
|
pub fn append(&mut self, other: &mut LinkedList<T>) {
|
||||||
match self.list_tail.resolve() {
|
match self.list_tail.resolve() {
|
||||||
None => {
|
None => {
|
||||||
|
@ -844,7 +841,7 @@ impl<A> ExactSizeIterator for IntoIter<A> {}
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<A> FromIterator<A> for LinkedList<A> {
|
impl<A> FromIterator<A> for LinkedList<A> {
|
||||||
fn from_iter<T: IntoIterator<Item=A>>(iter: T) -> LinkedList<A> {
|
fn from_iter<T: IntoIterator<Item=A>>(iter: T) -> LinkedList<A> {
|
||||||
let mut ret = DList::new();
|
let mut ret = LinkedList::new();
|
||||||
ret.extend(iter);
|
ret.extend(iter);
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
@ -1079,7 +1076,7 @@ mod test {
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
check_links(&n);
|
check_links(&n);
|
||||||
let a: &[_] = &[&1,&2,&3];
|
let a: &[_] = &[&1,&2,&3];
|
||||||
assert_eq!(a, n.iter().collect::<Vec<_>>());
|
assert_eq!(a, &n.iter().collect::<Vec<_>>()[..]);
|
||||||
}).join().ok().unwrap();
|
}).join().ok().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,8 +89,6 @@ use core::iter::MultiplicativeIterator;
|
||||||
use core::marker::Sized;
|
use core::marker::Sized;
|
||||||
use core::mem::size_of;
|
use core::mem::size_of;
|
||||||
use core::mem;
|
use core::mem;
|
||||||
#[cfg(stage0)]
|
|
||||||
use core::num::wrapping::WrappingOps;
|
|
||||||
use core::ops::FnMut;
|
use core::ops::FnMut;
|
||||||
use core::option::Option::{self, Some, None};
|
use core::option::Option::{self, Some, None};
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
|
@ -107,7 +105,6 @@ pub use core::slice::{IntSliceExt, SplitMut, ChunksMut, Split};
|
||||||
pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut};
|
pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut};
|
||||||
pub use core::slice::{bytes, mut_ref_slice, ref_slice};
|
pub use core::slice::{bytes, mut_ref_slice, ref_slice};
|
||||||
pub use core::slice::{from_raw_parts, from_raw_parts_mut};
|
pub use core::slice::{from_raw_parts, from_raw_parts_mut};
|
||||||
pub use core::slice::{from_raw_buf, from_raw_mut_buf};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Basic slice extension methods
|
// Basic slice extension methods
|
||||||
|
@ -281,33 +278,6 @@ impl<T> [T] {
|
||||||
cmp::min(self.len(), end-start)
|
cmp::min(self.len(), end-start)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deprecated: use `&s[start .. end]` notation instead.
|
|
||||||
#[unstable(feature = "collections",
|
|
||||||
reason = "will be replaced by slice syntax")]
|
|
||||||
#[deprecated(since = "1.0.0", reason = "use &s[start .. end] instead")]
|
|
||||||
#[inline]
|
|
||||||
pub fn slice(&self, start: usize, end: usize) -> &[T] {
|
|
||||||
&self[start .. end]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deprecated: use `&s[start..]` notation instead.
|
|
||||||
#[unstable(feature = "collections",
|
|
||||||
reason = "will be replaced by slice syntax")]
|
|
||||||
#[deprecated(since = "1.0.0", reason = "use &s[start..] instead")]
|
|
||||||
#[inline]
|
|
||||||
pub fn slice_from(&self, start: usize) -> &[T] {
|
|
||||||
&self[start ..]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deprecated: use `&s[..end]` notation instead.
|
|
||||||
#[unstable(feature = "collections",
|
|
||||||
reason = "will be replaced by slice syntax")]
|
|
||||||
#[deprecated(since = "1.0.0", reason = "use &s[..end] instead")]
|
|
||||||
#[inline]
|
|
||||||
pub fn slice_to(&self, end: usize) -> &[T] {
|
|
||||||
&self[.. end]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Divides one slice into two at an index.
|
/// Divides one slice into two at an index.
|
||||||
///
|
///
|
||||||
/// The first will contain all indices from `[0, mid)` (excluding
|
/// The first will contain all indices from `[0, mid)` (excluding
|
||||||
|
@ -557,7 +527,6 @@ impl<T> [T] {
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(core)]
|
/// # #![feature(core)]
|
||||||
/// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
|
/// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
|
||||||
/// let s = s.as_slice();
|
|
||||||
///
|
///
|
||||||
/// let seek = 13;
|
/// let seek = 13;
|
||||||
/// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Ok(9));
|
/// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Ok(9));
|
||||||
|
@ -611,42 +580,6 @@ impl<T> [T] {
|
||||||
core_slice::SliceExt::get_mut(self, index)
|
core_slice::SliceExt::get_mut(self, index)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deprecated: use `&mut s[..]` instead.
|
|
||||||
#[unstable(feature = "collections",
|
|
||||||
reason = "will be replaced by slice syntax")]
|
|
||||||
#[deprecated(since = "1.0.0", reason = "use &mut s[..] instead")]
|
|
||||||
#[allow(deprecated)]
|
|
||||||
pub fn as_mut_slice(&mut self) -> &mut [T] {
|
|
||||||
core_slice::SliceExt::as_mut_slice(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deprecated: use `&mut s[start .. end]` instead.
|
|
||||||
#[unstable(feature = "collections",
|
|
||||||
reason = "will be replaced by slice syntax")]
|
|
||||||
#[deprecated(since = "1.0.0", reason = "use &mut s[start .. end] instead")]
|
|
||||||
#[inline]
|
|
||||||
pub fn slice_mut(&mut self, start: usize, end: usize) -> &mut [T] {
|
|
||||||
&mut self[start .. end]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deprecated: use `&mut s[start ..]` instead.
|
|
||||||
#[unstable(feature = "collections",
|
|
||||||
reason = "will be replaced by slice syntax")]
|
|
||||||
#[deprecated(since = "1.0.0", reason = "use &mut s[start ..] instead")]
|
|
||||||
#[inline]
|
|
||||||
pub fn slice_from_mut(&mut self, start: usize) -> &mut [T] {
|
|
||||||
&mut self[start ..]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deprecated: use `&mut s[.. end]` instead.
|
|
||||||
#[unstable(feature = "collections",
|
|
||||||
reason = "will be replaced by slice syntax")]
|
|
||||||
#[deprecated(since = "1.0.0", reason = "use &mut s[.. end] instead")]
|
|
||||||
#[inline]
|
|
||||||
pub fn slice_to_mut(&mut self, end: usize) -> &mut [T] {
|
|
||||||
&mut self[.. end]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns an iterator that allows modifying each value
|
/// Returns an iterator that allows modifying each value
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -924,7 +857,6 @@ impl<T> [T] {
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(core)]
|
/// # #![feature(core)]
|
||||||
/// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
|
/// let s = [0, 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(&13), Ok(9));
|
||||||
/// assert_eq!(s.binary_search(&4), Err(7));
|
/// assert_eq!(s.binary_search(&4), Err(7));
|
||||||
|
@ -937,13 +869,6 @@ impl<T> [T] {
|
||||||
core_slice::SliceExt::binary_search(self, x)
|
core_slice::SliceExt::binary_search(self, x)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deprecated: use `binary_search` instead.
|
|
||||||
#[unstable(feature = "collections")]
|
|
||||||
#[deprecated(since = "1.0.0", reason = "use binary_search instead")]
|
|
||||||
pub fn binary_search_elem(&self, x: &T) -> Result<usize, usize> where T: Ord {
|
|
||||||
self.binary_search(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Mutates the slice to the next lexicographic permutation.
|
/// Mutates the slice to the next lexicographic permutation.
|
||||||
///
|
///
|
||||||
/// Returns `true` if successful and `false` if the slice is at the
|
/// Returns `true` if successful and `false` if the slice is at the
|
||||||
|
|
|
@ -10,13 +10,12 @@
|
||||||
//
|
//
|
||||||
// ignore-lexer-test FIXME #15679
|
// ignore-lexer-test FIXME #15679
|
||||||
|
|
||||||
//! Unicode string manipulation (the [`str`](../primitive.str.html) type).
|
//! Unicode string manipulation (the `str` type).
|
||||||
//!
|
//!
|
||||||
//! Rust's [`str`](../primitive.str.html) type is one of the core primitive
|
//! Rust's `str` type is one of the core primitive types of the language. `&str`
|
||||||
//! types of the language. `&str` is the borrowed string type. This type of
|
//! is the borrowed string type. This type of string can only be created from
|
||||||
//! string can only be created from other strings, unless it is a `&'static str`
|
//! other strings, unless it is a `&'static str` (see below). It is not possible
|
||||||
//! (see below). It is not possible to move out of borrowed strings because they
|
//! to move out of borrowed strings because they are owned elsewhere.
|
||||||
//! are owned elsewhere.
|
|
||||||
//!
|
//!
|
||||||
//! # Examples
|
//! # Examples
|
||||||
//!
|
//!
|
||||||
|
@ -70,11 +69,11 @@ use vec::Vec;
|
||||||
use slice::SliceConcatExt;
|
use slice::SliceConcatExt;
|
||||||
|
|
||||||
pub use core::str::{FromStr, Utf8Error, Str};
|
pub use core::str::{FromStr, Utf8Error, Str};
|
||||||
pub use core::str::{Lines, LinesAny, MatchIndices, SplitStr, CharRange};
|
pub use core::str::{Lines, LinesAny, MatchIndices, CharRange};
|
||||||
pub use core::str::{Split, SplitTerminator, SplitN};
|
pub use core::str::{Split, SplitTerminator, SplitN};
|
||||||
pub use core::str::{RSplit, RSplitN};
|
pub use core::str::{RSplit, RSplitN};
|
||||||
pub use core::str::{from_utf8, CharEq, Chars, CharIndices, Bytes};
|
pub use core::str::{from_utf8, Chars, CharIndices, Bytes};
|
||||||
pub use core::str::{from_utf8_unchecked, from_c_str, ParseBoolError};
|
pub use core::str::{from_utf8_unchecked, ParseBoolError};
|
||||||
pub use unicode::str::{Words, Graphemes, GraphemeIndices};
|
pub use unicode::str::{Words, Graphemes, GraphemeIndices};
|
||||||
pub use core::str::Pattern;
|
pub use core::str::Pattern;
|
||||||
pub use core::str::{Searcher, ReverseSearcher, DoubleEndedSearcher, SearchStep};
|
pub use core::str::{Searcher, ReverseSearcher, DoubleEndedSearcher, SearchStep};
|
||||||
|
@ -536,22 +535,6 @@ impl str {
|
||||||
core_str::StrExt::contains(&self[..], pat)
|
core_str::StrExt::contains(&self[..], pat)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if `self` contains a `char`.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # #![feature(collections)]
|
|
||||||
/// assert!("hello".contains_char('e'));
|
|
||||||
///
|
|
||||||
/// assert!(!"hello".contains_char('z'));
|
|
||||||
/// ```
|
|
||||||
#[unstable(feature = "collections")]
|
|
||||||
#[deprecated(since = "1.0.0", reason = "use `contains()` with a char")]
|
|
||||||
pub fn contains_char<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
|
|
||||||
core_str::StrExt::contains_char(&self[..], pat)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An iterator over the codepoints of `self`.
|
/// An iterator over the codepoints of `self`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
|
@ -778,25 +761,6 @@ impl str {
|
||||||
core_str::StrExt::match_indices(&self[..], pat)
|
core_str::StrExt::match_indices(&self[..], pat)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An iterator over the substrings of `self` separated by a `&str`.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # #![feature(collections)]
|
|
||||||
/// let v: Vec<&str> = "abcXXXabcYYYabc".split_str("abc").collect();
|
|
||||||
/// assert_eq!(v, ["", "XXX", "YYY", ""]);
|
|
||||||
///
|
|
||||||
/// let v: Vec<&str> = "1abcabc2".split_str("abc").collect();
|
|
||||||
/// assert_eq!(v, ["1", "", "2"]);
|
|
||||||
/// ```
|
|
||||||
#[unstable(feature = "collections")]
|
|
||||||
#[deprecated(since = "1.0.0", reason = "use `split()` with a `&str`")]
|
|
||||||
#[allow(deprecated) /* for SplitStr */]
|
|
||||||
pub fn split_str<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitStr<'a, P> {
|
|
||||||
core_str::StrExt::split_str(&self[..], pat)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An iterator over the lines of a string, separated by `\n`.
|
/// An iterator over the lines of a string, separated by `\n`.
|
||||||
///
|
///
|
||||||
/// This does not include the empty string after a trailing `\n`.
|
/// This does not include the empty string after a trailing `\n`.
|
||||||
|
@ -848,31 +812,6 @@ impl str {
|
||||||
pub fn lines_any(&self) -> LinesAny {
|
pub fn lines_any(&self) -> LinesAny {
|
||||||
core_str::StrExt::lines_any(&self[..])
|
core_str::StrExt::lines_any(&self[..])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deprecated: use `s[a .. b]` instead.
|
|
||||||
#[unstable(feature = "collections",
|
|
||||||
reason = "use slice notation [a..b] instead")]
|
|
||||||
#[deprecated(since = "1.0.0", reason = "use slice notation [a..b] instead")]
|
|
||||||
pub fn slice(&self, begin: usize, end: usize) -> &str {
|
|
||||||
&self[begin..end]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deprecated: use `s[a..]` instead.
|
|
||||||
#[unstable(feature = "collections",
|
|
||||||
reason = "use slice notation [a..b] instead")]
|
|
||||||
#[deprecated(since = "1.0.0", reason = "use slice notation [a..] instead")]
|
|
||||||
pub fn slice_from(&self, begin: usize) -> &str {
|
|
||||||
&self[begin..]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deprecated: use `s[..a]` instead.
|
|
||||||
#[unstable(feature = "collections",
|
|
||||||
reason = "use slice notation [a..b] instead")]
|
|
||||||
#[deprecated(since = "1.0.0", reason = "use slice notation [..a] instead")]
|
|
||||||
pub fn slice_to(&self, end: usize) -> &str {
|
|
||||||
&self[..end]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a slice of the string from the character range [`begin`..`end`).
|
/// Returns a slice of the string from the character range [`begin`..`end`).
|
||||||
///
|
///
|
||||||
/// That is, start at the `begin`-th code point of the string and continue
|
/// That is, start at the `begin`-th code point of the string and continue
|
||||||
|
@ -1306,27 +1245,6 @@ impl str {
|
||||||
core_str::StrExt::rfind(&self[..], pat)
|
core_str::StrExt::rfind(&self[..], pat)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the byte index of the first matching substring if it exists.
|
|
||||||
///
|
|
||||||
/// Returns `None` if it doesn't exist.
|
|
||||||
///
|
|
||||||
/// The pattern can be a simple `&str`, or a closure that determines the split.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # #![feature(collections)]
|
|
||||||
/// let s = "Löwe 老虎 Léopard";
|
|
||||||
///
|
|
||||||
/// assert_eq!(s.find_str("老虎 L"), Some(6));
|
|
||||||
/// assert_eq!(s.find_str("muffin man"), None);
|
|
||||||
/// ```
|
|
||||||
#[unstable(feature = "collections")]
|
|
||||||
#[deprecated(since = "1.0.0", reason = "use `find()` with a `&str`")]
|
|
||||||
pub fn find_str<'a, P: Pattern<'a>>(&'a self, needle: P) -> Option<usize> {
|
|
||||||
core_str::StrExt::find_str(&self[..], needle)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Retrieves the first character from a `&str` and returns it.
|
/// Retrieves the first character from a `&str` and returns it.
|
||||||
///
|
///
|
||||||
/// This does not allocate a new string; instead, it returns a slice that points one character
|
/// This does not allocate a new string; instead, it returns a slice that points one character
|
||||||
|
@ -1470,12 +1388,12 @@ impl str {
|
||||||
/// let gr1 = "a\u{310}e\u{301}o\u{308}\u{332}".graphemes(true).collect::<Vec<&str>>();
|
/// let gr1 = "a\u{310}e\u{301}o\u{308}\u{332}".graphemes(true).collect::<Vec<&str>>();
|
||||||
/// let b: &[_] = &["a\u{310}", "e\u{301}", "o\u{308}\u{332}"];
|
/// let b: &[_] = &["a\u{310}", "e\u{301}", "o\u{308}\u{332}"];
|
||||||
///
|
///
|
||||||
/// assert_eq!(gr1.as_slice(), b);
|
/// assert_eq!(&gr1[..], b);
|
||||||
///
|
///
|
||||||
/// let gr2 = "a\r\nb🇷🇺🇸🇹".graphemes(true).collect::<Vec<&str>>();
|
/// let gr2 = "a\r\nb🇷🇺🇸🇹".graphemes(true).collect::<Vec<&str>>();
|
||||||
/// let b: &[_] = &["a", "\r\n", "b", "🇷🇺🇸🇹"];
|
/// let b: &[_] = &["a", "\r\n", "b", "🇷🇺🇸🇹"];
|
||||||
///
|
///
|
||||||
/// assert_eq!(gr2.as_slice(), b);
|
/// assert_eq!(&gr2[..], b);
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "unicode",
|
#[unstable(feature = "unicode",
|
||||||
reason = "this functionality may only be provided by libunicode")]
|
reason = "this functionality may only be provided by libunicode")]
|
||||||
|
@ -1493,7 +1411,7 @@ impl str {
|
||||||
/// let gr_inds = "a̐éö̲\r\n".grapheme_indices(true).collect::<Vec<(usize, &str)>>();
|
/// let gr_inds = "a̐éö̲\r\n".grapheme_indices(true).collect::<Vec<(usize, &str)>>();
|
||||||
/// let b: &[_] = &[(0, "a̐"), (3, "é"), (6, "ö̲"), (11, "\r\n")];
|
/// let b: &[_] = &[(0, "a̐"), (3, "é"), (6, "ö̲"), (11, "\r\n")];
|
||||||
///
|
///
|
||||||
/// assert_eq!(gr_inds.as_slice(), b);
|
/// assert_eq!(&gr_inds[..], b);
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "unicode",
|
#[unstable(feature = "unicode",
|
||||||
reason = "this functionality may only be provided by libunicode")]
|
reason = "this functionality may only be provided by libunicode")]
|
||||||
|
|
|
@ -93,7 +93,7 @@ impl String {
|
||||||
/// ```
|
/// ```
|
||||||
/// # #![feature(collections, core)]
|
/// # #![feature(collections, core)]
|
||||||
/// let s = String::from_str("hello");
|
/// let s = String::from_str("hello");
|
||||||
/// assert_eq!(s.as_slice(), "hello");
|
/// assert_eq!(&s[..], "hello");
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "collections",
|
#[unstable(feature = "collections",
|
||||||
|
@ -364,6 +364,14 @@ impl String {
|
||||||
self.vec
|
self.vec
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Extract a string slice containing the entire string.
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "convert",
|
||||||
|
reason = "waiting on RFC revision")]
|
||||||
|
pub fn as_str(&self) -> &str {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Pushes the given string onto this string buffer.
|
/// Pushes the given string onto this string buffer.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
|
@ -848,7 +856,6 @@ impl<'a, 'b> PartialEq<Cow<'a, str>> for &'b str {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
impl Str for String {
|
impl Str for String {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
fn as_slice(&self) -> &str {
|
fn as_slice(&self) -> &str {
|
||||||
unsafe { mem::transmute(&*self.vec) }
|
unsafe { mem::transmute(&*self.vec) }
|
||||||
}
|
}
|
||||||
|
@ -1072,11 +1079,6 @@ impl<'a> Str for Cow<'a, str> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A clone-on-write string
|
|
||||||
#[deprecated(since = "1.0.0", reason = "use Cow<'a, str> instead")]
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
pub type CowString<'a> = Cow<'a, str>;
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl fmt::Write for String {
|
impl fmt::Write for String {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -389,7 +389,7 @@ impl<T> Vec<T> {
|
||||||
/// Note that this will drop any excess capacity. Calling this and
|
/// Note that this will drop any excess capacity. Calling this and
|
||||||
/// converting back to a vector with `into_vec()` is equivalent to calling
|
/// converting back to a vector with `into_vec()` is equivalent to calling
|
||||||
/// `shrink_to_fit()`.
|
/// `shrink_to_fit()`.
|
||||||
#[unstable(feature = "collections")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn into_boxed_slice(mut self) -> Box<[T]> {
|
pub fn into_boxed_slice(mut self) -> Box<[T]> {
|
||||||
self.shrink_to_fit();
|
self.shrink_to_fit();
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -425,11 +425,18 @@ impl<T> Vec<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Extract a slice containing the entire vector.
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "convert",
|
||||||
|
reason = "waiting on RFC revision")]
|
||||||
|
pub fn as_slice(&self) -> &[T] {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Deprecated: use `&mut s[..]` instead.
|
/// Deprecated: use `&mut s[..]` instead.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "collections",
|
#[unstable(feature = "convert",
|
||||||
reason = "will be replaced by slice syntax")]
|
reason = "waiting on RFC revision")]
|
||||||
#[deprecated(since = "1.0.0", reason = "use &mut s[..] instead")]
|
|
||||||
pub fn as_mut_slice(&mut self) -> &mut [T] {
|
pub fn as_mut_slice(&mut self) -> &mut [T] {
|
||||||
&mut self[..]
|
&mut self[..]
|
||||||
}
|
}
|
||||||
|
@ -823,13 +830,13 @@ impl<T> Vec<T> {
|
||||||
/// # #![feature(collections, core)]
|
/// # #![feature(collections, core)]
|
||||||
/// let v = vec![0, 1, 2];
|
/// let v = vec![0, 1, 2];
|
||||||
/// let w = v.map_in_place(|i| i + 3);
|
/// let w = v.map_in_place(|i| i + 3);
|
||||||
/// assert_eq!(w.as_slice(), [3, 4, 5].as_slice());
|
/// assert_eq!(&w[..], &[3, 4, 5]);
|
||||||
///
|
///
|
||||||
/// #[derive(PartialEq, Debug)]
|
/// #[derive(PartialEq, Debug)]
|
||||||
/// struct Newtype(u8);
|
/// struct Newtype(u8);
|
||||||
/// let bytes = vec![0x11, 0x22];
|
/// let bytes = vec![0x11, 0x22];
|
||||||
/// let newtyped_bytes = bytes.map_in_place(|x| Newtype(x));
|
/// let newtyped_bytes = bytes.map_in_place(|x| Newtype(x));
|
||||||
/// assert_eq!(newtyped_bytes.as_slice(), [Newtype(0x11), Newtype(0x22)].as_slice());
|
/// assert_eq!(&newtyped_bytes[..], &[Newtype(0x11), Newtype(0x22)]);
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "collections",
|
#[unstable(feature = "collections",
|
||||||
reason = "API may change to provide stronger guarantees")]
|
reason = "API may change to provide stronger guarantees")]
|
||||||
|
@ -1533,22 +1540,22 @@ impl<T> Extend<T> for Vec<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
__impl_slice_eq1! { Vec<A>, Vec<B> }
|
__impl_slice_eq1! { Vec<A>, Vec<B> }
|
||||||
__impl_slice_eq2! { Vec<A>, &'b [B] }
|
__impl_slice_eq1! { Vec<A>, &'b [B] }
|
||||||
__impl_slice_eq2! { Vec<A>, &'b mut [B] }
|
__impl_slice_eq1! { Vec<A>, &'b mut [B] }
|
||||||
__impl_slice_eq2! { Cow<'a, [A]>, &'b [B], Clone }
|
__impl_slice_eq1! { Cow<'a, [A]>, &'b [B], Clone }
|
||||||
__impl_slice_eq2! { Cow<'a, [A]>, &'b mut [B], Clone }
|
__impl_slice_eq1! { Cow<'a, [A]>, &'b mut [B], Clone }
|
||||||
__impl_slice_eq2! { Cow<'a, [A]>, Vec<B>, Clone }
|
__impl_slice_eq1! { Cow<'a, [A]>, Vec<B>, Clone }
|
||||||
|
|
||||||
macro_rules! array_impls {
|
macro_rules! array_impls {
|
||||||
($($N: expr)+) => {
|
($($N: expr)+) => {
|
||||||
$(
|
$(
|
||||||
// NOTE: some less important impls are omitted to reduce code bloat
|
// NOTE: some less important impls are omitted to reduce code bloat
|
||||||
__impl_slice_eq2! { Vec<A>, [B; $N] }
|
__impl_slice_eq1! { Vec<A>, [B; $N] }
|
||||||
__impl_slice_eq2! { Vec<A>, &'b [B; $N] }
|
__impl_slice_eq1! { Vec<A>, &'b [B; $N] }
|
||||||
// __impl_slice_eq2! { Vec<A>, &'b mut [B; $N] }
|
// __impl_slice_eq1! { Vec<A>, &'b mut [B; $N] }
|
||||||
// __impl_slice_eq2! { Cow<'a, [A]>, [B; $N], Clone }
|
// __impl_slice_eq1! { Cow<'a, [A]>, [B; $N], Clone }
|
||||||
// __impl_slice_eq2! { Cow<'a, [A]>, &'b [B; $N], Clone }
|
// __impl_slice_eq1! { Cow<'a, [A]>, &'b [B; $N], Clone }
|
||||||
// __impl_slice_eq2! { Cow<'a, [A]>, &'b mut [B; $N], Clone }
|
// __impl_slice_eq1! { Cow<'a, [A]>, &'b mut [B; $N], Clone }
|
||||||
)+
|
)+
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1642,13 +1649,6 @@ impl<T> AsRef<Vec<T>> for Vec<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
impl<T> Into<Vec<T>> for Vec<T> {
|
|
||||||
fn into(self) -> Vec<T> {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T> AsRef<[T]> for Vec<T> {
|
impl<T> AsRef<[T]> for Vec<T> {
|
||||||
fn as_ref(&self) -> &[T] {
|
fn as_ref(&self) -> &[T] {
|
||||||
|
@ -1679,11 +1679,6 @@ impl<'a> From<&'a str> for Vec<u8> {
|
||||||
// Clone-on-write
|
// Clone-on-write
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/// A clone-on-write vector
|
|
||||||
#[deprecated(since = "1.0.0", reason = "use Cow<'a, [T]> instead")]
|
|
||||||
#[unstable(feature = "collections")]
|
|
||||||
pub type CowVec<'a, T> = Cow<'a, [T]>;
|
|
||||||
|
|
||||||
#[unstable(feature = "collections")]
|
#[unstable(feature = "collections")]
|
||||||
impl<'a, T> FromIterator<T> for Cow<'a, [T]> where T: Clone {
|
impl<'a, T> FromIterator<T> for Cow<'a, [T]> where T: Clone {
|
||||||
fn from_iter<I: IntoIterator<Item=T>>(it: I) -> Cow<'a, [T]> {
|
fn from_iter<I: IntoIterator<Item=T>>(it: I) -> Cow<'a, [T]> {
|
||||||
|
|
|
@ -25,8 +25,6 @@ use core::default::Default;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::iter::{self, repeat, FromIterator, IntoIterator, RandomAccessIterator};
|
use core::iter::{self, repeat, FromIterator, IntoIterator, RandomAccessIterator};
|
||||||
use core::mem;
|
use core::mem;
|
||||||
#[cfg(stage0)]
|
|
||||||
use core::num::wrapping::WrappingOps;
|
|
||||||
use core::ops::{Index, IndexMut};
|
use core::ops::{Index, IndexMut};
|
||||||
use core::ptr::{self, Unique};
|
use core::ptr::{self, Unique};
|
||||||
use core::slice;
|
use core::slice;
|
||||||
|
@ -36,10 +34,6 @@ use core::cmp;
|
||||||
|
|
||||||
use alloc::heap;
|
use alloc::heap;
|
||||||
|
|
||||||
#[deprecated(since = "1.0.0", reason = "renamed to VecDeque")]
|
|
||||||
#[unstable(feature = "collections")]
|
|
||||||
pub use VecDeque as RingBuf;
|
|
||||||
|
|
||||||
const INITIAL_CAPACITY: usize = 7; // 2^3 - 1
|
const INITIAL_CAPACITY: usize = 7; // 2^3 - 1
|
||||||
const MINIMUM_CAPACITY: usize = 1; // 2 - 1
|
const MINIMUM_CAPACITY: usize = 1; // 2 - 1
|
||||||
|
|
||||||
|
@ -527,7 +521,8 @@ impl<T> VecDeque<T> {
|
||||||
/// buf.push_back(3);
|
/// buf.push_back(3);
|
||||||
/// buf.push_back(4);
|
/// buf.push_back(4);
|
||||||
/// let b: &[_] = &[&5, &3, &4];
|
/// let b: &[_] = &[&5, &3, &4];
|
||||||
/// assert_eq!(buf.iter().collect::<Vec<&i32>>().as_slice(), b);
|
/// let c: Vec<&i32> = buf.iter().collect();
|
||||||
|
/// assert_eq!(&c[..], b);
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn iter(&self) -> Iter<T> {
|
pub fn iter(&self) -> Iter<T> {
|
||||||
|
@ -1902,7 +1897,7 @@ mod test {
|
||||||
// len is the length *after* insertion
|
// len is the length *after* insertion
|
||||||
for len in 1..cap {
|
for len in 1..cap {
|
||||||
// 0, 1, 2, .., len - 1
|
// 0, 1, 2, .., len - 1
|
||||||
let expected = iter::count(0, 1).take(len).collect();
|
let expected = (0..).take(len).collect();
|
||||||
for tail_pos in 0..cap {
|
for tail_pos in 0..cap {
|
||||||
for to_insert in 0..len {
|
for to_insert in 0..len {
|
||||||
tester.tail = tail_pos;
|
tester.tail = tail_pos;
|
||||||
|
@ -1935,7 +1930,7 @@ mod test {
|
||||||
// len is the length *after* removal
|
// len is the length *after* removal
|
||||||
for len in 0..cap - 1 {
|
for len in 0..cap - 1 {
|
||||||
// 0, 1, 2, .., len - 1
|
// 0, 1, 2, .., len - 1
|
||||||
let expected = iter::count(0, 1).take(len).collect();
|
let expected = (0..).take(len).collect();
|
||||||
for tail_pos in 0..cap {
|
for tail_pos in 0..cap {
|
||||||
for to_remove in 0..len + 1 {
|
for to_remove in 0..len + 1 {
|
||||||
tester.tail = tail_pos;
|
tester.tail = tail_pos;
|
||||||
|
@ -1973,7 +1968,7 @@ mod test {
|
||||||
|
|
||||||
for len in 0..cap + 1 {
|
for len in 0..cap + 1 {
|
||||||
// 0, 1, 2, .., len - 1
|
// 0, 1, 2, .., len - 1
|
||||||
let expected = iter::count(0, 1).take(len).collect();
|
let expected = (0..).take(len).collect();
|
||||||
for tail_pos in 0..max_cap + 1 {
|
for tail_pos in 0..max_cap + 1 {
|
||||||
tester.tail = tail_pos;
|
tester.tail = tail_pos;
|
||||||
tester.head = tail_pos;
|
tester.head = tail_pos;
|
||||||
|
@ -2006,9 +2001,9 @@ mod test {
|
||||||
// index to split at
|
// index to split at
|
||||||
for at in 0..len + 1 {
|
for at in 0..len + 1 {
|
||||||
// 0, 1, 2, .., at - 1 (may be empty)
|
// 0, 1, 2, .., at - 1 (may be empty)
|
||||||
let expected_self = iter::count(0, 1).take(at).collect();
|
let expected_self = (0..).take(at).collect();
|
||||||
// at, at + 1, .., len - 1 (may be empty)
|
// at, at + 1, .., len - 1 (may be empty)
|
||||||
let expected_other = iter::count(at, 1).take(len - at).collect();
|
let expected_other = (at..).take(len - at).collect();
|
||||||
|
|
||||||
for tail_pos in 0..cap {
|
for tail_pos in 0..cap {
|
||||||
tester.tail = tail_pos;
|
tester.tail = tail_pos;
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
|
|
||||||
use std::cmp::Ordering::{Equal, Greater, Less};
|
use std::cmp::Ordering::{Equal, Greater, Less};
|
||||||
use std::collections::{BitSet, BitVec};
|
use std::collections::{BitSet, BitVec};
|
||||||
use std::iter::range_step;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_bit_set_show() {
|
fn test_bit_set_show() {
|
||||||
|
@ -42,7 +41,7 @@ fn test_bit_set_iterator() {
|
||||||
assert_eq!(idxs, [0, 2, 3]);
|
assert_eq!(idxs, [0, 2, 3]);
|
||||||
|
|
||||||
let long: BitSet = (0..10000).filter(|&n| n % 2 == 0).collect();
|
let long: BitSet = (0..10000).filter(|&n| n % 2 == 0).collect();
|
||||||
let real: Vec<_> = range_step(0, 10000, 2).collect();
|
let real: Vec<_> = (0..10000).step_by(2).collect();
|
||||||
|
|
||||||
let idxs: Vec<_> = long.iter().collect();
|
let idxs: Vec<_> = long.iter().collect();
|
||||||
assert_eq!(idxs, real);
|
assert_eq!(idxs, real);
|
||||||
|
|
|
@ -153,19 +153,19 @@ fn test_iterator() {
|
||||||
|
|
||||||
e1.insert(A);
|
e1.insert(A);
|
||||||
let elems: Vec<_> = e1.iter().collect();
|
let elems: Vec<_> = e1.iter().collect();
|
||||||
assert_eq!([A], elems);
|
assert_eq!(elems, [A]);
|
||||||
|
|
||||||
e1.insert(C);
|
e1.insert(C);
|
||||||
let elems: Vec<_> = e1.iter().collect();
|
let elems: Vec<_> = e1.iter().collect();
|
||||||
assert_eq!([A,C], elems);
|
assert_eq!(elems, [A,C]);
|
||||||
|
|
||||||
e1.insert(C);
|
e1.insert(C);
|
||||||
let elems: Vec<_> = e1.iter().collect();
|
let elems: Vec<_> = e1.iter().collect();
|
||||||
assert_eq!([A,C], elems);
|
assert_eq!(elems, [A,C]);
|
||||||
|
|
||||||
e1.insert(B);
|
e1.insert(B);
|
||||||
let elems: Vec<_> = e1.iter().collect();
|
let elems: Vec<_> = e1.iter().collect();
|
||||||
assert_eq!([A,B,C], elems);
|
assert_eq!(elems, [A,B,C]);
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -183,35 +183,35 @@ fn test_operators() {
|
||||||
|
|
||||||
let e_union = e1 | e2;
|
let e_union = e1 | e2;
|
||||||
let elems: Vec<_> = e_union.iter().collect();
|
let elems: Vec<_> = e_union.iter().collect();
|
||||||
assert_eq!([A,B,C], elems);
|
assert_eq!(elems, [A,B,C]);
|
||||||
|
|
||||||
let e_intersection = e1 & e2;
|
let e_intersection = e1 & e2;
|
||||||
let elems: Vec<_> = e_intersection.iter().collect();
|
let elems: Vec<_> = e_intersection.iter().collect();
|
||||||
assert_eq!([C], elems);
|
assert_eq!(elems, [C]);
|
||||||
|
|
||||||
// Another way to express intersection
|
// Another way to express intersection
|
||||||
let e_intersection = e1 - (e1 - e2);
|
let e_intersection = e1 - (e1 - e2);
|
||||||
let elems: Vec<_> = e_intersection.iter().collect();
|
let elems: Vec<_> = e_intersection.iter().collect();
|
||||||
assert_eq!([C], elems);
|
assert_eq!(elems, [C]);
|
||||||
|
|
||||||
let e_subtract = e1 - e2;
|
let e_subtract = e1 - e2;
|
||||||
let elems: Vec<_> = e_subtract.iter().collect();
|
let elems: Vec<_> = e_subtract.iter().collect();
|
||||||
assert_eq!([A], elems);
|
assert_eq!(elems, [A]);
|
||||||
|
|
||||||
// Bitwise XOR of two sets, aka symmetric difference
|
// Bitwise XOR of two sets, aka symmetric difference
|
||||||
let e_symmetric_diff = e1 ^ e2;
|
let e_symmetric_diff = e1 ^ e2;
|
||||||
let elems: Vec<_> = e_symmetric_diff.iter().collect();
|
let elems: Vec<_> = e_symmetric_diff.iter().collect();
|
||||||
assert_eq!([A,B], elems);
|
assert_eq!(elems, [A,B]);
|
||||||
|
|
||||||
// Another way to express symmetric difference
|
// Another way to express symmetric difference
|
||||||
let e_symmetric_diff = (e1 - e2) | (e2 - e1);
|
let e_symmetric_diff = (e1 - e2) | (e2 - e1);
|
||||||
let elems: Vec<_> = e_symmetric_diff.iter().collect();
|
let elems: Vec<_> = e_symmetric_diff.iter().collect();
|
||||||
assert_eq!([A,B], elems);
|
assert_eq!(elems, [A,B]);
|
||||||
|
|
||||||
// Yet another way to express symmetric difference
|
// Yet another way to express symmetric difference
|
||||||
let e_symmetric_diff = (e1 | e2) - (e1 & e2);
|
let e_symmetric_diff = (e1 | e2) - (e1 & e2);
|
||||||
let elems: Vec<_> = e_symmetric_diff.iter().collect();
|
let elems: Vec<_> = e_symmetric_diff.iter().collect();
|
||||||
assert_eq!([A,B], elems);
|
assert_eq!(elems, [A,B]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -13,5 +13,5 @@ use std::fmt;
|
||||||
#[test]
|
#[test]
|
||||||
fn test_format() {
|
fn test_format() {
|
||||||
let s = fmt::format(format_args!("Hello, {}!", "world"));
|
let s = fmt::format(format_args!("Hello, {}!", "world"));
|
||||||
assert_eq!(s.as_slice(), "Hello, world!");
|
assert_eq!(s, "Hello, world!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#![allow(deprecated)]
|
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
#![feature(collections)]
|
#![feature(collections)]
|
||||||
#![feature(core)]
|
#![feature(core)]
|
||||||
|
@ -21,6 +20,7 @@
|
||||||
#![feature(unicode)]
|
#![feature(unicode)]
|
||||||
#![feature(unsafe_destructor)]
|
#![feature(unsafe_destructor)]
|
||||||
#![feature(into_cow)]
|
#![feature(into_cow)]
|
||||||
|
#![feature(step_by)]
|
||||||
#![cfg_attr(test, feature(str_char))]
|
#![cfg_attr(test, feature(str_char))]
|
||||||
|
|
||||||
#[macro_use] extern crate log;
|
#[macro_use] extern crate log;
|
||||||
|
|
|
@ -59,7 +59,7 @@ fn test_from_elem() {
|
||||||
// Test on-heap from_elem.
|
// Test on-heap from_elem.
|
||||||
v = vec![20; 6];
|
v = vec![20; 6];
|
||||||
{
|
{
|
||||||
let v = v.as_slice();
|
let v = &v[..];
|
||||||
assert_eq!(v[0], 20);
|
assert_eq!(v[0], 20);
|
||||||
assert_eq!(v[1], 20);
|
assert_eq!(v[1], 20);
|
||||||
assert_eq!(v[2], 20);
|
assert_eq!(v[2], 20);
|
||||||
|
@ -685,7 +685,7 @@ fn test_capacity() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_slice_2() {
|
fn test_slice_2() {
|
||||||
let v = vec![1, 2, 3, 4, 5];
|
let v = vec![1, 2, 3, 4, 5];
|
||||||
let v = v.slice(1, 3);
|
let v = &v[1..3];
|
||||||
assert_eq!(v.len(), 2);
|
assert_eq!(v.len(), 2);
|
||||||
assert_eq!(v[0], 2);
|
assert_eq!(v[0], 2);
|
||||||
assert_eq!(v[1], 3);
|
assert_eq!(v[1], 3);
|
||||||
|
|
|
@ -83,38 +83,38 @@ fn test_collect() {
|
||||||
fn test_into_bytes() {
|
fn test_into_bytes() {
|
||||||
let data = String::from_str("asdf");
|
let data = String::from_str("asdf");
|
||||||
let buf = data.into_bytes();
|
let buf = data.into_bytes();
|
||||||
assert_eq!(b"asdf", buf);
|
assert_eq!(buf, b"asdf");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_find_str() {
|
fn test_find_str() {
|
||||||
// byte positions
|
// byte positions
|
||||||
assert_eq!("".find_str(""), Some(0));
|
assert_eq!("".find(""), Some(0));
|
||||||
assert!("banana".find_str("apple pie").is_none());
|
assert!("banana".find("apple pie").is_none());
|
||||||
|
|
||||||
let data = "abcabc";
|
let data = "abcabc";
|
||||||
assert_eq!(data[0..6].find_str("ab"), Some(0));
|
assert_eq!(data[0..6].find("ab"), Some(0));
|
||||||
assert_eq!(data[2..6].find_str("ab"), Some(3 - 2));
|
assert_eq!(data[2..6].find("ab"), Some(3 - 2));
|
||||||
assert!(data[2..4].find_str("ab").is_none());
|
assert!(data[2..4].find("ab").is_none());
|
||||||
|
|
||||||
let string = "ประเทศไทย中华Việt Nam";
|
let string = "ประเทศไทย中华Việt Nam";
|
||||||
let mut data = String::from_str(string);
|
let mut data = String::from_str(string);
|
||||||
data.push_str(string);
|
data.push_str(string);
|
||||||
assert!(data.find_str("ไท华").is_none());
|
assert!(data.find("ไท华").is_none());
|
||||||
assert_eq!(data[0..43].find_str(""), Some(0));
|
assert_eq!(data[0..43].find(""), Some(0));
|
||||||
assert_eq!(data[6..43].find_str(""), Some(6 - 6));
|
assert_eq!(data[6..43].find(""), Some(6 - 6));
|
||||||
|
|
||||||
assert_eq!(data[0..43].find_str("ประ"), Some( 0));
|
assert_eq!(data[0..43].find("ประ"), Some( 0));
|
||||||
assert_eq!(data[0..43].find_str("ทศไ"), Some(12));
|
assert_eq!(data[0..43].find("ทศไ"), Some(12));
|
||||||
assert_eq!(data[0..43].find_str("ย中"), Some(24));
|
assert_eq!(data[0..43].find("ย中"), Some(24));
|
||||||
assert_eq!(data[0..43].find_str("iệt"), Some(34));
|
assert_eq!(data[0..43].find("iệt"), Some(34));
|
||||||
assert_eq!(data[0..43].find_str("Nam"), Some(40));
|
assert_eq!(data[0..43].find("Nam"), Some(40));
|
||||||
|
|
||||||
assert_eq!(data[43..86].find_str("ประ"), Some(43 - 43));
|
assert_eq!(data[43..86].find("ประ"), Some(43 - 43));
|
||||||
assert_eq!(data[43..86].find_str("ทศไ"), Some(55 - 43));
|
assert_eq!(data[43..86].find("ทศไ"), Some(55 - 43));
|
||||||
assert_eq!(data[43..86].find_str("ย中"), Some(67 - 43));
|
assert_eq!(data[43..86].find("ย中"), Some(67 - 43));
|
||||||
assert_eq!(data[43..86].find_str("iệt"), Some(77 - 43));
|
assert_eq!(data[43..86].find("iệt"), Some(77 - 43));
|
||||||
assert_eq!(data[43..86].find_str("Nam"), Some(83 - 43));
|
assert_eq!(data[43..86].find("Nam"), Some(83 - 43));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -297,16 +297,16 @@ fn test_replace_2d() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_slice() {
|
fn test_slice() {
|
||||||
assert_eq!("ab", "abc".slice(0, 2));
|
assert_eq!("ab", &"abc"[0..2]);
|
||||||
assert_eq!("bc", "abc".slice(1, 3));
|
assert_eq!("bc", &"abc"[1..3]);
|
||||||
assert_eq!("", "abc".slice(1, 1));
|
assert_eq!("", &"abc"[1..1]);
|
||||||
assert_eq!("\u{65e5}", "\u{65e5}\u{672c}".slice(0, 3));
|
assert_eq!("\u{65e5}", &"\u{65e5}\u{672c}"[0..3]);
|
||||||
|
|
||||||
let data = "ประเทศไทย中华";
|
let data = "ประเทศไทย中华";
|
||||||
assert_eq!("ป", data.slice(0, 3));
|
assert_eq!("ป", &data[0..3]);
|
||||||
assert_eq!("ร", data.slice(3, 6));
|
assert_eq!("ร", &data[3..6]);
|
||||||
assert_eq!("", data.slice(3, 3));
|
assert_eq!("", &data[3..3]);
|
||||||
assert_eq!("华", data.slice(30, 33));
|
assert_eq!("华", &data[30..33]);
|
||||||
|
|
||||||
fn a_million_letter_x() -> String {
|
fn a_million_letter_x() -> String {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
|
@ -328,23 +328,23 @@ fn test_slice() {
|
||||||
}
|
}
|
||||||
let letters = a_million_letter_x();
|
let letters = a_million_letter_x();
|
||||||
assert!(half_a_million_letter_x() ==
|
assert!(half_a_million_letter_x() ==
|
||||||
String::from_str(letters.slice(0, 3 * 500000)));
|
String::from_str(&letters[0..3 * 500000]));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_slice_2() {
|
fn test_slice_2() {
|
||||||
let ss = "中华Việt Nam";
|
let ss = "中华Việt Nam";
|
||||||
|
|
||||||
assert_eq!("华", ss.slice(3, 6));
|
assert_eq!("华", &ss[3..6]);
|
||||||
assert_eq!("Việt Nam", ss.slice(6, 16));
|
assert_eq!("Việt Nam", &ss[6..16]);
|
||||||
|
|
||||||
assert_eq!("ab", "abc".slice(0, 2));
|
assert_eq!("ab", &"abc"[0..2]);
|
||||||
assert_eq!("bc", "abc".slice(1, 3));
|
assert_eq!("bc", &"abc"[1..3]);
|
||||||
assert_eq!("", "abc".slice(1, 1));
|
assert_eq!("", &"abc"[1..1]);
|
||||||
|
|
||||||
assert_eq!("中", ss.slice(0, 3));
|
assert_eq!("中", &ss[0..3]);
|
||||||
assert_eq!("华V", ss.slice(3, 7));
|
assert_eq!("华V", &ss[3..7]);
|
||||||
assert_eq!("", ss.slice(3, 3));
|
assert_eq!("", &ss[3..3]);
|
||||||
/*0: 中
|
/*0: 中
|
||||||
3: 华
|
3: 华
|
||||||
6: V
|
6: V
|
||||||
|
@ -360,20 +360,20 @@ fn test_slice_2() {
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic]
|
#[should_panic]
|
||||||
fn test_slice_fail() {
|
fn test_slice_fail() {
|
||||||
"中华Việt Nam".slice(0, 2);
|
&"中华Việt Nam"[0..2];
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_slice_from() {
|
fn test_slice_from() {
|
||||||
assert_eq!("abcd".slice_from(0), "abcd");
|
assert_eq!(&"abcd"[0..], "abcd");
|
||||||
assert_eq!("abcd".slice_from(2), "cd");
|
assert_eq!(&"abcd"[2..], "cd");
|
||||||
assert_eq!("abcd".slice_from(4), "");
|
assert_eq!(&"abcd"[4..], "");
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_slice_to() {
|
fn test_slice_to() {
|
||||||
assert_eq!("abcd".slice_to(0), "");
|
assert_eq!(&"abcd"[..0], "");
|
||||||
assert_eq!("abcd".slice_to(2), "ab");
|
assert_eq!(&"abcd"[..2], "ab");
|
||||||
assert_eq!("abcd".slice_to(4), "abcd");
|
assert_eq!(&"abcd"[..4], "abcd");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -660,10 +660,10 @@ fn test_contains() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_contains_char() {
|
fn test_contains_char() {
|
||||||
assert!("abc".contains_char('b'));
|
assert!("abc".contains('b'));
|
||||||
assert!("a".contains_char('a'));
|
assert!("a".contains('a'));
|
||||||
assert!(!"abc".contains_char('d'));
|
assert!(!"abc".contains('d'));
|
||||||
assert!(!"".contains_char('a'));
|
assert!(!"".contains('a'));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1445,9 +1445,9 @@ fn test_graphemes() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_split_strator() {
|
fn test_splitator() {
|
||||||
fn t(s: &str, sep: &str, u: &[&str]) {
|
fn t(s: &str, sep: &str, u: &[&str]) {
|
||||||
let v: Vec<&str> = s.split_str(sep).collect();
|
let v: Vec<&str> = s.split(sep).collect();
|
||||||
assert_eq!(v, u);
|
assert_eq!(v, u);
|
||||||
}
|
}
|
||||||
t("--1233345--", "12345", &["--1233345--"]);
|
t("--1233345--", "12345", &["--1233345--"]);
|
||||||
|
@ -1470,9 +1470,9 @@ fn test_split_strator() {
|
||||||
fn test_str_default() {
|
fn test_str_default() {
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
|
|
||||||
fn t<S: Default + Str>() {
|
fn t<S: Default + AsRef<str>>() {
|
||||||
let s: S = Default::default();
|
let s: S = Default::default();
|
||||||
assert_eq!(s.as_slice(), "");
|
assert_eq!(s.as_ref(), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
t::<&str>();
|
t::<&str>();
|
||||||
|
|
|
@ -8,10 +8,10 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::borrow::IntoCow;
|
use std::borrow::{IntoCow, Cow};
|
||||||
use std::iter::repeat;
|
use std::iter::repeat;
|
||||||
use std::str::Utf8Error;
|
use std::str::Utf8Error;
|
||||||
use std::string::{CowString, as_string};
|
use std::string::as_string;
|
||||||
|
|
||||||
use test::Bencher;
|
use test::Bencher;
|
||||||
|
|
||||||
|
@ -52,11 +52,11 @@ fn test_from_utf8() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_from_utf8_lossy() {
|
fn test_from_utf8_lossy() {
|
||||||
let xs = b"hello";
|
let xs = b"hello";
|
||||||
let ys: CowString = "hello".into_cow();
|
let ys: Cow<str> = "hello".into_cow();
|
||||||
assert_eq!(String::from_utf8_lossy(xs), ys);
|
assert_eq!(String::from_utf8_lossy(xs), ys);
|
||||||
|
|
||||||
let xs = "ศไทย中华Việt Nam".as_bytes();
|
let xs = "ศไทย中华Việt Nam".as_bytes();
|
||||||
let ys: CowString = "ศไทย中华Việt Nam".into_cow();
|
let ys: Cow<str> = "ศไทย中华Việt Nam".into_cow();
|
||||||
assert_eq!(String::from_utf8_lossy(xs), ys);
|
assert_eq!(String::from_utf8_lossy(xs), ys);
|
||||||
|
|
||||||
let xs = b"Hello\xC2 There\xFF Goodbye";
|
let xs = b"Hello\xC2 There\xFF Goodbye";
|
||||||
|
|
|
@ -18,7 +18,6 @@ use self::Taggy::*;
|
||||||
use self::Taggypar::*;
|
use self::Taggypar::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[allow(deprecated)]
|
|
||||||
fn test_simple() {
|
fn test_simple() {
|
||||||
let mut d = VecDeque::new();
|
let mut d = VecDeque::new();
|
||||||
assert_eq!(d.len(), 0);
|
assert_eq!(d.len(), 0);
|
||||||
|
@ -545,7 +544,7 @@ fn test_from_iter() {
|
||||||
let u: Vec<_> = deq.iter().cloned().collect();
|
let u: Vec<_> = deq.iter().cloned().collect();
|
||||||
assert_eq!(u, v);
|
assert_eq!(u, v);
|
||||||
|
|
||||||
let seq = iter::count(0, 2).take(256);
|
let seq = (0..).step_by(2).take(256);
|
||||||
let deq: VecDeque<_> = seq.collect();
|
let deq: VecDeque<_> = seq.collect();
|
||||||
for (i, &x) in deq.iter().enumerate() {
|
for (i, &x) in deq.iter().enumerate() {
|
||||||
assert_eq!(2*i, x);
|
assert_eq!(2*i, x);
|
||||||
|
@ -821,7 +820,7 @@ fn test_as_slices() {
|
||||||
|
|
||||||
let (left, right) = ring.as_slices();
|
let (left, right) = ring.as_slices();
|
||||||
let expected: Vec<_> = (0..i+1).collect();
|
let expected: Vec<_> = (0..i+1).collect();
|
||||||
assert_eq!(left, expected);
|
assert_eq!(left, &expected[..]);
|
||||||
assert_eq!(right, []);
|
assert_eq!(right, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -830,8 +829,8 @@ fn test_as_slices() {
|
||||||
let (left, right) = ring.as_slices();
|
let (left, right) = ring.as_slices();
|
||||||
let expected_left: Vec<_> = (-last..j+1).rev().collect();
|
let expected_left: Vec<_> = (-last..j+1).rev().collect();
|
||||||
let expected_right: Vec<_> = (0..first).collect();
|
let expected_right: Vec<_> = (0..first).collect();
|
||||||
assert_eq!(left, expected_left);
|
assert_eq!(left, &expected_left[..]);
|
||||||
assert_eq!(right, expected_right);
|
assert_eq!(right, &expected_right[..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(ring.len() as i32, cap);
|
assert_eq!(ring.len() as i32, cap);
|
||||||
|
@ -849,7 +848,7 @@ fn test_as_mut_slices() {
|
||||||
|
|
||||||
let (left, right) = ring.as_mut_slices();
|
let (left, right) = ring.as_mut_slices();
|
||||||
let expected: Vec<_> = (0..i+1).collect();
|
let expected: Vec<_> = (0..i+1).collect();
|
||||||
assert_eq!(left, expected);
|
assert_eq!(left, &expected[..]);
|
||||||
assert_eq!(right, []);
|
assert_eq!(right, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -858,8 +857,8 @@ fn test_as_mut_slices() {
|
||||||
let (left, right) = ring.as_mut_slices();
|
let (left, right) = ring.as_mut_slices();
|
||||||
let expected_left: Vec<_> = (-last..j+1).rev().collect();
|
let expected_left: Vec<_> = (-last..j+1).rev().collect();
|
||||||
let expected_right: Vec<_> = (0..first).collect();
|
let expected_right: Vec<_> = (0..first).collect();
|
||||||
assert_eq!(left, expected_left);
|
assert_eq!(left, &expected_left[..]);
|
||||||
assert_eq!(right, expected_right);
|
assert_eq!(right, &expected_right[..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(ring.len() as i32, cap);
|
assert_eq!(ring.len() as i32, cap);
|
||||||
|
|
|
@ -202,8 +202,7 @@ pub struct TypeId {
|
||||||
impl TypeId {
|
impl TypeId {
|
||||||
/// Returns the `TypeId` of the type this generic function has been
|
/// Returns the `TypeId` of the type this generic function has been
|
||||||
/// instantiated with
|
/// instantiated with
|
||||||
#[unstable(feature = "core",
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
reason = "may grow a `Reflect` bound soon via marker traits")]
|
|
||||||
pub fn of<T: ?Sized + Any>() -> TypeId {
|
pub fn of<T: ?Sized + Any>() -> TypeId {
|
||||||
TypeId {
|
TypeId {
|
||||||
t: unsafe { intrinsics::type_id::<T>() },
|
t: unsafe { intrinsics::type_id::<T>() },
|
||||||
|
|
|
@ -1062,144 +1062,3 @@ pub fn fence(order: Ordering) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "core")]
|
|
||||||
#[deprecated(since = "1.0.0",
|
|
||||||
reason = "renamed to AtomicIsize")]
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
pub struct AtomicInt {
|
|
||||||
v: UnsafeCell<isize>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(deprecated)]
|
|
||||||
unsafe impl Sync for AtomicInt {}
|
|
||||||
|
|
||||||
#[unstable(feature = "core")]
|
|
||||||
#[deprecated(since = "1.0.0",
|
|
||||||
reason = "renamed to AtomicUsize")]
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
pub struct AtomicUint {
|
|
||||||
v: UnsafeCell<usize>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(deprecated)]
|
|
||||||
unsafe impl Sync for AtomicUint {}
|
|
||||||
|
|
||||||
#[unstable(feature = "core")]
|
|
||||||
#[deprecated(since = "1.0.0",
|
|
||||||
reason = "use ATOMIC_ISIZE_INIT instead")]
|
|
||||||
#[allow(missing_docs, deprecated)]
|
|
||||||
pub const ATOMIC_INT_INIT: AtomicInt =
|
|
||||||
AtomicInt { v: UnsafeCell { value: 0 } };
|
|
||||||
#[unstable(feature = "core")]
|
|
||||||
#[deprecated(since = "1.0.0",
|
|
||||||
reason = "use ATOMIC_USIZE_INIT instead")]
|
|
||||||
#[allow(missing_docs, deprecated)]
|
|
||||||
pub const ATOMIC_UINT_INIT: AtomicUint =
|
|
||||||
AtomicUint { v: UnsafeCell { value: 0, } };
|
|
||||||
|
|
||||||
#[allow(missing_docs, deprecated)]
|
|
||||||
impl AtomicInt {
|
|
||||||
#[inline]
|
|
||||||
pub fn new(v: isize) -> AtomicInt {
|
|
||||||
AtomicInt {v: UnsafeCell::new(v)}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn load(&self, order: Ordering) -> isize {
|
|
||||||
unsafe { atomic_load(self.v.get(), order) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn store(&self, val: isize, order: Ordering) {
|
|
||||||
unsafe { atomic_store(self.v.get(), val, order); }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn swap(&self, val: isize, order: Ordering) -> isize {
|
|
||||||
unsafe { atomic_swap(self.v.get(), val, order) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn compare_and_swap(&self, old: isize, new: isize, order: Ordering) -> isize {
|
|
||||||
unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn fetch_add(&self, val: isize, order: Ordering) -> isize {
|
|
||||||
unsafe { atomic_add(self.v.get(), val, order) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn fetch_sub(&self, val: isize, order: Ordering) -> isize {
|
|
||||||
unsafe { atomic_sub(self.v.get(), val, order) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn fetch_and(&self, val: isize, order: Ordering) -> isize {
|
|
||||||
unsafe { atomic_and(self.v.get(), val, order) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn fetch_or(&self, val: isize, order: Ordering) -> isize {
|
|
||||||
unsafe { atomic_or(self.v.get(), val, order) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn fetch_xor(&self, val: isize, order: Ordering) -> isize {
|
|
||||||
unsafe { atomic_xor(self.v.get(), val, order) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(missing_docs, deprecated)]
|
|
||||||
impl AtomicUint {
|
|
||||||
#[inline]
|
|
||||||
pub fn new(v: usize) -> AtomicUint {
|
|
||||||
AtomicUint { v: UnsafeCell::new(v) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn load(&self, order: Ordering) -> usize {
|
|
||||||
unsafe { atomic_load(self.v.get(), order) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn store(&self, val: usize, order: Ordering) {
|
|
||||||
unsafe { atomic_store(self.v.get(), val, order); }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn swap(&self, val: usize, order: Ordering) -> usize {
|
|
||||||
unsafe { atomic_swap(self.v.get(), val, order) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn compare_and_swap(&self, old: usize, new: usize, order: Ordering) -> usize {
|
|
||||||
unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn fetch_add(&self, val: usize, order: Ordering) -> usize {
|
|
||||||
unsafe { atomic_add(self.v.get(), val, order) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn fetch_sub(&self, val: usize, order: Ordering) -> usize {
|
|
||||||
unsafe { atomic_sub(self.v.get(), val, order) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn fetch_and(&self, val: usize, order: Ordering) -> usize {
|
|
||||||
unsafe { atomic_and(self.v.get(), val, order) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn fetch_or(&self, val: usize, order: Ordering) -> usize {
|
|
||||||
unsafe { atomic_or(self.v.get(), val, order) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn fetch_xor(&self, val: usize, order: Ordering) -> usize {
|
|
||||||
unsafe { atomic_xor(self.v.get(), val, order) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -343,23 +343,6 @@ impl<T> RefCell<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to immutably borrow the wrapped value.
|
|
||||||
///
|
|
||||||
/// The borrow lasts until the returned `Ref` exits scope. Multiple
|
|
||||||
/// immutable borrows can be taken out at the same time.
|
|
||||||
///
|
|
||||||
/// Returns `None` if the value is currently mutably borrowed.
|
|
||||||
#[unstable(feature = "core", reason = "may be renamed or removed")]
|
|
||||||
#[deprecated(since = "1.0.0",
|
|
||||||
reason = "dispatch on `cell.borrow_state()` instead")]
|
|
||||||
#[inline]
|
|
||||||
pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
|
|
||||||
match BorrowRef::new(&self.borrow) {
|
|
||||||
Some(b) => Some(Ref { _value: unsafe { &*self.value.get() }, _borrow: b }),
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Immutably borrows the wrapped value.
|
/// Immutably borrows the wrapped value.
|
||||||
///
|
///
|
||||||
/// The borrow lasts until the returned `Ref` exits scope. Multiple
|
/// The borrow lasts until the returned `Ref` exits scope. Multiple
|
||||||
|
@ -407,23 +390,6 @@ impl<T> RefCell<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mutably borrows the wrapped value.
|
|
||||||
///
|
|
||||||
/// The borrow lasts until the returned `RefMut` exits scope. The value
|
|
||||||
/// cannot be borrowed while this borrow is active.
|
|
||||||
///
|
|
||||||
/// Returns `None` if the value is currently borrowed.
|
|
||||||
#[unstable(feature = "core", reason = "may be renamed or removed")]
|
|
||||||
#[deprecated(since = "1.0.0",
|
|
||||||
reason = "dispatch on `cell.borrow_state()` instead")]
|
|
||||||
#[inline]
|
|
||||||
pub fn try_borrow_mut<'a>(&'a self) -> Option<RefMut<'a, T>> {
|
|
||||||
match BorrowRefMut::new(&self.borrow) {
|
|
||||||
Some(b) => Some(RefMut { _value: unsafe { &mut *self.value.get() }, _borrow: b }),
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Mutably borrows the wrapped value.
|
/// Mutably borrows the wrapped value.
|
||||||
///
|
///
|
||||||
/// The borrow lasts until the returned `RefMut` exits scope. The value
|
/// The borrow lasts until the returned `RefMut` exits scope. The value
|
||||||
|
|
|
@ -64,7 +64,6 @@ use option::Option::{self, Some, None};
|
||||||
/// inverse of `ne`; that is, `!(a == b)` if and only if `a != b`.
|
/// inverse of `ne`; that is, `!(a == b)` if and only if `a != b`.
|
||||||
#[lang="eq"]
|
#[lang="eq"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[old_orphan_check]
|
|
||||||
pub trait PartialEq<Rhs: ?Sized = Self> {
|
pub trait PartialEq<Rhs: ?Sized = Self> {
|
||||||
/// This method tests for `self` and `other` values to be equal, and is used by `==`.
|
/// This method tests for `self` and `other` values to be equal, and is used by `==`.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -360,6 +359,8 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
|
||||||
|
|
||||||
/// Compare and return the minimum of two values.
|
/// Compare and return the minimum of two values.
|
||||||
///
|
///
|
||||||
|
/// Returns the first argument if the comparison determines them to be equal.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -371,11 +372,13 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn min<T: Ord>(v1: T, v2: T) -> T {
|
pub fn min<T: Ord>(v1: T, v2: T) -> T {
|
||||||
if v1 < v2 { v1 } else { v2 }
|
if v1 <= v2 { v1 } else { v2 }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compare and return the maximum of two values.
|
/// Compare and return the maximum of two values.
|
||||||
///
|
///
|
||||||
|
/// Returns the second argument if the comparison determines them to be equal.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -387,7 +390,7 @@ pub fn min<T: Ord>(v1: T, v2: T) -> T {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn max<T: Ord>(v1: T, v2: T) -> T {
|
pub fn max<T: Ord>(v1: T, v2: T) -> T {
|
||||||
if v1 > v2 { v1 } else { v2 }
|
if v2 >= v1 { v2 } else { v1 }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compare and return the minimum of two values if there is one.
|
/// Compare and return the minimum of two values if there is one.
|
||||||
|
@ -425,7 +428,7 @@ pub fn partial_min<T: PartialOrd>(v1: T, v2: T) -> Option<T> {
|
||||||
|
|
||||||
/// Compare and return the maximum of two values if there is one.
|
/// Compare and return the maximum of two values if there is one.
|
||||||
///
|
///
|
||||||
/// Returns the first argument if the comparison determines them to be equal.
|
/// Returns the second argument if the comparison determines them to be equal.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -450,8 +453,8 @@ pub fn partial_min<T: PartialOrd>(v1: T, v2: T) -> Option<T> {
|
||||||
#[unstable(feature = "core")]
|
#[unstable(feature = "core")]
|
||||||
pub fn partial_max<T: PartialOrd>(v1: T, v2: T) -> Option<T> {
|
pub fn partial_max<T: PartialOrd>(v1: T, v2: T) -> Option<T> {
|
||||||
match v1.partial_cmp(&v2) {
|
match v1.partial_cmp(&v2) {
|
||||||
Some(Less) => Some(v2),
|
Some(Equal) | Some(Less) => Some(v2),
|
||||||
Some(Equal) | Some(Greater) => Some(v1),
|
Some(Greater) => Some(v1),
|
||||||
None => None
|
None => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,11 @@
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! __impl_slice_eq1 {
|
macro_rules! __impl_slice_eq1 {
|
||||||
($Lhs: ty, $Rhs: ty) => {
|
($Lhs: ty, $Rhs: ty) => {
|
||||||
|
__impl_slice_eq1! { $Lhs, $Rhs, Sized }
|
||||||
|
};
|
||||||
|
($Lhs: ty, $Rhs: ty, $Bound: ident) => {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<'a, 'b, A, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
|
impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn eq(&self, other: &$Rhs) -> bool { &self[..] == &other[..] }
|
fn eq(&self, other: &$Rhs) -> bool { &self[..] == &other[..] }
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -31,13 +34,7 @@ macro_rules! __impl_slice_eq2 {
|
||||||
__impl_slice_eq2! { $Lhs, $Rhs, Sized }
|
__impl_slice_eq2! { $Lhs, $Rhs, Sized }
|
||||||
};
|
};
|
||||||
($Lhs: ty, $Rhs: ty, $Bound: ident) => {
|
($Lhs: ty, $Rhs: ty, $Bound: ident) => {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
__impl_slice_eq1!($Lhs, $Rhs, $Bound);
|
||||||
impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
|
|
||||||
#[inline]
|
|
||||||
fn eq(&self, other: &$Rhs) -> bool { &self[..] == &other[..] }
|
|
||||||
#[inline]
|
|
||||||
fn ne(&self, other: &$Rhs) -> bool { &self[..] != &other[..] }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<'a, 'b, A: $Bound, B> PartialEq<$Lhs> for $Rhs where B: PartialEq<A> {
|
impl<'a, 'b, A: $Bound, B> PartialEq<$Lhs> for $Rhs where B: PartialEq<A> {
|
||||||
|
|
|
@ -14,33 +14,40 @@
|
||||||
//! conversions from one type to another. They follow the standard
|
//! conversions from one type to another. They follow the standard
|
||||||
//! Rust conventions of `as`/`to`/`into`/`from`.
|
//! Rust conventions of `as`/`to`/`into`/`from`.
|
||||||
|
|
||||||
#![unstable(feature = "convert",
|
#![stable(feature = "rust1", since = "1.0.0")]
|
||||||
reason = "recently added, experimental traits")]
|
|
||||||
|
|
||||||
use marker::Sized;
|
use marker::Sized;
|
||||||
|
|
||||||
/// A cheap, reference-to-reference conversion.
|
/// A cheap, reference-to-reference conversion.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub trait AsRef<T: ?Sized> {
|
pub trait AsRef<T: ?Sized> {
|
||||||
/// Perform the conversion.
|
/// Perform the conversion.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn as_ref(&self) -> &T;
|
fn as_ref(&self) -> &T;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A cheap, mutable reference-to-mutable reference conversion.
|
/// A cheap, mutable reference-to-mutable reference conversion.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub trait AsMut<T: ?Sized> {
|
pub trait AsMut<T: ?Sized> {
|
||||||
/// Perform the conversion.
|
/// Perform the conversion.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn as_mut(&mut self) -> &mut T;
|
fn as_mut(&mut self) -> &mut T;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A conversion that consumes `self`, which may or may not be
|
/// A conversion that consumes `self`, which may or may not be
|
||||||
/// expensive.
|
/// expensive.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub trait Into<T>: Sized {
|
pub trait Into<T>: Sized {
|
||||||
/// Perform the conversion.
|
/// Perform the conversion.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn into(self) -> T;
|
fn into(self) -> T;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct `Self` via a conversion.
|
/// Construct `Self` via a conversion.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub trait From<T> {
|
pub trait From<T> {
|
||||||
/// Perform the conversion.
|
/// Perform the conversion.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn from(T) -> Self;
|
fn from(T) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,14 +55,8 @@ pub trait From<T> {
|
||||||
// GENERIC IMPLS
|
// GENERIC IMPLS
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// As implies Into
|
|
||||||
impl<'a, T: ?Sized, U: ?Sized> Into<&'a U> for &'a T where T: AsRef<U> {
|
|
||||||
fn into(self) -> &'a U {
|
|
||||||
self.as_ref()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// As lifts over &
|
// As lifts over &
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a T where T: AsRef<U> {
|
impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a T where T: AsRef<U> {
|
||||||
fn as_ref(&self) -> &U {
|
fn as_ref(&self) -> &U {
|
||||||
<T as AsRef<U>>::as_ref(*self)
|
<T as AsRef<U>>::as_ref(*self)
|
||||||
|
@ -63,6 +64,7 @@ impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a T where T: AsRef<U> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// As lifts over &mut
|
// As lifts over &mut
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a mut T where T: AsRef<U> {
|
impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a mut T where T: AsRef<U> {
|
||||||
fn as_ref(&self) -> &U {
|
fn as_ref(&self) -> &U {
|
||||||
<T as AsRef<U>>::as_ref(*self)
|
<T as AsRef<U>>::as_ref(*self)
|
||||||
|
@ -77,14 +79,8 @@ impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a mut T where T: AsRef<U> {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// AsMut implies Into
|
|
||||||
impl<'a, T: ?Sized, U: ?Sized> Into<&'a mut U> for &'a mut T where T: AsMut<U> {
|
|
||||||
fn into(self) -> &'a mut U {
|
|
||||||
(*self).as_mut()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AsMut lifts over &mut
|
// AsMut lifts over &mut
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<'a, T: ?Sized, U: ?Sized> AsMut<U> for &'a mut T where T: AsMut<U> {
|
impl<'a, T: ?Sized, U: ?Sized> AsMut<U> for &'a mut T where T: AsMut<U> {
|
||||||
fn as_mut(&mut self) -> &mut U {
|
fn as_mut(&mut self) -> &mut U {
|
||||||
(*self).as_mut()
|
(*self).as_mut()
|
||||||
|
@ -100,28 +96,38 @@ impl<'a, T: ?Sized, U: ?Sized> AsMut<U> for &'a mut T where T: AsMut<U> {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// From implies Into
|
// From implies Into
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T, U> Into<U> for T where U: From<T> {
|
impl<T, U> Into<U> for T where U: From<T> {
|
||||||
fn into(self) -> U {
|
fn into(self) -> U {
|
||||||
U::from(self)
|
U::from(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// From (and thus Into) is reflexive
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<T> From<T> for T {
|
||||||
|
fn from(t: T) -> T { t }
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// CONCRETE IMPLS
|
// CONCRETE IMPLS
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T> AsRef<[T]> for [T] {
|
impl<T> AsRef<[T]> for [T] {
|
||||||
fn as_ref(&self) -> &[T] {
|
fn as_ref(&self) -> &[T] {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T> AsMut<[T]> for [T] {
|
impl<T> AsMut<[T]> for [T] {
|
||||||
fn as_mut(&mut self) -> &mut [T] {
|
fn as_mut(&mut self) -> &mut [T] {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl AsRef<str> for str {
|
impl AsRef<str> for str {
|
||||||
fn as_ref(&self) -> &str {
|
fn as_ref(&self) -> &str {
|
||||||
self
|
self
|
||||||
|
|
|
@ -33,49 +33,6 @@
|
||||||
//! high-level module to provide its own errors that do not commit to any
|
//! high-level module to provide its own errors that do not commit to any
|
||||||
//! particular implementation, but also reveal some of its implementation for
|
//! particular implementation, but also reveal some of its implementation for
|
||||||
//! debugging via `cause` chains.
|
//! debugging via `cause` chains.
|
||||||
//!
|
|
||||||
//! # The `FromError` trait
|
|
||||||
//!
|
|
||||||
//! `FromError` is a simple trait that expresses conversions between different
|
|
||||||
//! error types. To provide maximum flexibility, it does not require either of
|
|
||||||
//! the types to actually implement the `Error` trait, although this will be the
|
|
||||||
//! common case.
|
|
||||||
//!
|
|
||||||
//! The main use of this trait is in the `try!` macro, which uses it to
|
|
||||||
//! automatically convert a given error to the error specified in a function's
|
|
||||||
//! return type.
|
|
||||||
//!
|
|
||||||
//! For example,
|
|
||||||
//!
|
|
||||||
//! ```
|
|
||||||
//! #![feature(core)]
|
|
||||||
//! use std::error::FromError;
|
|
||||||
//! use std::{io, str};
|
|
||||||
//! use std::fs::File;
|
|
||||||
//!
|
|
||||||
//! enum MyError {
|
|
||||||
//! Io(io::Error),
|
|
||||||
//! Utf8(str::Utf8Error),
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! impl FromError<io::Error> for MyError {
|
|
||||||
//! fn from_error(err: io::Error) -> MyError { MyError::Io(err) }
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! impl FromError<str::Utf8Error> for MyError {
|
|
||||||
//! fn from_error(err: str::Utf8Error) -> MyError { MyError::Utf8(err) }
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! #[allow(unused_variables)]
|
|
||||||
//! fn open_and_map() -> Result<(), MyError> {
|
|
||||||
//! let b = b"foo.txt";
|
|
||||||
//! let s = try!(str::from_utf8(b));
|
|
||||||
//! let f = try!(File::open(s));
|
|
||||||
//!
|
|
||||||
//! // do something interesting here...
|
|
||||||
//! Ok(())
|
|
||||||
//! }
|
|
||||||
//! ```
|
|
||||||
|
|
||||||
#![stable(feature = "rust1", since = "1.0.0")]
|
#![stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
||||||
|
@ -97,19 +54,3 @@ pub trait Error: Debug + Display {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn cause(&self) -> Option<&Error> { None }
|
fn cause(&self) -> Option<&Error> { None }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A trait for types that can be converted from a given error type `E`.
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
pub trait FromError<E> {
|
|
||||||
/// Perform the conversion.
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
fn from_error(err: E) -> Self;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Any type is convertable from itself
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
impl<E> FromError<E> for E {
|
|
||||||
fn from_error(err: E) -> E {
|
|
||||||
err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,111 +0,0 @@
|
||||||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
|
||||||
// file at the top-level directory of this distribution and at
|
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
||||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
||||||
// option. This file may not be copied, modified, or distributed
|
|
||||||
// except according to those terms.
|
|
||||||
|
|
||||||
//! The Finally trait provides a method, `finally` on
|
|
||||||
//! stack closures that emulates Java-style try/finally blocks.
|
|
||||||
//!
|
|
||||||
//! Using the `finally` method is sometimes convenient, but the type rules
|
|
||||||
//! prohibit any shared, mutable state between the "try" case and the
|
|
||||||
//! "finally" case. For advanced cases, the `try_finally` function can
|
|
||||||
//! also be used. See that function for more details.
|
|
||||||
//!
|
|
||||||
//! # Examples
|
|
||||||
//!
|
|
||||||
//! ```
|
|
||||||
//! # #![feature(core)]
|
|
||||||
//! # #![feature(unboxed_closures)]
|
|
||||||
//!
|
|
||||||
//! use std::finally::Finally;
|
|
||||||
//!
|
|
||||||
//! (|| {
|
|
||||||
//! // ...
|
|
||||||
//! }).finally(|| {
|
|
||||||
//! // this code is always run
|
|
||||||
//! })
|
|
||||||
//! ```
|
|
||||||
|
|
||||||
#![unstable(feature = "core")]
|
|
||||||
#![deprecated(since = "1.0.0",
|
|
||||||
reason = "It is unclear if this module is more robust than implementing \
|
|
||||||
Drop on a custom type, and this module is being removed with no \
|
|
||||||
replacement. Use a custom Drop implementation to regain existing \
|
|
||||||
functionality.")]
|
|
||||||
#![allow(deprecated)]
|
|
||||||
|
|
||||||
use ops::{Drop, FnMut, FnOnce};
|
|
||||||
|
|
||||||
/// A trait for executing a destructor unconditionally after a block of code,
|
|
||||||
/// regardless of whether the blocked fails.
|
|
||||||
pub trait Finally<T> {
|
|
||||||
/// Executes this object, unconditionally running `dtor` after this block of
|
|
||||||
/// code has run.
|
|
||||||
fn finally<F>(&mut self, dtor: F) -> T where F: FnMut();
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, F> Finally<T> for F where F: FnMut() -> T {
|
|
||||||
fn finally<G>(&mut self, mut dtor: G) -> T where G: FnMut() {
|
|
||||||
try_finally(&mut (), self, |_, f| (*f)(), |_| dtor())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The most general form of the `finally` functions. The function
|
|
||||||
/// `try_fn` will be invoked first; whether or not it panics, the
|
|
||||||
/// function `finally_fn` will be invoked next. The two parameters
|
|
||||||
/// `mutate` and `drop` are used to thread state through the two
|
|
||||||
/// closures. `mutate` is used for any shared, mutable state that both
|
|
||||||
/// closures require access to; `drop` is used for any state that the
|
|
||||||
/// `try_fn` requires ownership of.
|
|
||||||
///
|
|
||||||
/// **WARNING:** While shared, mutable state between the try and finally
|
|
||||||
/// function is often necessary, one must be very careful; the `try`
|
|
||||||
/// function could have panicked at any point, so the values of the shared
|
|
||||||
/// state may be inconsistent.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # #![feature(core)]
|
|
||||||
/// use std::finally::try_finally;
|
|
||||||
///
|
|
||||||
/// struct State<'a> { buffer: &'a mut [u8], len: usize }
|
|
||||||
/// # let mut buf = [];
|
|
||||||
/// let mut state = State { buffer: &mut buf, len: 0 };
|
|
||||||
/// try_finally(
|
|
||||||
/// &mut state, (),
|
|
||||||
/// |state, ()| {
|
|
||||||
/// // use state.buffer, state.len
|
|
||||||
/// },
|
|
||||||
/// |state| {
|
|
||||||
/// // use state.buffer, state.len to cleanup
|
|
||||||
/// })
|
|
||||||
/// ```
|
|
||||||
pub fn try_finally<T, U, R, F, G>(mutate: &mut T, drop: U, try_fn: F, finally_fn: G) -> R where
|
|
||||||
F: FnOnce(&mut T, U) -> R,
|
|
||||||
G: FnMut(&mut T),
|
|
||||||
{
|
|
||||||
let f = Finallyalizer {
|
|
||||||
mutate: mutate,
|
|
||||||
dtor: finally_fn,
|
|
||||||
};
|
|
||||||
try_fn(&mut *f.mutate, drop)
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Finallyalizer<'a, A:'a, F> where F: FnMut(&mut A) {
|
|
||||||
mutate: &'a mut A,
|
|
||||||
dtor: F,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe_destructor]
|
|
||||||
impl<'a, A, F> Drop for Finallyalizer<'a, A, F> where F: FnMut(&mut A) {
|
|
||||||
#[inline]
|
|
||||||
fn drop(&mut self) {
|
|
||||||
(self.dtor)(self.mutate);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -114,11 +114,6 @@ impl SipHasher {
|
||||||
state
|
state
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the computed hash.
|
|
||||||
#[unstable(feature = "hash")]
|
|
||||||
#[deprecated(since = "1.0.0", reason = "renamed to finish")]
|
|
||||||
pub fn result(&self) -> u64 { self.finish() }
|
|
||||||
|
|
||||||
fn reset(&mut self) {
|
fn reset(&mut self) {
|
||||||
self.length = 0;
|
self.length = 0;
|
||||||
self.v0 = self.k0 ^ 0x736f6d6570736575;
|
self.v0 = self.k0 ^ 0x736f6d6570736575;
|
||||||
|
|
|
@ -197,7 +197,6 @@ extern "rust-intrinsic" {
|
||||||
/// Rust moves to non-zeroing dynamic drop (and thus removes the
|
/// Rust moves to non-zeroing dynamic drop (and thus removes the
|
||||||
/// embedded drop flags that are being established by this
|
/// embedded drop flags that are being established by this
|
||||||
/// intrinsic).
|
/// intrinsic).
|
||||||
#[cfg(not(stage0))]
|
|
||||||
pub fn init_dropped<T>() -> T;
|
pub fn init_dropped<T>() -> T;
|
||||||
|
|
||||||
/// Create a value initialized to zero.
|
/// Create a value initialized to zero.
|
||||||
|
|
|
@ -12,39 +12,40 @@
|
||||||
//!
|
//!
|
||||||
//! # The `Iterator` trait
|
//! # The `Iterator` trait
|
||||||
//!
|
//!
|
||||||
//! This module defines Rust's core iteration trait. The `Iterator` trait has one
|
//! This module defines Rust's core iteration trait. The `Iterator` trait has
|
||||||
//! unimplemented method, `next`. All other methods are derived through default
|
//! one unimplemented method, `next`. All other methods are derived through
|
||||||
//! methods to perform operations such as `zip`, `chain`, `enumerate`, and `fold`.
|
//! default methods to perform operations such as `zip`, `chain`, `enumerate`,
|
||||||
|
//! and `fold`.
|
||||||
//!
|
//!
|
||||||
//! The goal of this module is to unify iteration across all containers in Rust.
|
//! The goal of this module is to unify iteration across all containers in Rust.
|
||||||
//! An iterator can be considered as a state machine which is used to track which
|
//! An iterator can be considered as a state machine which is used to track
|
||||||
//! element will be yielded next.
|
//! which element will be yielded next.
|
||||||
//!
|
//!
|
||||||
//! There are various extensions also defined in this module to assist with various
|
//! There are various extensions also defined in this module to assist with
|
||||||
//! types of iteration, such as the `DoubleEndedIterator` for iterating in reverse,
|
//! various types of iteration, such as the `DoubleEndedIterator` for iterating
|
||||||
//! the `FromIterator` trait for creating a container from an iterator, and much
|
//! in reverse, the `FromIterator` trait for creating a container from an
|
||||||
//! more.
|
//! iterator, and much more.
|
||||||
//!
|
//!
|
||||||
//! ## Rust's `for` loop
|
//! # Rust's `for` loop
|
||||||
//!
|
//!
|
||||||
//! The special syntax used by rust's `for` loop is based around the `Iterator`
|
//! The special syntax used by rust's `for` loop is based around the
|
||||||
//! trait defined in this module. For loops can be viewed as a syntactical expansion
|
//! `IntoIterator` trait defined in this module. `for` loops can be viewed as a
|
||||||
//! into a `loop`, for example, the `for` loop in this example is essentially
|
//! syntactical expansion into a `loop`, for example, the `for` loop in this
|
||||||
//! translated to the `loop` below.
|
//! example is essentially translated to the `loop` below.
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! let values = vec![1, 2, 3];
|
//! let values = vec![1, 2, 3];
|
||||||
//!
|
//!
|
||||||
//! // "Syntactical sugar" taking advantage of an iterator
|
//! for x in values {
|
||||||
//! for &x in values.iter() {
|
|
||||||
//! println!("{}", x);
|
//! println!("{}", x);
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! // Rough translation of the iteration without a `for` iterator.
|
//! // Rough translation of the iteration without a `for` iterator.
|
||||||
//! let mut it = values.iter();
|
//! # let values = vec![1, 2, 3];
|
||||||
|
//! let mut it = values.into_iter();
|
||||||
//! loop {
|
//! loop {
|
||||||
//! match it.next() {
|
//! match it.next() {
|
||||||
//! Some(&x) => {
|
//! Some(x) => {
|
||||||
//! println!("{}", x);
|
//! println!("{}", x);
|
||||||
//! }
|
//! }
|
||||||
//! None => { break }
|
//! None => { break }
|
||||||
|
@ -52,7 +53,8 @@
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! This `for` loop syntax can be applied to any iterator over any type.
|
//! Because `Iterator`s implement `IntoIterator`, this `for` loop syntax can be applied to any
|
||||||
|
//! iterator over any type.
|
||||||
|
|
||||||
#![stable(feature = "rust1", since = "1.0.0")]
|
#![stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
||||||
|
@ -64,10 +66,9 @@ use cmp::Ord;
|
||||||
use default::Default;
|
use default::Default;
|
||||||
use marker;
|
use marker;
|
||||||
use mem;
|
use mem;
|
||||||
use num::{Int, Zero, One, ToPrimitive};
|
use num::{Int, Zero, One};
|
||||||
use ops::{Add, Sub, FnMut, RangeFrom};
|
use ops::{self, Add, Sub, FnMut, RangeFrom};
|
||||||
use option::Option;
|
use option::Option::{self, Some, None};
|
||||||
use option::Option::{Some, None};
|
|
||||||
use marker::Sized;
|
use marker::Sized;
|
||||||
use usize;
|
use usize;
|
||||||
|
|
||||||
|
@ -85,21 +86,22 @@ fn _assert_is_object_safe(_: &Iterator) {}
|
||||||
/// else.
|
/// else.
|
||||||
#[lang="iterator"]
|
#[lang="iterator"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_on_unimplemented = "`{Self}` is not an iterator; maybe try calling `.iter()` or a similar \
|
#[rustc_on_unimplemented = "`{Self}` is not an iterator; maybe try calling \
|
||||||
method"]
|
`.iter()` or a similar method"]
|
||||||
pub trait Iterator {
|
pub trait Iterator {
|
||||||
/// The type of the elements being iterated
|
/// The type of the elements being iterated
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
type Item;
|
type Item;
|
||||||
|
|
||||||
/// Advance the iterator and return the next value. Return `None` when the end is reached.
|
/// Advance the iterator and return the next value. Return `None` when the
|
||||||
|
/// end is reached.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn next(&mut self) -> Option<Self::Item>;
|
fn next(&mut self) -> Option<Self::Item>;
|
||||||
|
|
||||||
/// Returns a lower and upper bound on the remaining length of the iterator.
|
/// Returns a lower and upper bound on the remaining length of the iterator.
|
||||||
///
|
///
|
||||||
/// An upper bound of `None` means either there is no known upper bound, or the upper bound
|
/// An upper bound of `None` means either there is no known upper bound, or
|
||||||
/// does not fit within a `usize`.
|
/// the upper bound does not fit within a `usize`.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) { (0, None) }
|
fn size_hint(&self) -> (usize, Option<usize>) { (0, None) }
|
||||||
|
@ -275,7 +277,8 @@ pub trait Iterator {
|
||||||
/// iterator plus the current index of iteration.
|
/// iterator plus the current index of iteration.
|
||||||
///
|
///
|
||||||
/// `enumerate` keeps its count as a `usize`. If you want to count by a
|
/// `enumerate` keeps its count as a `usize`. If you want to count by a
|
||||||
/// different sized integer, the `zip` function provides similar functionality.
|
/// different sized integer, the `zip` function provides similar
|
||||||
|
/// functionality.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -433,7 +436,7 @@ pub trait Iterator {
|
||||||
/// # #![feature(core)]
|
/// # #![feature(core)]
|
||||||
/// let xs = [2, 3];
|
/// let xs = [2, 3];
|
||||||
/// let ys = [0, 1, 0, 1, 2];
|
/// let ys = [0, 1, 0, 1, 2];
|
||||||
/// let it = xs.iter().flat_map(|&x| std::iter::count(0, 1).take(x));
|
/// let it = xs.iter().flat_map(|&x| (0..).take(x));
|
||||||
/// // Check that `it` has the same elements as `ys`
|
/// // Check that `it` has the same elements as `ys`
|
||||||
/// for (i, x) in it.enumerate() {
|
/// for (i, x) in it.enumerate() {
|
||||||
/// assert_eq!(x, ys[i]);
|
/// assert_eq!(x, ys[i]);
|
||||||
|
@ -530,10 +533,9 @@ pub trait Iterator {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #![feature(core)]
|
/// let expected = [1, 2, 3, 4, 5];
|
||||||
/// let a = [1, 2, 3, 4, 5];
|
/// let actual: Vec<_> = expected.iter().cloned().collect();
|
||||||
/// let b: Vec<_> = a.iter().cloned().collect();
|
/// assert_eq!(actual, expected);
|
||||||
/// assert_eq!(a, b);
|
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -553,8 +555,7 @@ pub trait Iterator {
|
||||||
/// assert_eq!(even, [2, 4]);
|
/// assert_eq!(even, [2, 4]);
|
||||||
/// assert_eq!(odd, [1, 3]);
|
/// assert_eq!(odd, [1, 3]);
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "core",
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
reason = "recently added as part of collections reform")]
|
|
||||||
fn partition<B, F>(self, mut f: F) -> (B, B) where
|
fn partition<B, F>(self, mut f: F) -> (B, B) where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
B: Default + Extend<Self::Item>,
|
B: Default + Extend<Self::Item>,
|
||||||
|
@ -613,7 +614,8 @@ pub trait Iterator {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tests whether any element of an iterator satisfies the specified predicate.
|
/// Tests whether any element of an iterator satisfies the specified
|
||||||
|
/// predicate.
|
||||||
///
|
///
|
||||||
/// Does not consume the iterator past the first found element.
|
/// Does not consume the iterator past the first found element.
|
||||||
///
|
///
|
||||||
|
@ -624,7 +626,7 @@ pub trait Iterator {
|
||||||
/// let a = [1, 2, 3, 4, 5];
|
/// let a = [1, 2, 3, 4, 5];
|
||||||
/// let mut it = a.iter();
|
/// let mut it = a.iter();
|
||||||
/// assert!(it.any(|x| *x == 3));
|
/// assert!(it.any(|x| *x == 3));
|
||||||
/// assert_eq!(it.as_slice(), [4, 5]);
|
/// assert_eq!(&it[..], [4, 5]);
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -648,7 +650,7 @@ pub trait Iterator {
|
||||||
/// let a = [1, 2, 3, 4, 5];
|
/// let a = [1, 2, 3, 4, 5];
|
||||||
/// let mut it = a.iter();
|
/// let mut it = a.iter();
|
||||||
/// assert_eq!(it.find(|&x| *x == 3).unwrap(), &3);
|
/// assert_eq!(it.find(|&x| *x == 3).unwrap(), &3);
|
||||||
/// assert_eq!(it.as_slice(), [4, 5]);
|
/// assert_eq!(&it[..], [4, 5]);
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item> where
|
fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item> where
|
||||||
|
@ -672,7 +674,7 @@ pub trait Iterator {
|
||||||
/// let a = [1, 2, 3, 4, 5];
|
/// let a = [1, 2, 3, 4, 5];
|
||||||
/// let mut it = a.iter();
|
/// let mut it = a.iter();
|
||||||
/// assert_eq!(it.position(|x| *x == 3).unwrap(), 2);
|
/// assert_eq!(it.position(|x| *x == 3).unwrap(), 2);
|
||||||
/// assert_eq!(it.as_slice(), [4, 5]);
|
/// assert_eq!(&it[..], [4, 5]);
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn position<P>(&mut self, mut predicate: P) -> Option<usize> where
|
fn position<P>(&mut self, mut predicate: P) -> Option<usize> where
|
||||||
|
@ -702,7 +704,7 @@ pub trait Iterator {
|
||||||
/// let a = [1, 2, 2, 4, 5];
|
/// let a = [1, 2, 2, 4, 5];
|
||||||
/// let mut it = a.iter();
|
/// let mut it = a.iter();
|
||||||
/// assert_eq!(it.rposition(|x| *x == 2).unwrap(), 2);
|
/// assert_eq!(it.rposition(|x| *x == 2).unwrap(), 2);
|
||||||
/// assert_eq!(it.as_slice(), [1, 2]);
|
/// assert_eq!(&it[..], [1, 2]);
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn rposition<P>(&mut self, mut predicate: P) -> Option<usize> where
|
fn rposition<P>(&mut self, mut predicate: P) -> Option<usize> where
|
||||||
|
@ -722,6 +724,9 @@ pub trait Iterator {
|
||||||
|
|
||||||
/// Consumes the entire iterator to return the maximum element.
|
/// Consumes the entire iterator to return the maximum element.
|
||||||
///
|
///
|
||||||
|
/// Returns the rightmost element if the comparison determines two elements
|
||||||
|
/// to be equally maximum.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -732,16 +737,19 @@ pub trait Iterator {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn max(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord
|
fn max(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord
|
||||||
{
|
{
|
||||||
self.fold(None, |max, x| {
|
self.fold(None, |max, y| {
|
||||||
match max {
|
match max {
|
||||||
None => Some(x),
|
None => Some(y),
|
||||||
Some(y) => Some(cmp::max(x, y))
|
Some(x) => Some(cmp::max(x, y))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consumes the entire iterator to return the minimum element.
|
/// Consumes the entire iterator to return the minimum element.
|
||||||
///
|
///
|
||||||
|
/// Returns the leftmost element if the comparison determines two elements
|
||||||
|
/// to be equally minimum.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -752,10 +760,10 @@ pub trait Iterator {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn min(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord
|
fn min(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord
|
||||||
{
|
{
|
||||||
self.fold(None, |min, x| {
|
self.fold(None, |min, y| {
|
||||||
match min {
|
match min {
|
||||||
None => Some(x),
|
None => Some(y),
|
||||||
Some(y) => Some(cmp::min(x, y))
|
Some(x) => Some(cmp::min(x, y))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -771,7 +779,8 @@ pub trait Iterator {
|
||||||
/// element in the iterator and all elements are equal.
|
/// element in the iterator and all elements are equal.
|
||||||
///
|
///
|
||||||
/// On an iterator of length `n`, `min_max` does `1.5 * n` comparisons,
|
/// On an iterator of length `n`, `min_max` does `1.5 * n` comparisons,
|
||||||
/// and so is faster than calling `min` and `max` separately which does `2 * n` comparisons.
|
/// and so is faster than calling `min` and `max` separately which does `2 *
|
||||||
|
/// n` comparisons.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -799,16 +808,17 @@ pub trait Iterator {
|
||||||
Some(x) => {
|
Some(x) => {
|
||||||
match self.next() {
|
match self.next() {
|
||||||
None => return OneElement(x),
|
None => return OneElement(x),
|
||||||
Some(y) => if x < y {(x, y)} else {(y,x)}
|
Some(y) => if x <= y {(x, y)} else {(y, x)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// `first` and `second` are the two next elements we want to look at.
|
// `first` and `second` are the two next elements we want to look
|
||||||
// We first compare `first` and `second` (#1). The smaller one is then compared to
|
// at. We first compare `first` and `second` (#1). The smaller one
|
||||||
// current minimum (#2). The larger one is compared to current maximum (#3). This
|
// is then compared to current minimum (#2). The larger one is
|
||||||
// way we do 3 comparisons for 2 elements.
|
// compared to current maximum (#3). This way we do 3 comparisons
|
||||||
|
// for 2 elements.
|
||||||
let first = match self.next() {
|
let first = match self.next() {
|
||||||
None => break,
|
None => break,
|
||||||
Some(x) => x
|
Some(x) => x
|
||||||
|
@ -817,19 +827,19 @@ pub trait Iterator {
|
||||||
None => {
|
None => {
|
||||||
if first < min {
|
if first < min {
|
||||||
min = first;
|
min = first;
|
||||||
} else if first > max {
|
} else if first >= max {
|
||||||
max = first;
|
max = first;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Some(x) => x
|
Some(x) => x
|
||||||
};
|
};
|
||||||
if first < second {
|
if first <= second {
|
||||||
if first < min {min = first;}
|
if first < min { min = first }
|
||||||
if max < second {max = second;}
|
if second >= max { max = second }
|
||||||
} else {
|
} else {
|
||||||
if second < min {min = second;}
|
if second < min { min = second }
|
||||||
if max < first {max = first;}
|
if first >= max { max = first }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -839,6 +849,9 @@ pub trait Iterator {
|
||||||
/// Return the element that gives the maximum value from the
|
/// Return the element that gives the maximum value from the
|
||||||
/// specified function.
|
/// specified function.
|
||||||
///
|
///
|
||||||
|
/// Returns the rightmost element if the comparison determines two elements
|
||||||
|
/// to be equally maximum.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -854,14 +867,14 @@ pub trait Iterator {
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
F: FnMut(&Self::Item) -> B,
|
F: FnMut(&Self::Item) -> B,
|
||||||
{
|
{
|
||||||
self.fold(None, |max: Option<(Self::Item, B)>, x| {
|
self.fold(None, |max: Option<(Self::Item, B)>, y| {
|
||||||
let x_val = f(&x);
|
let y_val = f(&y);
|
||||||
match max {
|
match max {
|
||||||
None => Some((x, x_val)),
|
None => Some((y, y_val)),
|
||||||
Some((y, y_val)) => if x_val > y_val {
|
Some((x, x_val)) => if y_val >= x_val {
|
||||||
Some((x, x_val))
|
|
||||||
} else {
|
|
||||||
Some((y, y_val))
|
Some((y, y_val))
|
||||||
|
} else {
|
||||||
|
Some((x, x_val))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).map(|(x, _)| x)
|
}).map(|(x, _)| x)
|
||||||
|
@ -870,6 +883,9 @@ pub trait Iterator {
|
||||||
/// Return the element that gives the minimum value from the
|
/// Return the element that gives the minimum value from the
|
||||||
/// specified function.
|
/// specified function.
|
||||||
///
|
///
|
||||||
|
/// Returns the leftmost element if the comparison determines two elements
|
||||||
|
/// to be equally minimum.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -885,11 +901,11 @@ pub trait Iterator {
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
F: FnMut(&Self::Item) -> B,
|
F: FnMut(&Self::Item) -> B,
|
||||||
{
|
{
|
||||||
self.fold(None, |min: Option<(Self::Item, B)>, x| {
|
self.fold(None, |min: Option<(Self::Item, B)>, y| {
|
||||||
let x_val = f(&x);
|
let y_val = f(&y);
|
||||||
match min {
|
match min {
|
||||||
None => Some((x, x_val)),
|
None => Some((y, y_val)),
|
||||||
Some((y, y_val)) => if x_val < y_val {
|
Some((x, x_val)) => if x_val <= y_val {
|
||||||
Some((x, x_val))
|
Some((x, x_val))
|
||||||
} else {
|
} else {
|
||||||
Some((y, y_val))
|
Some((y, y_val))
|
||||||
|
@ -927,10 +943,10 @@ pub trait Iterator {
|
||||||
/// # #![feature(core)]
|
/// # #![feature(core)]
|
||||||
/// let a = [(1, 2), (3, 4)];
|
/// let a = [(1, 2), (3, 4)];
|
||||||
/// let (left, right): (Vec<_>, Vec<_>) = a.iter().cloned().unzip();
|
/// let (left, right): (Vec<_>, Vec<_>) = a.iter().cloned().unzip();
|
||||||
/// assert_eq!([1, 3], left);
|
/// assert_eq!(left, [1, 3]);
|
||||||
/// assert_eq!([2, 4], right);
|
/// assert_eq!(right, [2, 4]);
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "core", reason = "recent addition")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) where
|
fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) where
|
||||||
FromA: Default + Extend<A>,
|
FromA: Default + Extend<A>,
|
||||||
FromB: Default + Extend<B>,
|
FromB: Default + Extend<B>,
|
||||||
|
@ -1027,7 +1043,8 @@ pub trait FromIterator<A> {
|
||||||
/// assert_eq!(colors_set.len(), 3);
|
/// assert_eq!(colors_set.len(), 3);
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// `FromIterator` is more commonly used implicitly via the `Iterator::collect` method:
|
/// `FromIterator` is more commonly used implicitly via the
|
||||||
|
/// `Iterator::collect` method:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::HashSet;
|
/// use std::collections::HashSet;
|
||||||
|
@ -1041,6 +1058,9 @@ pub trait FromIterator<A> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Conversion into an `Iterator`
|
/// Conversion into an `Iterator`
|
||||||
|
///
|
||||||
|
/// Implementing this trait allows you to use your type with Rust's `for` loop. See
|
||||||
|
/// the [module level documentation](../index.html) for more details.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub trait IntoIterator {
|
pub trait IntoIterator {
|
||||||
/// The type of the elements being iterated
|
/// The type of the elements being iterated
|
||||||
|
@ -1094,12 +1114,13 @@ impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I {
|
||||||
|
|
||||||
/// An object implementing random access indexing by `usize`
|
/// An object implementing random access indexing by `usize`
|
||||||
///
|
///
|
||||||
/// A `RandomAccessIterator` should be either infinite or a `DoubleEndedIterator`.
|
/// A `RandomAccessIterator` should be either infinite or a
|
||||||
/// Calling `next()` or `next_back()` on a `RandomAccessIterator`
|
/// `DoubleEndedIterator`. Calling `next()` or `next_back()` on a
|
||||||
/// reduces the indexable range accordingly. That is, `it.idx(1)` will become `it.idx(0)`
|
/// `RandomAccessIterator` reduces the indexable range accordingly. That is,
|
||||||
/// after `it.next()` is called.
|
/// `it.idx(1)` will become `it.idx(0)` after `it.next()` is called.
|
||||||
#[unstable(feature = "core",
|
#[unstable(feature = "core",
|
||||||
reason = "not widely used, may be better decomposed into Index and ExactSizeIterator")]
|
reason = "not widely used, may be better decomposed into Index \
|
||||||
|
and ExactSizeIterator")]
|
||||||
pub trait RandomAccessIterator: Iterator {
|
pub trait RandomAccessIterator: Iterator {
|
||||||
/// Return the number of indexable elements. At most `std::usize::MAX`
|
/// Return the number of indexable elements. At most `std::usize::MAX`
|
||||||
/// elements are indexable, even if the iterator represents a longer range.
|
/// elements are indexable, even if the iterator represents a longer range.
|
||||||
|
@ -1144,13 +1165,15 @@ impl<I: ExactSizeIterator, F> ExactSizeIterator for Inspect<I, F> where
|
||||||
F: FnMut(&I::Item),
|
F: FnMut(&I::Item),
|
||||||
{}
|
{}
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<I> ExactSizeIterator for Rev<I> where I: ExactSizeIterator + DoubleEndedIterator {}
|
impl<I> ExactSizeIterator for Rev<I>
|
||||||
|
where I: ExactSizeIterator + DoubleEndedIterator {}
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<B, I: ExactSizeIterator, F> ExactSizeIterator for Map<I, F> where
|
impl<B, I: ExactSizeIterator, F> ExactSizeIterator for Map<I, F> where
|
||||||
F: FnMut(I::Item) -> B,
|
F: FnMut(I::Item) -> B,
|
||||||
{}
|
{}
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<A, B> ExactSizeIterator for Zip<A, B> where A: ExactSizeIterator, B: ExactSizeIterator {}
|
impl<A, B> ExactSizeIterator for Zip<A, B>
|
||||||
|
where A: ExactSizeIterator, B: ExactSizeIterator {}
|
||||||
|
|
||||||
/// An double-ended iterator with the direction inverted
|
/// An double-ended iterator with the direction inverted
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -1177,7 +1200,9 @@ impl<I> DoubleEndedIterator for Rev<I> where I: DoubleEndedIterator {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "core", reason = "trait is experimental")]
|
#[unstable(feature = "core", reason = "trait is experimental")]
|
||||||
impl<I> RandomAccessIterator for Rev<I> where I: DoubleEndedIterator + RandomAccessIterator {
|
impl<I> RandomAccessIterator for Rev<I>
|
||||||
|
where I: DoubleEndedIterator + RandomAccessIterator
|
||||||
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn indexable(&self) -> usize { self.iter.indexable() }
|
fn indexable(&self) -> usize { self.iter.indexable() }
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1244,10 +1269,10 @@ pub trait MultiplicativeIterator<A> {
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #![feature(core)]
|
/// # #![feature(core)]
|
||||||
/// use std::iter::{count, MultiplicativeIterator};
|
/// use std::iter::MultiplicativeIterator;
|
||||||
///
|
///
|
||||||
/// fn factorial(n: usize) -> usize {
|
/// fn factorial(n: usize) -> usize {
|
||||||
/// count(1, 1).take_while(|&i| i <= n).product()
|
/// (1..).take_while(|&i| i <= n).product()
|
||||||
/// }
|
/// }
|
||||||
/// assert!(factorial(0) == 1);
|
/// assert!(factorial(0) == 1);
|
||||||
/// assert!(factorial(1) == 1);
|
/// assert!(factorial(1) == 1);
|
||||||
|
@ -1280,7 +1305,8 @@ impl_multiplicative! { usize, 1 }
|
||||||
impl_multiplicative! { f32, 1.0 }
|
impl_multiplicative! { f32, 1.0 }
|
||||||
impl_multiplicative! { f64, 1.0 }
|
impl_multiplicative! { f64, 1.0 }
|
||||||
|
|
||||||
/// `MinMaxResult` is an enum returned by `min_max`. See `Iterator::min_max` for more detail.
|
/// `MinMaxResult` is an enum returned by `min_max`. See `Iterator::min_max` for
|
||||||
|
/// more detail.
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
#[unstable(feature = "core",
|
#[unstable(feature = "core",
|
||||||
reason = "unclear whether such a fine-grained result is widely useful")]
|
reason = "unclear whether such a fine-grained result is widely useful")]
|
||||||
|
@ -1291,15 +1317,17 @@ pub enum MinMaxResult<T> {
|
||||||
/// Iterator with one element, so the minimum and maximum are the same
|
/// Iterator with one element, so the minimum and maximum are the same
|
||||||
OneElement(T),
|
OneElement(T),
|
||||||
|
|
||||||
/// More than one element in the iterator, the first element is not larger than the second
|
/// More than one element in the iterator, the first element is not larger
|
||||||
|
/// than the second
|
||||||
MinMax(T, T)
|
MinMax(T, T)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Clone> MinMaxResult<T> {
|
impl<T: Clone> MinMaxResult<T> {
|
||||||
/// `into_option` creates an `Option` of type `(T,T)`. The returned `Option` has variant
|
/// `into_option` creates an `Option` of type `(T,T)`. The returned `Option`
|
||||||
/// `None` if and only if the `MinMaxResult` has variant `NoElements`. Otherwise variant
|
/// has variant `None` if and only if the `MinMaxResult` has variant
|
||||||
/// `Some(x,y)` is returned where `x <= y`. If `MinMaxResult` has variant `OneElement(x)`,
|
/// `NoElements`. Otherwise variant `Some(x,y)` is returned where `x <= y`.
|
||||||
/// performing this operation will make one clone of `x`.
|
/// If `MinMaxResult` has variant `OneElement(x)`, performing this operation
|
||||||
|
/// will make one clone of `x`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -2511,7 +2539,7 @@ impl<A: Step> RangeFrom<A> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
impl<A: Step> ::ops::Range<A> {
|
impl<A: Step> ops::Range<A> {
|
||||||
/// Creates an iterator with the same range, but stepping by the
|
/// Creates an iterator with the same range, but stepping by the
|
||||||
/// given amount at each iteration.
|
/// given amount at each iteration.
|
||||||
///
|
///
|
||||||
|
@ -2544,26 +2572,6 @@ impl<A: Step> ::ops::Range<A> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An infinite iterator starting at `start` and advancing by `step` with each
|
|
||||||
/// iteration
|
|
||||||
#[unstable(feature = "core",
|
|
||||||
reason = "may be renamed or replaced by range notation adapters")]
|
|
||||||
#[deprecated(since = "1.0.0-beta", reason = "use range notation and step_by")]
|
|
||||||
pub type Counter<A> = StepBy<A, RangeFrom<A>>;
|
|
||||||
|
|
||||||
/// Deprecated: use `(start..).step_by(step)` instead.
|
|
||||||
#[inline]
|
|
||||||
#[unstable(feature = "core",
|
|
||||||
reason = "may be renamed or replaced by range notation adapters")]
|
|
||||||
#[deprecated(since = "1.0.0-beta", reason = "use (start..).step_by(step) instead")]
|
|
||||||
#[allow(deprecated)]
|
|
||||||
pub fn count<A>(start: A, step: A) -> Counter<A> {
|
|
||||||
StepBy {
|
|
||||||
range: RangeFrom { start: start },
|
|
||||||
step_by: step,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<A> Iterator for StepBy<A, RangeFrom<A>> where
|
impl<A> Iterator for StepBy<A, RangeFrom<A>> where
|
||||||
A: Clone,
|
A: Clone,
|
||||||
|
@ -2584,108 +2592,12 @@ impl<A> Iterator for StepBy<A, RangeFrom<A>> where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An iterator over the range [start, stop)
|
|
||||||
#[allow(deprecated)]
|
|
||||||
#[derive(Clone)]
|
|
||||||
#[unstable(feature = "core",
|
|
||||||
reason = "will be replaced by range notation")]
|
|
||||||
#[deprecated(since = "1.0.0-beta", reason = "use range notation")]
|
|
||||||
pub struct Range<A> {
|
|
||||||
state: A,
|
|
||||||
stop: A,
|
|
||||||
one: A,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deprecated: use `(start..stop)` instead.
|
|
||||||
#[inline]
|
|
||||||
#[unstable(feature = "core", reason = "will be replaced by range notation")]
|
|
||||||
#[deprecated(since = "1.0.0-beta", reason = "use (start..stop) instead")]
|
|
||||||
#[allow(deprecated)]
|
|
||||||
pub fn range<A: Int>(start: A, stop: A) -> Range<A> {
|
|
||||||
Range {
|
|
||||||
state: start,
|
|
||||||
stop: stop,
|
|
||||||
one: Int::one(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: #10414: Unfortunate type bound
|
|
||||||
#[unstable(feature = "core",
|
|
||||||
reason = "will be replaced by range notation")]
|
|
||||||
#[deprecated(since = "1.0.0-beta", reason = "use range notation")]
|
|
||||||
#[allow(deprecated)]
|
|
||||||
impl<A: Int + ToPrimitive> Iterator for Range<A> {
|
|
||||||
type Item = A;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn next(&mut self) -> Option<A> {
|
|
||||||
if self.state < self.stop {
|
|
||||||
let result = self.state.clone();
|
|
||||||
self.state = self.state + self.one;
|
|
||||||
Some(result)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
|
||||||
// This first checks if the elements are representable as i64. If they aren't, try u64 (to
|
|
||||||
// handle cases like range(huge, huger)). We don't use usize/isize because the difference of
|
|
||||||
// the i64/u64 might lie within their range.
|
|
||||||
let bound = match self.state.to_i64() {
|
|
||||||
Some(a) => {
|
|
||||||
let sz = self.stop.to_i64().map(|b| b.checked_sub(a));
|
|
||||||
match sz {
|
|
||||||
Some(Some(bound)) => bound.to_usize(),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => match self.state.to_u64() {
|
|
||||||
Some(a) => {
|
|
||||||
let sz = self.stop.to_u64().map(|b| b.checked_sub(a));
|
|
||||||
match sz {
|
|
||||||
Some(Some(bound)) => bound.to_usize(),
|
|
||||||
_ => None
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => None
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match bound {
|
|
||||||
Some(b) => (b, Some(b)),
|
|
||||||
// Standard fallback for unbounded/unrepresentable bounds
|
|
||||||
None => (0, None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `Int` is required to ensure the range will be the same regardless of
|
|
||||||
/// the direction it is consumed.
|
|
||||||
#[unstable(feature = "core",
|
|
||||||
reason = "will be replaced by range notation")]
|
|
||||||
#[deprecated(since = "1.0.0-beta", reason = "use range notation")]
|
|
||||||
#[allow(deprecated)]
|
|
||||||
impl<A: Int + ToPrimitive> DoubleEndedIterator for Range<A> {
|
|
||||||
#[inline]
|
|
||||||
fn next_back(&mut self) -> Option<A> {
|
|
||||||
if self.stop > self.state {
|
|
||||||
self.stop = self.stop - self.one;
|
|
||||||
Some(self.stop.clone())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An iterator over the range [start, stop]
|
/// An iterator over the range [start, stop]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
#[unstable(feature = "core",
|
#[unstable(feature = "core",
|
||||||
reason = "likely to be replaced by range notation and adapters")]
|
reason = "likely to be replaced by range notation and adapters")]
|
||||||
#[allow(deprecated)]
|
|
||||||
pub struct RangeInclusive<A> {
|
pub struct RangeInclusive<A> {
|
||||||
range: Range<A>,
|
range: ops::Range<A>,
|
||||||
done: bool,
|
done: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2693,18 +2605,18 @@ pub struct RangeInclusive<A> {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "core",
|
#[unstable(feature = "core",
|
||||||
reason = "likely to be replaced by range notation and adapters")]
|
reason = "likely to be replaced by range notation and adapters")]
|
||||||
#[allow(deprecated)]
|
pub fn range_inclusive<A>(start: A, stop: A) -> RangeInclusive<A>
|
||||||
pub fn range_inclusive<A: Int>(start: A, stop: A) -> RangeInclusive<A> {
|
where A: Step + One + Clone
|
||||||
|
{
|
||||||
RangeInclusive {
|
RangeInclusive {
|
||||||
range: range(start, stop),
|
range: start..stop,
|
||||||
done: false,
|
done: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "core",
|
#[unstable(feature = "core",
|
||||||
reason = "likely to be replaced by range notation and adapters")]
|
reason = "likely to be replaced by range notation and adapters")]
|
||||||
#[allow(deprecated)]
|
impl<A: Step + One + Clone> Iterator for RangeInclusive<A> {
|
||||||
impl<A: Int + ToPrimitive> Iterator for RangeInclusive<A> {
|
|
||||||
type Item = A;
|
type Item = A;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -2712,9 +2624,9 @@ impl<A: Int + ToPrimitive> Iterator for RangeInclusive<A> {
|
||||||
match self.range.next() {
|
match self.range.next() {
|
||||||
Some(x) => Some(x),
|
Some(x) => Some(x),
|
||||||
None => {
|
None => {
|
||||||
if !self.done && self.range.state == self.range.stop {
|
if !self.done && self.range.start == self.range.end {
|
||||||
self.done = true;
|
self.done = true;
|
||||||
Some(self.range.stop.clone())
|
Some(self.range.end.clone())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -2740,46 +2652,28 @@ impl<A: Int + ToPrimitive> Iterator for RangeInclusive<A> {
|
||||||
|
|
||||||
#[unstable(feature = "core",
|
#[unstable(feature = "core",
|
||||||
reason = "likely to be replaced by range notation and adapters")]
|
reason = "likely to be replaced by range notation and adapters")]
|
||||||
#[allow(deprecated)]
|
impl<A> DoubleEndedIterator for RangeInclusive<A>
|
||||||
impl<A: Int + ToPrimitive> DoubleEndedIterator for RangeInclusive<A> {
|
where A: Step + One + Clone,
|
||||||
|
for<'a> &'a A: Sub<Output=A>
|
||||||
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next_back(&mut self) -> Option<A> {
|
fn next_back(&mut self) -> Option<A> {
|
||||||
if self.range.stop > self.range.state {
|
if self.range.end > self.range.start {
|
||||||
let result = self.range.stop.clone();
|
let result = self.range.end.clone();
|
||||||
self.range.stop = self.range.stop - self.range.one;
|
self.range.end = &self.range.end - &A::one();
|
||||||
Some(result)
|
Some(result)
|
||||||
} else if !self.done && self.range.state == self.range.stop {
|
} else if !self.done && self.range.start == self.range.end {
|
||||||
self.done = true;
|
self.done = true;
|
||||||
Some(self.range.stop.clone())
|
Some(self.range.end.clone())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An iterator over the range [start, stop) by `step`. It handles overflow by stopping.
|
|
||||||
#[unstable(feature = "core",
|
|
||||||
reason = "likely to be replaced by range notation and adapters")]
|
|
||||||
#[deprecated(since = "1.0.0-beta", reason = "use range notation and step_by")]
|
|
||||||
pub type RangeStep<A> = StepBy<A, ::ops::Range<A>>;
|
|
||||||
|
|
||||||
/// Deprecated: use `(start..stop).step_by(step)` instead.
|
|
||||||
#[inline]
|
|
||||||
#[unstable(feature = "core",
|
|
||||||
reason = "likely to be replaced by range notation and adapters")]
|
|
||||||
#[deprecated(since = "1.0.0-beta",
|
|
||||||
reason = "use `(start..stop).step_by(step)` instead")]
|
|
||||||
#[allow(deprecated)]
|
|
||||||
pub fn range_step<A: Int>(start: A, stop: A, step: A) -> RangeStep<A> {
|
|
||||||
StepBy {
|
|
||||||
step_by: step,
|
|
||||||
range: ::ops::Range { start: start, end: stop },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
impl<A: Step + Zero + Clone> Iterator for StepBy<A, ::ops::Range<A>> {
|
impl<A: Step + Zero + Clone> Iterator for StepBy<A, ops::Range<A>> {
|
||||||
type Item = A;
|
type Item = A;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -2882,13 +2776,13 @@ impl<A: Int> Iterator for RangeStepInclusive<A> {
|
||||||
macro_rules! range_exact_iter_impl {
|
macro_rules! range_exact_iter_impl {
|
||||||
($($t:ty)*) => ($(
|
($($t:ty)*) => ($(
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl ExactSizeIterator for ::ops::Range<$t> { }
|
impl ExactSizeIterator for ops::Range<$t> { }
|
||||||
)*)
|
)*)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
impl<A: Step + One + Clone> Iterator for ::ops::Range<A> {
|
impl<A: Step + One + Clone> Iterator for ops::Range<A> {
|
||||||
type Item = A;
|
type Item = A;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -2927,7 +2821,7 @@ range_exact_iter_impl!(usize u8 u16 u32 isize i8 i16 i32);
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
impl<A: Step + One + Clone> DoubleEndedIterator for ::ops::Range<A> where
|
impl<A: Step + One + Clone> DoubleEndedIterator for ops::Range<A> where
|
||||||
for<'a> &'a A: Sub<&'a A, Output = A>
|
for<'a> &'a A: Sub<&'a A, Output = A>
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -2943,7 +2837,7 @@ impl<A: Step + One + Clone> DoubleEndedIterator for ::ops::Range<A> where
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
impl<A: Step + One> Iterator for ::ops::RangeFrom<A> {
|
impl<A: Step + One> Iterator for ops::RangeFrom<A> {
|
||||||
type Item = A;
|
type Item = A;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -136,7 +136,6 @@ pub mod atomic;
|
||||||
pub mod cell;
|
pub mod cell;
|
||||||
pub mod char;
|
pub mod char;
|
||||||
pub mod panicking;
|
pub mod panicking;
|
||||||
pub mod finally;
|
|
||||||
pub mod iter;
|
pub mod iter;
|
||||||
pub mod option;
|
pub mod option;
|
||||||
pub mod raw;
|
pub mod raw;
|
||||||
|
|
|
@ -66,10 +66,10 @@ macro_rules! assert {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Asserts that two expressions are equal to each other, testing equality in
|
/// Asserts that two expressions are equal to each other.
|
||||||
/// both directions.
|
|
||||||
///
|
///
|
||||||
/// On panic, this macro will print the values of the expressions.
|
/// On panic, this macro will print the values of the expressions with their
|
||||||
|
/// debug representations.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -84,10 +84,8 @@ macro_rules! assert_eq {
|
||||||
($left:expr , $right:expr) => ({
|
($left:expr , $right:expr) => ({
|
||||||
match (&($left), &($right)) {
|
match (&($left), &($right)) {
|
||||||
(left_val, right_val) => {
|
(left_val, right_val) => {
|
||||||
// check both directions of equality....
|
if !(*left_val == *right_val) {
|
||||||
if !((*left_val == *right_val) &&
|
panic!("assertion failed: `(left == right)` \
|
||||||
(*right_val == *left_val)) {
|
|
||||||
panic!("assertion failed: `(left == right) && (right == left)` \
|
|
||||||
(left: `{:?}`, right: `{:?}`)", *left_val, *right_val)
|
(left: `{:?}`, right: `{:?}`)", *left_val, *right_val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,7 +154,7 @@ macro_rules! debug_assert_eq {
|
||||||
|
|
||||||
/// Short circuiting evaluation on Err
|
/// Short circuiting evaluation on Err
|
||||||
///
|
///
|
||||||
/// `libstd` contains a more general `try!` macro that uses `FromError`.
|
/// `libstd` contains a more general `try!` macro that uses `From<E>`.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! try {
|
macro_rules! try {
|
||||||
($e:expr) => ({
|
($e:expr) => ({
|
||||||
|
@ -233,7 +231,7 @@ macro_rules! writeln {
|
||||||
/// ```
|
/// ```
|
||||||
/// # #![feature(core)]
|
/// # #![feature(core)]
|
||||||
/// fn divide_by_three(x: u32) -> u32 { // one of the poorest implementations of x/3
|
/// fn divide_by_three(x: u32) -> u32 { // one of the poorest implementations of x/3
|
||||||
/// for i in std::iter::count(0, 1) {
|
/// for i in 0.. {
|
||||||
/// if 3*i < i { panic!("u32 overflow"); }
|
/// if 3*i < i { panic!("u32 overflow"); }
|
||||||
/// if x < 3*i { return i-1; }
|
/// if x < 3*i { return i-1; }
|
||||||
/// }
|
/// }
|
||||||
|
|
|
@ -415,42 +415,6 @@ mod impls {
|
||||||
unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {}
|
unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Old-style marker trait. Deprecated.
|
|
||||||
#[unstable(feature = "core", reason = "deprecated")]
|
|
||||||
#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<&'a ()>`")]
|
|
||||||
#[lang="contravariant_lifetime"]
|
|
||||||
pub struct ContravariantLifetime<'a>;
|
|
||||||
|
|
||||||
/// Old-style marker trait. Deprecated.
|
|
||||||
#[unstable(feature = "core", reason = "deprecated")]
|
|
||||||
#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<fn(&'a ())>`")]
|
|
||||||
#[lang="covariant_lifetime"]
|
|
||||||
pub struct CovariantLifetime<'a>;
|
|
||||||
|
|
||||||
/// Old-style marker trait. Deprecated.
|
|
||||||
#[unstable(feature = "core", reason = "deprecated")]
|
|
||||||
#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<Cell<&'a ()>>`")]
|
|
||||||
#[lang="invariant_lifetime"]
|
|
||||||
pub struct InvariantLifetime<'a>;
|
|
||||||
|
|
||||||
/// Old-style marker trait. Deprecated.
|
|
||||||
#[unstable(feature = "core", reason = "deprecated")]
|
|
||||||
#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<fn(T)>`")]
|
|
||||||
#[lang="contravariant_type"]
|
|
||||||
pub struct ContravariantType<T>;
|
|
||||||
|
|
||||||
/// Old-style marker trait. Deprecated.
|
|
||||||
#[unstable(feature = "core", reason = "deprecated")]
|
|
||||||
#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<T>`")]
|
|
||||||
#[lang="covariant_type"]
|
|
||||||
pub struct CovariantType<T>;
|
|
||||||
|
|
||||||
/// Old-style marker trait. Deprecated.
|
|
||||||
#[unstable(feature = "core", reason = "deprecated")]
|
|
||||||
#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<Cell<T>>`")]
|
|
||||||
#[lang="invariant_type"]
|
|
||||||
pub struct InvariantType<T>;
|
|
||||||
|
|
||||||
/// A marker trait indicates a type that can be reflected over. This
|
/// A marker trait indicates a type that can be reflected over. This
|
||||||
/// trait is implemented for all types. Its purpose is to ensure that
|
/// trait is implemented for all types. Its purpose is to ensure that
|
||||||
/// when you write a generic function that will employ reflection,
|
/// when you write a generic function that will employ reflection,
|
||||||
|
@ -487,9 +451,5 @@ pub struct InvariantType<T>;
|
||||||
pub trait Reflect : MarkerTrait {
|
pub trait Reflect : MarkerTrait {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<T> Reflect for T { }
|
|
||||||
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
impl Reflect for .. { }
|
impl Reflect for .. { }
|
||||||
|
|
||||||
|
|
|
@ -173,11 +173,6 @@ pub unsafe fn zeroed<T>() -> T {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "filling_drop")]
|
#[unstable(feature = "filling_drop")]
|
||||||
pub unsafe fn dropped<T>() -> T {
|
pub unsafe fn dropped<T>() -> T {
|
||||||
#[cfg(stage0)]
|
|
||||||
#[inline(always)]
|
|
||||||
unsafe fn dropped_impl<T>() -> T { zeroed() }
|
|
||||||
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
unsafe fn dropped_impl<T>() -> T { intrinsics::init_dropped() }
|
unsafe fn dropped_impl<T>() -> T { intrinsics::init_dropped() }
|
||||||
|
|
||||||
|
@ -337,38 +332,32 @@ macro_rules! repeat_u8_as_u64 {
|
||||||
// But having the sign bit set is a pain, so 0x1d is probably better.
|
// But having the sign bit set is a pain, so 0x1d is probably better.
|
||||||
//
|
//
|
||||||
// And of course, 0x00 brings back the old world of zero'ing on drop.
|
// And of course, 0x00 brings back the old world of zero'ing on drop.
|
||||||
#[cfg(not(stage0))] #[unstable(feature = "filling_drop")]
|
#[unstable(feature = "filling_drop")]
|
||||||
pub const POST_DROP_U8: u8 = 0x1d;
|
pub const POST_DROP_U8: u8 = 0x1d;
|
||||||
#[cfg(not(stage0))] #[unstable(feature = "filling_drop")]
|
#[unstable(feature = "filling_drop")]
|
||||||
pub const POST_DROP_U32: u32 = repeat_u8_as_u32!(POST_DROP_U8);
|
pub const POST_DROP_U32: u32 = repeat_u8_as_u32!(POST_DROP_U8);
|
||||||
#[cfg(not(stage0))] #[unstable(feature = "filling_drop")]
|
#[unstable(feature = "filling_drop")]
|
||||||
pub const POST_DROP_U64: u64 = repeat_u8_as_u64!(POST_DROP_U8);
|
pub const POST_DROP_U64: u64 = repeat_u8_as_u64!(POST_DROP_U8);
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
#[cfg(not(stage0))] #[unstable(feature = "filling_drop")]
|
#[unstable(feature = "filling_drop")]
|
||||||
pub const POST_DROP_USIZE: usize = POST_DROP_U32 as usize;
|
pub const POST_DROP_USIZE: usize = POST_DROP_U32 as usize;
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
#[cfg(not(stage0))] #[unstable(feature = "filling_drop")]
|
#[unstable(feature = "filling_drop")]
|
||||||
pub const POST_DROP_USIZE: usize = POST_DROP_U64 as usize;
|
pub const POST_DROP_USIZE: usize = POST_DROP_U64 as usize;
|
||||||
|
|
||||||
#[cfg(stage0)] #[unstable(feature = "filling_drop")]
|
/// Interprets `src` as `&U`, and then reads `src` without moving the contained
|
||||||
pub const POST_DROP_U8: u8 = 0;
|
/// value.
|
||||||
#[cfg(stage0)] #[unstable(feature = "filling_drop")]
|
|
||||||
pub const POST_DROP_U32: u32 = 0;
|
|
||||||
#[cfg(stage0)] #[unstable(feature = "filling_drop")]
|
|
||||||
pub const POST_DROP_U64: u64 = 0;
|
|
||||||
#[cfg(stage0)] #[unstable(feature = "filling_drop")]
|
|
||||||
pub const POST_DROP_USIZE: usize = 0;
|
|
||||||
|
|
||||||
/// Interprets `src` as `&U`, and then reads `src` without moving the contained value.
|
|
||||||
///
|
///
|
||||||
/// This function will unsafely assume the pointer `src` is valid for `sizeof(U)` bytes by
|
/// This function will unsafely assume the pointer `src` is valid for
|
||||||
/// transmuting `&T` to `&U` and then reading the `&U`. It will also unsafely create a copy of the
|
/// `sizeof(U)` bytes by transmuting `&T` to `&U` and then reading the `&U`. It
|
||||||
/// contained value instead of moving out of `src`.
|
/// will also unsafely create a copy of the contained value instead of moving
|
||||||
|
/// out of `src`.
|
||||||
///
|
///
|
||||||
/// It is not a compile-time error if `T` and `U` have different sizes, but it is highly encouraged
|
/// It is not a compile-time error if `T` and `U` have different sizes, but it
|
||||||
/// to only invoke this function where `T` and `U` have the same size. This function triggers
|
/// is highly encouraged to only invoke this function where `T` and `U` have the
|
||||||
/// undefined behavior if `U` is larger than `T`.
|
/// same size. This function triggers undefined behavior if `U` is larger than
|
||||||
|
/// `T`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
|
|
@ -46,7 +46,7 @@ use str::{FromStr, StrExt};
|
||||||
/// intended to have wrapping semantics.
|
/// intended to have wrapping semantics.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)]
|
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)]
|
||||||
pub struct Wrapping<T>(pub T);
|
pub struct Wrapping<T>(#[stable(feature = "rust1", since = "1.0.0")] pub T);
|
||||||
|
|
||||||
#[unstable(feature = "core", reason = "may be removed or relocated")]
|
#[unstable(feature = "core", reason = "may be removed or relocated")]
|
||||||
pub mod wrapping;
|
pub mod wrapping;
|
||||||
|
|
|
@ -30,6 +30,8 @@ use intrinsics::{i16_mul_with_overflow, u16_mul_with_overflow};
|
||||||
use intrinsics::{i32_mul_with_overflow, u32_mul_with_overflow};
|
use intrinsics::{i32_mul_with_overflow, u32_mul_with_overflow};
|
||||||
use intrinsics::{i64_mul_with_overflow, u64_mul_with_overflow};
|
use intrinsics::{i64_mul_with_overflow, u64_mul_with_overflow};
|
||||||
|
|
||||||
|
use ::{i8,i16,i32,i64,u8,u16,u32,u64};
|
||||||
|
|
||||||
#[unstable(feature = "core", reason = "may be removed, renamed, or relocated")]
|
#[unstable(feature = "core", reason = "may be removed, renamed, or relocated")]
|
||||||
#[deprecated(since = "1.0.0", reason = "moved to inherent methods")]
|
#[deprecated(since = "1.0.0", reason = "moved to inherent methods")]
|
||||||
pub trait WrappingOps {
|
pub trait WrappingOps {
|
||||||
|
@ -43,6 +45,12 @@ pub trait OverflowingOps {
|
||||||
fn overflowing_add(self, rhs: Self) -> (Self, bool);
|
fn overflowing_add(self, rhs: Self) -> (Self, bool);
|
||||||
fn overflowing_sub(self, rhs: Self) -> (Self, bool);
|
fn overflowing_sub(self, rhs: Self) -> (Self, bool);
|
||||||
fn overflowing_mul(self, rhs: Self) -> (Self, bool);
|
fn overflowing_mul(self, rhs: Self) -> (Self, bool);
|
||||||
|
|
||||||
|
fn overflowing_div(self, rhs: Self) -> (Self, bool);
|
||||||
|
fn overflowing_rem(self, rhs: Self) -> (Self, bool);
|
||||||
|
|
||||||
|
fn overflowing_shl(self, rhs: u32) -> (Self, bool);
|
||||||
|
fn overflowing_shr(self, rhs: u32) -> (Self, bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! sh_impl {
|
macro_rules! sh_impl {
|
||||||
|
@ -184,6 +192,20 @@ macro_rules! wrapping_impl {
|
||||||
|
|
||||||
wrapping_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
|
wrapping_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
|
||||||
|
|
||||||
|
mod shift_max {
|
||||||
|
#![allow(non_upper_case_globals)]
|
||||||
|
|
||||||
|
pub const i8: u32 = (1 << 3) - 1;
|
||||||
|
pub const i16: u32 = (1 << 4) - 1;
|
||||||
|
pub const i32: u32 = (1 << 5) - 1;
|
||||||
|
pub const i64: u32 = (1 << 6) - 1;
|
||||||
|
|
||||||
|
pub const u8: u32 = i8;
|
||||||
|
pub const u16: u32 = i16;
|
||||||
|
pub const u32: u32 = i32;
|
||||||
|
pub const u64: u32 = i64;
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! overflowing_impl {
|
macro_rules! overflowing_impl {
|
||||||
($($t:ident)*) => ($(
|
($($t:ident)*) => ($(
|
||||||
impl OverflowingOps for $t {
|
impl OverflowingOps for $t {
|
||||||
|
@ -205,6 +227,34 @@ macro_rules! overflowing_impl {
|
||||||
concat_idents!($t, _mul_with_overflow)(self, rhs)
|
concat_idents!($t, _mul_with_overflow)(self, rhs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn overflowing_div(self, rhs: $t) -> ($t, bool) {
|
||||||
|
if self == $t::MIN && rhs == -1 {
|
||||||
|
(1, true)
|
||||||
|
} else {
|
||||||
|
(self/rhs, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn overflowing_rem(self, rhs: $t) -> ($t, bool) {
|
||||||
|
if self == $t::MIN && rhs == -1 {
|
||||||
|
(0, true)
|
||||||
|
} else {
|
||||||
|
(self % rhs, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn overflowing_shl(self, rhs: u32) -> ($t, bool) {
|
||||||
|
(self << (rhs & self::shift_max::$t),
|
||||||
|
(rhs > self::shift_max::$t))
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn overflowing_shr(self, rhs: u32) -> ($t, bool) {
|
||||||
|
(self >> (rhs & self::shift_max::$t),
|
||||||
|
(rhs > self::shift_max::$t))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)*)
|
)*)
|
||||||
}
|
}
|
||||||
|
@ -234,6 +284,26 @@ impl OverflowingOps for usize {
|
||||||
(res.0 as usize, res.1)
|
(res.0 as usize, res.1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn overflowing_div(self, rhs: usize) -> (usize, bool) {
|
||||||
|
let (r, f) = (self as u64).overflowing_div(rhs as u64);
|
||||||
|
(r as usize, f)
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn overflowing_rem(self, rhs: usize) -> (usize, bool) {
|
||||||
|
let (r, f) = (self as u64).overflowing_rem(rhs as u64);
|
||||||
|
(r as usize, f)
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn overflowing_shl(self, rhs: u32) -> (usize, bool) {
|
||||||
|
let (r, f) = (self as u64).overflowing_shl(rhs);
|
||||||
|
(r as usize, f)
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn overflowing_shr(self, rhs: u32) -> (usize, bool) {
|
||||||
|
let (r, f) = (self as u64).overflowing_shr(rhs);
|
||||||
|
(r as usize, f)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
|
@ -259,6 +329,26 @@ impl OverflowingOps for usize {
|
||||||
(res.0 as usize, res.1)
|
(res.0 as usize, res.1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn overflowing_div(self, rhs: usize) -> (usize, bool) {
|
||||||
|
let (r, f) = (self as u32).overflowing_div(rhs as u32);
|
||||||
|
(r as usize, f)
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn overflowing_rem(self, rhs: usize) -> (usize, bool) {
|
||||||
|
let (r, f) = (self as u32).overflowing_rem(rhs as u32);
|
||||||
|
(r as usize, f)
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn overflowing_shl(self, rhs: u32) -> (usize, bool) {
|
||||||
|
let (r, f) = (self as u32).overflowing_shl(rhs);
|
||||||
|
(r as usize, f)
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn overflowing_shr(self, rhs: u32) -> (usize, bool) {
|
||||||
|
let (r, f) = (self as u32).overflowing_shr(rhs);
|
||||||
|
(r as usize, f)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
|
@ -284,6 +374,26 @@ impl OverflowingOps for isize {
|
||||||
(res.0 as isize, res.1)
|
(res.0 as isize, res.1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn overflowing_div(self, rhs: isize) -> (isize, bool) {
|
||||||
|
let (r, f) = (self as i64).overflowing_div(rhs as i64);
|
||||||
|
(r as isize, f)
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn overflowing_rem(self, rhs: isize) -> (isize, bool) {
|
||||||
|
let (r, f) = (self as i64).overflowing_rem(rhs as i64);
|
||||||
|
(r as isize, f)
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn overflowing_shl(self, rhs: u32) -> (isize, bool) {
|
||||||
|
let (r, f) = (self as i64).overflowing_shl(rhs);
|
||||||
|
(r as isize, f)
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn overflowing_shr(self, rhs: u32) -> (isize, bool) {
|
||||||
|
let (r, f) = (self as i64).overflowing_shr(rhs);
|
||||||
|
(r as isize, f)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
|
@ -309,4 +419,24 @@ impl OverflowingOps for isize {
|
||||||
(res.0 as isize, res.1)
|
(res.0 as isize, res.1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn overflowing_div(self, rhs: isize) -> (isize, bool) {
|
||||||
|
let (r, f) = (self as i32).overflowing_div(rhs as i32);
|
||||||
|
(r as isize, f)
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn overflowing_rem(self, rhs: isize) -> (isize, bool) {
|
||||||
|
let (r, f) = (self as i32).overflowing_rem(rhs as i32);
|
||||||
|
(r as isize, f)
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn overflowing_shl(self, rhs: u32) -> (isize, bool) {
|
||||||
|
let (r, f) = (self as i32).overflowing_shl(rhs);
|
||||||
|
(r as isize, f)
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn overflowing_shr(self, rhs: u32) -> (isize, bool) {
|
||||||
|
let (r, f) = (self as i32).overflowing_shr(rhs);
|
||||||
|
(r as isize, f)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,8 +154,6 @@ use mem;
|
||||||
use ops::FnOnce;
|
use ops::FnOnce;
|
||||||
use result::Result::{Ok, Err};
|
use result::Result::{Ok, Err};
|
||||||
use result::Result;
|
use result::Result;
|
||||||
#[allow(deprecated)]
|
|
||||||
use slice::AsSlice;
|
|
||||||
use slice;
|
use slice;
|
||||||
|
|
||||||
// Note that this is not a lang item per se, but it has a hidden dependency on
|
// Note that this is not a lang item per se, but it has a hidden dependency on
|
||||||
|
@ -765,25 +763,6 @@ impl<T: Default> Option<T> {
|
||||||
// Trait implementations
|
// Trait implementations
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[unstable(feature = "core",
|
|
||||||
reason = "waiting on the stability of the trait itself")]
|
|
||||||
#[deprecated(since = "1.0.0",
|
|
||||||
reason = "use the inherent method instead")]
|
|
||||||
#[allow(deprecated)]
|
|
||||||
impl<T> AsSlice<T> for Option<T> {
|
|
||||||
/// Convert from `Option<T>` to `&[T]` (without copying)
|
|
||||||
#[inline]
|
|
||||||
fn as_slice<'a>(&'a self) -> &'a [T] {
|
|
||||||
match *self {
|
|
||||||
Some(ref x) => slice::ref_slice(x),
|
|
||||||
None => {
|
|
||||||
let result: &[_] = &[];
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T> Default for Option<T> {
|
impl<T> Default for Option<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -37,10 +37,11 @@ pub use char::CharExt;
|
||||||
pub use clone::Clone;
|
pub use clone::Clone;
|
||||||
pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
|
pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
|
||||||
pub use convert::{AsRef, AsMut, Into, From};
|
pub use convert::{AsRef, AsMut, Into, From};
|
||||||
pub use iter::Extend;
|
pub use iter::{Iterator, DoubleEndedIterator, Extend, ExactSizeIterator};
|
||||||
pub use iter::{Iterator, DoubleEndedIterator};
|
|
||||||
pub use iter::{ExactSizeIterator};
|
|
||||||
pub use option::Option::{self, Some, None};
|
pub use option::Option::{self, Some, None};
|
||||||
pub use result::Result::{self, Ok, Err};
|
pub use result::Result::{self, Ok, Err};
|
||||||
pub use slice::{AsSlice, SliceExt};
|
pub use slice::SliceExt;
|
||||||
pub use str::{Str, StrExt};
|
pub use str::StrExt;
|
||||||
|
|
||||||
|
#[allow(deprecated)] pub use slice::AsSlice;
|
||||||
|
#[allow(deprecated)] pub use str::Str;
|
||||||
|
|
|
@ -157,21 +157,6 @@ pub fn null<T>() -> *const T { 0 as *const T }
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn null_mut<T>() -> *mut T { 0 as *mut T }
|
pub fn null_mut<T>() -> *mut T { 0 as *mut T }
|
||||||
|
|
||||||
/// Zeroes out `count * size_of::<T>` bytes of memory at `dst`. `count` may be
|
|
||||||
/// `0`.
|
|
||||||
///
|
|
||||||
/// # Safety
|
|
||||||
///
|
|
||||||
/// Beyond accepting a raw pointer, this is unsafe because it will not drop the
|
|
||||||
/// contents of `dst`, and may be used to create invalid instances of `T`.
|
|
||||||
#[inline]
|
|
||||||
#[unstable(feature = "core",
|
|
||||||
reason = "may play a larger role in std::ptr future extensions")]
|
|
||||||
#[deprecated(since = "1.0.0", reason = "use `write_bytes` instead")]
|
|
||||||
pub unsafe fn zero_memory<T>(dst: *mut T, count: usize) {
|
|
||||||
write_bytes(dst, 0, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Swaps the values at two mutable locations of the same type, without
|
/// Swaps the values at two mutable locations of the same type, without
|
||||||
/// deinitialising either. They may overlap, unlike `mem::swap` which is
|
/// deinitialising either. They may overlap, unlike `mem::swap` which is
|
||||||
/// otherwise equivalent.
|
/// otherwise equivalent.
|
||||||
|
|
|
@ -64,19 +64,6 @@ pub struct Slice<T> {
|
||||||
|
|
||||||
impl<T> Copy for Slice<T> {}
|
impl<T> Copy for Slice<T> {}
|
||||||
|
|
||||||
/// The representation of an old closure.
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Copy)]
|
|
||||||
#[unstable(feature = "core")]
|
|
||||||
#[deprecated(reason = "unboxed new closures do not have a universal representation; \
|
|
||||||
`&Fn` (etc) trait objects should use `TraitObject` instead",
|
|
||||||
since= "1.0.0")]
|
|
||||||
#[allow(deprecated) /* for deriving Copy impl */]
|
|
||||||
pub struct Closure {
|
|
||||||
pub code: *mut (),
|
|
||||||
pub env: *mut (),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The representation of a trait object like `&SomeTrait`.
|
/// The representation of a trait object like `&SomeTrait`.
|
||||||
///
|
///
|
||||||
/// This struct has the same layout as types like `&SomeTrait` and
|
/// This struct has the same layout as types like `&SomeTrait` and
|
||||||
|
|
|
@ -88,10 +88,6 @@ pub trait SliceExt {
|
||||||
fn len(&self) -> usize;
|
fn len(&self) -> usize;
|
||||||
fn is_empty(&self) -> bool { self.len() == 0 }
|
fn is_empty(&self) -> bool { self.len() == 0 }
|
||||||
fn get_mut<'a>(&'a mut self, index: usize) -> Option<&'a mut Self::Item>;
|
fn get_mut<'a>(&'a mut self, index: usize) -> Option<&'a mut Self::Item>;
|
||||||
#[unstable(feature = "core",
|
|
||||||
reason = "will be replaced by slice syntax")]
|
|
||||||
#[deprecated(since = "1.0.0", reason = "use &mut s[..] instead")]
|
|
||||||
fn as_mut_slice<'a>(&'a mut self) -> &'a mut [Self::Item];
|
|
||||||
fn iter_mut<'a>(&'a mut self) -> IterMut<'a, 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 first_mut<'a>(&'a mut self) -> Option<&'a mut Self::Item>;
|
||||||
fn tail_mut<'a>(&'a mut self) -> &'a mut [Self::Item];
|
fn tail_mut<'a>(&'a mut self) -> &'a mut [Self::Item];
|
||||||
|
@ -263,12 +259,6 @@ impl<T> SliceExt for [T] {
|
||||||
if index < self.len() { Some(&mut self[index]) } else { None }
|
if index < self.len() { Some(&mut self[index]) } else { None }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
#[unstable(feature = "core",
|
|
||||||
reason = "will be replaced by slice syntax")]
|
|
||||||
#[deprecated(since = "1.0.0", reason = "use &mut s[..] instead")]
|
|
||||||
fn as_mut_slice(&mut self) -> &mut [T] { self }
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
|
fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1502,54 +1492,6 @@ pub unsafe fn from_raw_parts_mut<'a, T>(p: *mut T, len: usize) -> &'a mut [T] {
|
||||||
transmute(RawSlice { data: p, len: len })
|
transmute(RawSlice { data: p, len: len })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Forms a slice from a pointer and a length.
|
|
||||||
///
|
|
||||||
/// The pointer given is actually a reference to the base of the slice. This
|
|
||||||
/// reference is used to give a concrete lifetime to tie the returned slice to.
|
|
||||||
/// Typically this should indicate that the slice is valid for as long as the
|
|
||||||
/// pointer itself is valid.
|
|
||||||
///
|
|
||||||
/// The `len` argument is the number of **elements**, not the number of bytes.
|
|
||||||
///
|
|
||||||
/// This function is unsafe as there is no guarantee that the given pointer is
|
|
||||||
/// valid for `len` elements, nor whether the lifetime provided is a suitable
|
|
||||||
/// lifetime for the returned slice.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// #![feature(core)]
|
|
||||||
/// use std::slice;
|
|
||||||
///
|
|
||||||
/// // manifest a slice out of thin air!
|
|
||||||
/// let ptr = 0x1234 as *const usize;
|
|
||||||
/// let amt = 10;
|
|
||||||
/// unsafe {
|
|
||||||
/// let slice = slice::from_raw_buf(&ptr, amt);
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
#[inline]
|
|
||||||
#[unstable(feature = "core")]
|
|
||||||
#[deprecated(since = "1.0.0",
|
|
||||||
reason = "use from_raw_parts")]
|
|
||||||
pub unsafe fn from_raw_buf<'a, T>(p: &'a *const T, len: usize) -> &'a [T] {
|
|
||||||
transmute(RawSlice { data: *p, len: len })
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Performs the same functionality as `from_raw_buf`, except that a mutable
|
|
||||||
/// slice is returned.
|
|
||||||
///
|
|
||||||
/// This function is unsafe for the same reasons as `from_raw_buf`, as well as
|
|
||||||
/// not being able to provide a non-aliasing guarantee of the returned mutable
|
|
||||||
/// slice.
|
|
||||||
#[inline]
|
|
||||||
#[unstable(feature = "core")]
|
|
||||||
#[deprecated(since = "1.0.0",
|
|
||||||
reason = "use from_raw_parts_mut")]
|
|
||||||
pub unsafe fn from_raw_mut_buf<'a, T>(p: &'a *mut T, len: usize) -> &'a mut [T] {
|
|
||||||
transmute(RawSlice { data: *p, len: len })
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Submodules
|
// Submodules
|
||||||
//
|
//
|
||||||
|
|
|
@ -28,8 +28,6 @@ use iter::ExactSizeIterator;
|
||||||
use iter::{Map, Iterator, DoubleEndedIterator};
|
use iter::{Map, Iterator, DoubleEndedIterator};
|
||||||
use marker::Sized;
|
use marker::Sized;
|
||||||
use mem;
|
use mem;
|
||||||
#[allow(deprecated)]
|
|
||||||
use num::Int;
|
|
||||||
use ops::{Fn, FnMut, FnOnce};
|
use ops::{Fn, FnMut, FnOnce};
|
||||||
use option::Option::{self, None, Some};
|
use option::Option::{self, None, Some};
|
||||||
use raw::{Repr, Slice};
|
use raw::{Repr, Slice};
|
||||||
|
@ -243,78 +241,6 @@ pub unsafe fn from_utf8_unchecked<'a>(v: &'a [u8]) -> &'a str {
|
||||||
mem::transmute(v)
|
mem::transmute(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a static string slice from a given raw pointer.
|
|
||||||
///
|
|
||||||
/// This function will read memory starting at `s` until it finds a 0, and then
|
|
||||||
/// transmute the memory up to that point as a string slice, returning the
|
|
||||||
/// corresponding `&'static str` value.
|
|
||||||
///
|
|
||||||
/// This function is unsafe because the caller must ensure the C string itself
|
|
||||||
/// has the static lifetime and that the memory `s` is valid up to and including
|
|
||||||
/// the first null byte.
|
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// This function will panic if the string pointed to by `s` is not valid UTF-8.
|
|
||||||
#[unstable(feature = "core")]
|
|
||||||
#[deprecated(since = "1.0.0",
|
|
||||||
reason = "use std::ffi::c_str_to_bytes + str::from_utf8")]
|
|
||||||
pub unsafe fn from_c_str(s: *const i8) -> &'static str {
|
|
||||||
let s = s as *const u8;
|
|
||||||
let mut len: usize = 0;
|
|
||||||
while *s.offset(len as isize) != 0 {
|
|
||||||
len += 1;
|
|
||||||
}
|
|
||||||
let v: &'static [u8] = ::mem::transmute(Slice { data: s, len: len });
|
|
||||||
from_utf8(v).ok().expect("from_c_str passed invalid utf-8 data")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Something that can be used to compare against a character
|
|
||||||
#[unstable(feature = "core")]
|
|
||||||
#[deprecated(since = "1.0.0",
|
|
||||||
reason = "use `Pattern` instead")]
|
|
||||||
// NB: Rather than removing it, make it private and move it into self::pattern
|
|
||||||
pub trait CharEq {
|
|
||||||
/// Determine if the splitter should split at the given character
|
|
||||||
fn matches(&mut self, char) -> bool;
|
|
||||||
/// Indicate if this is only concerned about ASCII characters,
|
|
||||||
/// which can allow for a faster implementation.
|
|
||||||
fn only_ascii(&self) -> bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(deprecated) /* for CharEq */ ]
|
|
||||||
impl CharEq for char {
|
|
||||||
#[inline]
|
|
||||||
fn matches(&mut self, c: char) -> bool { *self == c }
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn only_ascii(&self) -> bool { (*self as u32) < 128 }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(deprecated) /* for CharEq */ ]
|
|
||||||
impl<F> CharEq for F where F: FnMut(char) -> bool {
|
|
||||||
#[inline]
|
|
||||||
fn matches(&mut self, c: char) -> bool { (*self)(c) }
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn only_ascii(&self) -> bool { false }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(deprecated) /* for CharEq */ ]
|
|
||||||
impl<'a> CharEq for &'a [char] {
|
|
||||||
#[inline]
|
|
||||||
#[allow(deprecated) /* for CharEq */ ]
|
|
||||||
fn matches(&mut self, c: char) -> bool {
|
|
||||||
self.iter().any(|&m| { let mut m = m; m.matches(c) })
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
#[allow(deprecated) /* for CharEq */ ]
|
|
||||||
fn only_ascii(&self) -> bool {
|
|
||||||
self.iter().all(|m| m.only_ascii())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl Error for Utf8Error {
|
impl Error for Utf8Error {
|
||||||
fn description(&self) -> &str {
|
fn description(&self) -> &str {
|
||||||
|
@ -1047,22 +973,6 @@ impl<'a, P: Pattern<'a>> Iterator for MatchIndices<'a, P> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An iterator over the substrings of a string separated by a given
|
|
||||||
/// search string
|
|
||||||
#[unstable(feature = "core")]
|
|
||||||
#[deprecated(since = "1.0.0", reason = "use `Split` with a `&str`")]
|
|
||||||
pub struct SplitStr<'a, P: Pattern<'a>>(Split<'a, P>);
|
|
||||||
#[allow(deprecated)]
|
|
||||||
impl<'a, P: Pattern<'a>> Iterator for SplitStr<'a, P> {
|
|
||||||
type Item = &'a str;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
#[allow(deprecated)]
|
|
||||||
fn next(&mut self) -> Option<&'a str> {
|
|
||||||
Iterator::next(&mut self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'b> OldMatchIndices<'a, 'b> {
|
impl<'a, 'b> OldMatchIndices<'a, 'b> {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -1444,8 +1354,6 @@ pub trait StrExt {
|
||||||
fn rsplitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> RSplitN<'a, P>
|
fn rsplitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> RSplitN<'a, P>
|
||||||
where P::Searcher: ReverseSearcher<'a>;
|
where P::Searcher: ReverseSearcher<'a>;
|
||||||
fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P>;
|
fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P>;
|
||||||
#[allow(deprecated) /* for SplitStr */]
|
|
||||||
fn split_str<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitStr<'a, P>;
|
|
||||||
fn lines<'a>(&'a self) -> Lines<'a>;
|
fn lines<'a>(&'a self) -> Lines<'a>;
|
||||||
fn lines_any<'a>(&'a self) -> LinesAny<'a>;
|
fn lines_any<'a>(&'a self) -> LinesAny<'a>;
|
||||||
fn char_len(&self) -> usize;
|
fn char_len(&self) -> usize;
|
||||||
|
@ -1565,12 +1473,6 @@ impl StrExt for str {
|
||||||
MatchIndices(pat.into_searcher(self))
|
MatchIndices(pat.into_searcher(self))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
#[allow(deprecated) /* for SplitStr */ ]
|
|
||||||
fn split_str<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitStr<'a, P> {
|
|
||||||
SplitStr(self.split(pat))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn lines(&self) -> Lines {
|
fn lines(&self) -> Lines {
|
||||||
Lines { inner: self.split_terminator('\n').0 }
|
Lines { inner: self.split_terminator('\n').0 }
|
||||||
|
|
|
@ -8,10 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#![allow(deprecated) /* for CharEq */ ]
|
|
||||||
|
|
||||||
use prelude::*;
|
use prelude::*;
|
||||||
use super::CharEq;
|
|
||||||
|
|
||||||
// Pattern
|
// Pattern
|
||||||
|
|
||||||
|
@ -228,6 +225,40 @@ pub trait DoubleEndedSearcher<'a>: ReverseSearcher<'a> {}
|
||||||
|
|
||||||
// Impl for a CharEq wrapper
|
// Impl for a CharEq wrapper
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
trait CharEq {
|
||||||
|
fn matches(&mut self, char) -> bool;
|
||||||
|
fn only_ascii(&self) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CharEq for char {
|
||||||
|
#[inline]
|
||||||
|
fn matches(&mut self, c: char) -> bool { *self == c }
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn only_ascii(&self) -> bool { (*self as u32) < 128 }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F> CharEq for F where F: FnMut(char) -> bool {
|
||||||
|
#[inline]
|
||||||
|
fn matches(&mut self, c: char) -> bool { (*self)(c) }
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn only_ascii(&self) -> bool { false }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> CharEq for &'a [char] {
|
||||||
|
#[inline]
|
||||||
|
fn matches(&mut self, c: char) -> bool {
|
||||||
|
self.iter().any(|&m| { let mut m = m; m.matches(c) })
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn only_ascii(&self) -> bool {
|
||||||
|
self.iter().all(|m| m.only_ascii())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct CharEqPattern<C: CharEq>(C);
|
struct CharEqPattern<C: CharEq>(C);
|
||||||
|
|
||||||
struct CharEqSearcher<'a, C: CharEq> {
|
struct CharEqSearcher<'a, C: CharEq> {
|
||||||
|
@ -425,65 +456,116 @@ fn str_search_step<F, G>(mut m: &mut StrSearcher,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! associated_items {
|
macro_rules! char_eq_pattern_impl {
|
||||||
($t:ty, $s:ident, $e:expr) => {
|
($wrapper:ty, $wrapper_ident:ident) => {
|
||||||
// FIXME: #22463
|
fn into_searcher(self, haystack: &'a str) -> $wrapper {
|
||||||
//type Searcher = $t;
|
$wrapper_ident(CharEqPattern(self).into_searcher(haystack))
|
||||||
|
|
||||||
fn into_searcher(self, haystack: &'a str) -> $t {
|
|
||||||
let $s = self;
|
|
||||||
$e.into_searcher(haystack)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_contained_in(self, haystack: &'a str) -> bool {
|
fn is_contained_in(self, haystack: &'a str) -> bool {
|
||||||
let $s = self;
|
CharEqPattern(self).is_contained_in(haystack)
|
||||||
$e.is_contained_in(haystack)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_prefix_of(self, haystack: &'a str) -> bool {
|
fn is_prefix_of(self, haystack: &'a str) -> bool {
|
||||||
let $s = self;
|
CharEqPattern(self).is_prefix_of(haystack)
|
||||||
$e.is_prefix_of(haystack)
|
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
// FIXME: #21750
|
|
||||||
/*#[inline]
|
|
||||||
fn is_suffix_of(self, haystack: &'a str) -> bool
|
fn is_suffix_of(self, haystack: &'a str) -> bool
|
||||||
where $t: ReverseSearcher<'a>
|
where $wrapper: ReverseSearcher<'a>
|
||||||
{
|
{
|
||||||
let $s = self;
|
CharEqPattern(self).is_suffix_of(haystack)
|
||||||
$e.is_suffix_of(haystack)
|
}
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CharEq delegation impls
|
// Pattern for char
|
||||||
|
|
||||||
/// Searches for chars that are equal to a given char
|
|
||||||
impl<'a> Pattern<'a> for char {
|
impl<'a> Pattern<'a> for char {
|
||||||
type Searcher = <CharEqPattern<Self> as Pattern<'a>>::Searcher;
|
type Searcher = CharSearcher<'a>;
|
||||||
associated_items!(<CharEqPattern<Self> as Pattern<'a>>::Searcher,
|
char_eq_pattern_impl!(CharSearcher<'a>, CharSearcher);
|
||||||
s, CharEqPattern(s));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Searches for chars that are equal to any of the chars in the array
|
pub struct CharSearcher<'a>(CharEqSearcher<'a, char>);
|
||||||
|
|
||||||
|
unsafe impl<'a> Searcher<'a> for CharSearcher<'a> {
|
||||||
|
#[inline]
|
||||||
|
fn haystack(&self) -> &'a str { self.0.haystack() }
|
||||||
|
#[inline]
|
||||||
|
fn next(&mut self) -> SearchStep { self.0.next() }
|
||||||
|
}
|
||||||
|
unsafe impl<'a> ReverseSearcher<'a> for CharSearcher<'a> {
|
||||||
|
#[inline]
|
||||||
|
fn next_back(&mut self) -> SearchStep { self.0.next_back() }
|
||||||
|
}
|
||||||
|
impl<'a> DoubleEndedSearcher<'a> for CharSearcher<'a> {}
|
||||||
|
|
||||||
|
// Pattern for &[char]
|
||||||
|
|
||||||
impl<'a, 'b> Pattern<'a> for &'b [char] {
|
impl<'a, 'b> Pattern<'a> for &'b [char] {
|
||||||
type Searcher = <CharEqPattern<Self> as Pattern<'a>>::Searcher;
|
type Searcher = CharSliceSearcher<'a, 'b>;
|
||||||
associated_items!(<CharEqPattern<Self> as Pattern<'a>>::Searcher,
|
char_eq_pattern_impl!(CharSliceSearcher<'a, 'b>, CharSliceSearcher);
|
||||||
s, CharEqPattern(s));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A convenience impl that delegates to the impl for `&str`
|
pub struct CharSliceSearcher<'a, 'b>(CharEqSearcher<'a, &'b [char]>);
|
||||||
|
|
||||||
|
unsafe impl<'a, 'b> Searcher<'a> for CharSliceSearcher<'a, 'b> {
|
||||||
|
#[inline]
|
||||||
|
fn haystack(&self) -> &'a str { self.0.haystack() }
|
||||||
|
#[inline]
|
||||||
|
fn next(&mut self) -> SearchStep { self.0.next() }
|
||||||
|
}
|
||||||
|
unsafe impl<'a, 'b> ReverseSearcher<'a> for CharSliceSearcher<'a, 'b> {
|
||||||
|
#[inline]
|
||||||
|
fn next_back(&mut self) -> SearchStep { self.0.next_back() }
|
||||||
|
}
|
||||||
|
impl<'a, 'b> DoubleEndedSearcher<'a> for CharSliceSearcher<'a, 'b> {}
|
||||||
|
|
||||||
|
// Pattern for predicates
|
||||||
|
|
||||||
|
impl<'a, F: FnMut(char) -> bool> Pattern<'a> for F {
|
||||||
|
type Searcher = CharPredSearcher<'a, F>;
|
||||||
|
char_eq_pattern_impl!(CharPredSearcher<'a, F>, CharPredSearcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CharPredSearcher<'a, F: FnMut(char) -> bool>(CharEqSearcher<'a, F>);
|
||||||
|
|
||||||
|
unsafe impl<'a, F> Searcher<'a> for CharPredSearcher<'a, F>
|
||||||
|
where F: FnMut(char) -> bool
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn haystack(&self) -> &'a str { self.0.haystack() }
|
||||||
|
#[inline]
|
||||||
|
fn next(&mut self) -> SearchStep { self.0.next() }
|
||||||
|
}
|
||||||
|
unsafe impl<'a, F> ReverseSearcher<'a> for CharPredSearcher<'a, F>
|
||||||
|
where F: FnMut(char) -> bool
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn next_back(&mut self) -> SearchStep { self.0.next_back() }
|
||||||
|
}
|
||||||
|
impl<'a, F> DoubleEndedSearcher<'a> for CharPredSearcher<'a, F>
|
||||||
|
where F: FnMut(char) -> bool
|
||||||
|
{}
|
||||||
|
|
||||||
|
// Pattern for &&str
|
||||||
|
|
||||||
impl<'a, 'b> Pattern<'a> for &'b &'b str {
|
impl<'a, 'b> Pattern<'a> for &'b &'b str {
|
||||||
type Searcher = <&'b str as Pattern<'a>>::Searcher;
|
type Searcher = <&'b str as Pattern<'a>>::Searcher;
|
||||||
associated_items!(<&'b str as Pattern<'a>>::Searcher,
|
#[inline]
|
||||||
s, (*s));
|
fn into_searcher(self, haystack: &'a str)
|
||||||
}
|
-> <&'b str as Pattern<'a>>::Searcher {
|
||||||
|
(*self).into_searcher(haystack)
|
||||||
/// Searches for chars that match the given predicate
|
}
|
||||||
impl<'a, F> Pattern<'a> for F where F: FnMut(char) -> bool {
|
#[inline]
|
||||||
type Searcher = <CharEqPattern<Self> as Pattern<'a>>::Searcher;
|
fn is_contained_in(self, haystack: &'a str) -> bool {
|
||||||
associated_items!(<CharEqPattern<Self> as Pattern<'a>>::Searcher,
|
(*self).is_contained_in(haystack)
|
||||||
s, CharEqPattern(s));
|
}
|
||||||
|
#[inline]
|
||||||
|
fn is_prefix_of(self, haystack: &'a str) -> bool {
|
||||||
|
(*self).is_prefix_of(haystack)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn is_suffix_of(self, haystack: &'a str) -> bool {
|
||||||
|
(*self).is_suffix_of(haystack)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,6 @@ fn double_imm_borrow() {
|
||||||
fn no_mut_then_imm_borrow() {
|
fn no_mut_then_imm_borrow() {
|
||||||
let x = RefCell::new(0);
|
let x = RefCell::new(0);
|
||||||
let _b1 = x.borrow_mut();
|
let _b1 = x.borrow_mut();
|
||||||
assert!(x.try_borrow().is_none());
|
|
||||||
assert_eq!(x.borrow_state(), BorrowState::Writing);
|
assert_eq!(x.borrow_state(), BorrowState::Writing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +66,6 @@ fn no_mut_then_imm_borrow() {
|
||||||
fn no_imm_then_borrow_mut() {
|
fn no_imm_then_borrow_mut() {
|
||||||
let x = RefCell::new(0);
|
let x = RefCell::new(0);
|
||||||
let _b1 = x.borrow();
|
let _b1 = x.borrow();
|
||||||
assert!(x.try_borrow_mut().is_none());
|
|
||||||
assert_eq!(x.borrow_state(), BorrowState::Reading);
|
assert_eq!(x.borrow_state(), BorrowState::Reading);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +74,6 @@ fn no_double_borrow_mut() {
|
||||||
let x = RefCell::new(0);
|
let x = RefCell::new(0);
|
||||||
assert_eq!(x.borrow_state(), BorrowState::Unused);
|
assert_eq!(x.borrow_state(), BorrowState::Unused);
|
||||||
let _b1 = x.borrow_mut();
|
let _b1 = x.borrow_mut();
|
||||||
assert!(x.try_borrow_mut().is_none());
|
|
||||||
assert_eq!(x.borrow_state(), BorrowState::Writing);
|
assert_eq!(x.borrow_state(), BorrowState::Writing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +102,7 @@ fn double_borrow_single_release_no_borrow_mut() {
|
||||||
{
|
{
|
||||||
let _b2 = x.borrow();
|
let _b2 = x.borrow();
|
||||||
}
|
}
|
||||||
assert!(x.try_borrow_mut().is_none());
|
assert_eq!(x.borrow_state(), BorrowState::Reading);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -122,14 +119,14 @@ fn clone_ref_updates_flag() {
|
||||||
let x = RefCell::new(0);
|
let x = RefCell::new(0);
|
||||||
{
|
{
|
||||||
let b1 = x.borrow();
|
let b1 = x.borrow();
|
||||||
assert!(x.try_borrow_mut().is_none());
|
assert_eq!(x.borrow_state(), BorrowState::Reading);
|
||||||
{
|
{
|
||||||
let _b2 = clone_ref(&b1);
|
let _b2 = clone_ref(&b1);
|
||||||
assert!(x.try_borrow_mut().is_none());
|
assert_eq!(x.borrow_state(), BorrowState::Reading);
|
||||||
}
|
}
|
||||||
assert!(x.try_borrow_mut().is_none());
|
assert_eq!(x.borrow_state(), BorrowState::Reading);
|
||||||
}
|
}
|
||||||
assert!(x.try_borrow_mut().is_some());
|
assert_eq!(x.borrow_state(), BorrowState::Unused);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
|
||||||
// file at the top-level directory of this distribution and at
|
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
||||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
||||||
// option. This file may not be copied, modified, or distributed
|
|
||||||
// except according to those terms.
|
|
||||||
|
|
||||||
#![allow(deprecated)]
|
|
||||||
|
|
||||||
use core::finally::{try_finally, Finally};
|
|
||||||
use std::thread;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_success() {
|
|
||||||
let mut i = 0;
|
|
||||||
try_finally(
|
|
||||||
&mut i, (),
|
|
||||||
|i, ()| {
|
|
||||||
*i = 10;
|
|
||||||
},
|
|
||||||
|i| {
|
|
||||||
assert!(!thread::panicking());
|
|
||||||
assert_eq!(*i, 10);
|
|
||||||
*i = 20;
|
|
||||||
});
|
|
||||||
assert_eq!(i, 20);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_panic]
|
|
||||||
fn test_fail() {
|
|
||||||
let mut i = 0;
|
|
||||||
try_finally(
|
|
||||||
&mut i, (),
|
|
||||||
|i, ()| {
|
|
||||||
*i = 10;
|
|
||||||
panic!();
|
|
||||||
},
|
|
||||||
|i| {
|
|
||||||
assert!(thread::panicking());
|
|
||||||
assert_eq!(*i, 10);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_retval() {
|
|
||||||
let mut closure = || 10;
|
|
||||||
// FIXME(#16640) `: i32` annotation shouldn't be necessary
|
|
||||||
let i: i32 = closure.finally(|| { });
|
|
||||||
assert_eq!(i, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_compact() {
|
|
||||||
fn do_some_fallible_work() {}
|
|
||||||
fn but_always_run_this_function() { }
|
|
||||||
let mut f = do_some_fallible_work;
|
|
||||||
f.finally(but_always_run_this_function);
|
|
||||||
}
|
|
|
@ -72,7 +72,7 @@ fn test_multi_iter() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_counter_from_iter() {
|
fn test_counter_from_iter() {
|
||||||
let it = count(0, 5).take(10);
|
let it = (0..).step_by(5).take(10);
|
||||||
let xs: Vec<isize> = FromIterator::from_iter(it);
|
let xs: Vec<isize> = FromIterator::from_iter(it);
|
||||||
assert_eq!(xs, [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]);
|
assert_eq!(xs, [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]);
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ fn test_iterator_chain() {
|
||||||
}
|
}
|
||||||
assert_eq!(i, expected.len());
|
assert_eq!(i, expected.len());
|
||||||
|
|
||||||
let ys = count(30, 10).take(4);
|
let ys = (30..).step_by(10).take(4);
|
||||||
let it = xs.iter().cloned().chain(ys);
|
let it = xs.iter().cloned().chain(ys);
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
for x in it {
|
for x in it {
|
||||||
|
@ -102,7 +102,7 @@ fn test_iterator_chain() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_filter_map() {
|
fn test_filter_map() {
|
||||||
let it = count(0, 1).take(10)
|
let it = (0..).step_by(1).take(10)
|
||||||
.filter_map(|x| if x % 2 == 0 { Some(x*x) } else { None });
|
.filter_map(|x| if x % 2 == 0 { Some(x*x) } else { None });
|
||||||
assert_eq!(it.collect::<Vec<usize>>(), [0*0, 2*2, 4*4, 6*6, 8*8]);
|
assert_eq!(it.collect::<Vec<usize>>(), [0*0, 2*2, 4*4, 6*6, 8*8]);
|
||||||
}
|
}
|
||||||
|
@ -244,7 +244,7 @@ fn test_iterator_scan() {
|
||||||
fn test_iterator_flat_map() {
|
fn test_iterator_flat_map() {
|
||||||
let xs = [0, 3, 6];
|
let xs = [0, 3, 6];
|
||||||
let ys = [0, 1, 2, 3, 4, 5, 6, 7, 8];
|
let ys = [0, 1, 2, 3, 4, 5, 6, 7, 8];
|
||||||
let it = xs.iter().flat_map(|&x| count(x, 1).take(3));
|
let it = xs.iter().flat_map(|&x| (x..).step_by(1).take(3));
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
for x in it {
|
for x in it {
|
||||||
assert_eq!(x, ys[i]);
|
assert_eq!(x, ys[i]);
|
||||||
|
@ -291,13 +291,13 @@ fn test_unfoldr() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_cycle() {
|
fn test_cycle() {
|
||||||
let cycle_len = 3;
|
let cycle_len = 3;
|
||||||
let it = count(0, 1).take(cycle_len).cycle();
|
let it = (0..).step_by(1).take(cycle_len).cycle();
|
||||||
assert_eq!(it.size_hint(), (usize::MAX, None));
|
assert_eq!(it.size_hint(), (usize::MAX, None));
|
||||||
for (i, x) in it.take(100).enumerate() {
|
for (i, x) in it.take(100).enumerate() {
|
||||||
assert_eq!(i % cycle_len, x);
|
assert_eq!(i % cycle_len, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut it = count(0, 1).take(0).cycle();
|
let mut it = (0..).step_by(1).take(0).cycle();
|
||||||
assert_eq!(it.size_hint(), (0, Some(0)));
|
assert_eq!(it.size_hint(), (0, Some(0)));
|
||||||
assert_eq!(it.next(), None);
|
assert_eq!(it.next(), None);
|
||||||
}
|
}
|
||||||
|
@ -360,7 +360,7 @@ fn test_iterator_min() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_iterator_size_hint() {
|
fn test_iterator_size_hint() {
|
||||||
let c = count(0, 1);
|
let c = (0..).step_by(1);
|
||||||
let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||||
let v2 = &[10, 11, 12];
|
let v2 = &[10, 11, 12];
|
||||||
let vi = v.iter();
|
let vi = v.iter();
|
||||||
|
|
|
@ -39,7 +39,6 @@ mod atomic;
|
||||||
mod cell;
|
mod cell;
|
||||||
mod char;
|
mod char;
|
||||||
mod cmp;
|
mod cmp;
|
||||||
mod finally;
|
|
||||||
mod fmt;
|
mod fmt;
|
||||||
mod hash;
|
mod hash;
|
||||||
mod iter;
|
mod iter;
|
||||||
|
|
|
@ -103,7 +103,7 @@ fn test_transmute() {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
assert_eq!([76], transmute::<_, Vec<u8>>("L".to_string()));
|
assert_eq!(transmute::<_, Vec<u8>>("L".to_string()), [76]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ mod tests {
|
||||||
fn test_overflows() {
|
fn test_overflows() {
|
||||||
assert!(MAX > 0);
|
assert!(MAX > 0);
|
||||||
assert!(MIN <= 0);
|
assert!(MIN <= 0);
|
||||||
assert!(MIN + MAX + 1 == 0);
|
assert!((MIN + MAX).wrapping_add(1) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -163,9 +163,9 @@ fn starts_short_long() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn contains_weird_cases() {
|
fn contains_weird_cases() {
|
||||||
assert!("* \t".contains_char(' '));
|
assert!("* \t".contains(' '));
|
||||||
assert!(!"* \t".contains_char('?'));
|
assert!(!"* \t".contains('?'));
|
||||||
assert!(!"* \t".contains_char('\u{1F4A9}'));
|
assert!(!"* \t".contains('\u{1F4A9}'));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -347,11 +347,11 @@ malesuada sollicitudin quam eu fermentum!");
|
||||||
make_test!(chars_count, s, s.chars().count());
|
make_test!(chars_count, s, s.chars().count());
|
||||||
|
|
||||||
make_test!(contains_bang_str, s, s.contains("!"));
|
make_test!(contains_bang_str, s, s.contains("!"));
|
||||||
make_test!(contains_bang_char, s, s.contains_char('!'));
|
make_test!(contains_bang_char, s, s.contains('!'));
|
||||||
|
|
||||||
make_test!(match_indices_a_str, s, s.match_indices("a").count());
|
make_test!(match_indices_a_str, s, s.match_indices("a").count());
|
||||||
|
|
||||||
make_test!(split_str_a_str, s, s.split_str("a").count());
|
make_test!(split_a_str, s, s.split("a").count());
|
||||||
|
|
||||||
make_test!(trim_ascii_char, s, {
|
make_test!(trim_ascii_char, s, {
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
|
@ -368,11 +368,11 @@ malesuada sollicitudin quam eu fermentum!");
|
||||||
|
|
||||||
make_test!(find_underscore_char, s, s.find('_'));
|
make_test!(find_underscore_char, s, s.find('_'));
|
||||||
make_test!(rfind_underscore_char, s, s.rfind('_'));
|
make_test!(rfind_underscore_char, s, s.rfind('_'));
|
||||||
make_test!(find_underscore_str, s, s.find_str("_"));
|
make_test!(find_underscore_str, s, s.find("_"));
|
||||||
|
|
||||||
make_test!(find_zzz_char, s, s.find('\u{1F4A4}'));
|
make_test!(find_zzz_char, s, s.find('\u{1F4A4}'));
|
||||||
make_test!(rfind_zzz_char, s, s.rfind('\u{1F4A4}'));
|
make_test!(rfind_zzz_char, s, s.rfind('\u{1F4A4}'));
|
||||||
make_test!(find_zzz_str, s, s.find_str("\u{1F4A4}"));
|
make_test!(find_zzz_str, s, s.find("\u{1F4A4}"));
|
||||||
|
|
||||||
make_test!(split_space_char, s, s.split(' ').count());
|
make_test!(split_space_char, s, s.split(' ').count());
|
||||||
make_test!(split_terminator_space_char, s, s.split_terminator(' ').count());
|
make_test!(split_terminator_space_char, s, s.split_terminator(' ').count());
|
||||||
|
@ -380,6 +380,6 @@ malesuada sollicitudin quam eu fermentum!");
|
||||||
make_test!(splitn_space_char, s, s.splitn(10, ' ').count());
|
make_test!(splitn_space_char, s, s.splitn(10, ' ').count());
|
||||||
make_test!(rsplitn_space_char, s, s.rsplitn(10, ' ').count());
|
make_test!(rsplitn_space_char, s, s.rsplitn(10, ' ').count());
|
||||||
|
|
||||||
make_test!(split_str_space_str, s, s.split_str(" ").count());
|
make_test!(split_space_str, s, s.split(" ").count());
|
||||||
make_test!(split_str_ad_str, s, s.split_str("ad").count());
|
make_test!(split_ad_str, s, s.split("ad").count());
|
||||||
}
|
}
|
||||||
|
|
|
@ -446,7 +446,7 @@ mod tests {
|
||||||
|
|
||||||
fn same(fmt: &'static str, p: &[Piece<'static>]) {
|
fn same(fmt: &'static str, p: &[Piece<'static>]) {
|
||||||
let parser = Parser::new(fmt);
|
let parser = Parser::new(fmt);
|
||||||
assert!(p == parser.collect::<Vec<Piece<'static>>>());
|
assert!(parser.collect::<Vec<Piece<'static>>>() == p);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fmtdflt() -> FormatSpec<'static> {
|
fn fmtdflt() -> FormatSpec<'static> {
|
||||||
|
|
|
@ -84,7 +84,7 @@
|
||||||
//!
|
//!
|
||||||
//! fn edges(&'a self) -> dot::Edges<'a,Ed> {
|
//! fn edges(&'a self) -> dot::Edges<'a,Ed> {
|
||||||
//! let &Edges(ref edges) = self;
|
//! let &Edges(ref edges) = self;
|
||||||
//! edges.as_slice().into_cow()
|
//! (&edges[..]).into_cow()
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! fn source(&self, e: &Ed) -> Nd { let &(s,_) = e; s }
|
//! fn source(&self, e: &Ed) -> Nd { let &(s,_) = e; s }
|
||||||
|
|
|
@ -198,7 +198,7 @@ impl Rand for ChaChaRng {
|
||||||
for word in &mut key {
|
for word in &mut key {
|
||||||
*word = other.gen();
|
*word = other.gen();
|
||||||
}
|
}
|
||||||
SeedableRng::from_seed(key.as_slice())
|
SeedableRng::from_seed(&key[..])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -154,7 +154,7 @@ pub trait Rng : Sized {
|
||||||
///
|
///
|
||||||
/// let mut v = [0; 13579];
|
/// let mut v = [0; 13579];
|
||||||
/// thread_rng().fill_bytes(&mut v);
|
/// thread_rng().fill_bytes(&mut v);
|
||||||
/// println!("{:?}", v.as_slice());
|
/// println!("{:?}", &v[..]);
|
||||||
/// ```
|
/// ```
|
||||||
fn fill_bytes(&mut self, dest: &mut [u8]) {
|
fn fill_bytes(&mut self, dest: &mut [u8]) {
|
||||||
// this could, in theory, be done by transmuting dest to a
|
// this could, in theory, be done by transmuting dest to a
|
||||||
|
@ -310,9 +310,9 @@ pub trait Rng : Sized {
|
||||||
/// let mut rng = thread_rng();
|
/// let mut rng = thread_rng();
|
||||||
/// let mut y = [1, 2, 3];
|
/// let mut y = [1, 2, 3];
|
||||||
/// rng.shuffle(&mut y);
|
/// rng.shuffle(&mut y);
|
||||||
/// println!("{:?}", y.as_slice());
|
/// println!("{:?}", y);
|
||||||
/// rng.shuffle(&mut y);
|
/// rng.shuffle(&mut y);
|
||||||
/// println!("{:?}", y.as_slice());
|
/// println!("{:?}", y);
|
||||||
/// ```
|
/// ```
|
||||||
fn shuffle<T>(&mut self, values: &mut [T]) {
|
fn shuffle<T>(&mut self, values: &mut [T]) {
|
||||||
let mut i = values.len();
|
let mut i = values.len();
|
||||||
|
|
|
@ -123,7 +123,6 @@
|
||||||
html_root_url = "http://doc.rust-lang.org/nightly/",
|
html_root_url = "http://doc.rust-lang.org/nightly/",
|
||||||
html_playground_url = "http://play.rust-lang.org/")]
|
html_playground_url = "http://play.rust-lang.org/")]
|
||||||
|
|
||||||
#![feature(io)]
|
|
||||||
#![feature(core)]
|
#![feature(core)]
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(staged_api)]
|
#![feature(staged_api)]
|
||||||
|
@ -862,8 +861,8 @@ pub mod writer {
|
||||||
} else if 0x100 <= n && n < NUM_TAGS {
|
} else if 0x100 <= n && n < NUM_TAGS {
|
||||||
w.write_all(&[0xf0 | (n >> 8) as u8, n as u8])
|
w.write_all(&[0xf0 | (n >> 8) as u8, n as u8])
|
||||||
} else {
|
} else {
|
||||||
Err(io::Error::new(io::ErrorKind::Other, "invalid tag",
|
Err(io::Error::new(io::ErrorKind::Other,
|
||||||
Some(n.to_string())))
|
&format!("invalid tag: {}", n)[..]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -876,7 +875,7 @@ pub mod writer {
|
||||||
4 => w.write_all(&[0x10 | ((n >> 24) as u8), (n >> 16) as u8,
|
4 => w.write_all(&[0x10 | ((n >> 24) as u8), (n >> 16) as u8,
|
||||||
(n >> 8) as u8, n as u8]),
|
(n >> 8) as u8, n as u8]),
|
||||||
_ => Err(io::Error::new(io::ErrorKind::Other,
|
_ => Err(io::Error::new(io::ErrorKind::Other,
|
||||||
"isize too big", Some(n.to_string())))
|
&format!("isize too big: {}", n)[..]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -885,8 +884,8 @@ pub mod writer {
|
||||||
if n < 0x4000 { return write_sized_vuint(w, n, 2); }
|
if n < 0x4000 { return write_sized_vuint(w, n, 2); }
|
||||||
if n < 0x200000 { return write_sized_vuint(w, n, 3); }
|
if n < 0x200000 { return write_sized_vuint(w, n, 3); }
|
||||||
if n < 0x10000000 { return write_sized_vuint(w, n, 4); }
|
if n < 0x10000000 { return write_sized_vuint(w, n, 4); }
|
||||||
Err(io::Error::new(io::ErrorKind::Other, "isize too big",
|
Err(io::Error::new(io::ErrorKind::Other,
|
||||||
Some(n.to_string())))
|
&format!("isize too big: {}", n)[..]))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Encoder<'a> {
|
impl<'a> Encoder<'a> {
|
||||||
|
@ -1077,8 +1076,8 @@ pub mod writer {
|
||||||
self.wr_tagged_raw_u32(EsSub32 as usize, v)
|
self.wr_tagged_raw_u32(EsSub32 as usize, v)
|
||||||
} else {
|
} else {
|
||||||
Err(io::Error::new(io::ErrorKind::Other,
|
Err(io::Error::new(io::ErrorKind::Other,
|
||||||
"length or variant id too big",
|
&format!("length or variant id too big: {}",
|
||||||
Some(v.to_string())))
|
v)[..]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,8 @@ register_diagnostics! {
|
||||||
E0019,
|
E0019,
|
||||||
E0020,
|
E0020,
|
||||||
E0022,
|
E0022,
|
||||||
|
E0079, // enum variant: expected signed integer constant
|
||||||
|
E0080, // enum variant: constant evaluation error
|
||||||
E0109,
|
E0109,
|
||||||
E0110,
|
E0110,
|
||||||
E0133,
|
E0133,
|
||||||
|
@ -128,7 +130,8 @@ register_diagnostics! {
|
||||||
E0313, // lifetime of borrowed pointer outlives lifetime of captured variable
|
E0313, // lifetime of borrowed pointer outlives lifetime of captured variable
|
||||||
E0314, // closure outlives stack frame
|
E0314, // closure outlives stack frame
|
||||||
E0315, // cannot invoke closure outside of its lifetime
|
E0315, // cannot invoke closure outside of its lifetime
|
||||||
E0316 // nested quantification of lifetimes
|
E0316, // nested quantification of lifetimes
|
||||||
|
E0370 // discriminant overflow
|
||||||
}
|
}
|
||||||
|
|
||||||
__build_diagnostic_array! { DIAGNOSTICS }
|
__build_diagnostic_array! { DIAGNOSTICS }
|
||||||
|
|
|
@ -37,11 +37,9 @@
|
||||||
#![feature(unsafe_destructor)]
|
#![feature(unsafe_destructor)]
|
||||||
#![feature(staged_api)]
|
#![feature(staged_api)]
|
||||||
#![feature(std_misc)]
|
#![feature(std_misc)]
|
||||||
#![feature(io)]
|
|
||||||
#![feature(path_ext)]
|
#![feature(path_ext)]
|
||||||
#![feature(str_words)]
|
#![feature(str_words)]
|
||||||
#![feature(str_char)]
|
#![feature(str_char)]
|
||||||
#![feature(convert)]
|
|
||||||
#![feature(into_cow)]
|
#![feature(into_cow)]
|
||||||
#![feature(slice_patterns)]
|
#![feature(slice_patterns)]
|
||||||
#![cfg_attr(test, feature(test))]
|
#![cfg_attr(test, feature(test))]
|
||||||
|
|
|
@ -1197,7 +1197,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ty) = tcx.node_types.borrow().get(&id) {
|
if let Some(ty) = tcx.node_types().get(&id) {
|
||||||
rbml_w.tag(c::tag_table_node_type, |rbml_w| {
|
rbml_w.tag(c::tag_table_node_type, |rbml_w| {
|
||||||
rbml_w.id(id);
|
rbml_w.id(id);
|
||||||
rbml_w.emit_ty(ecx, *ty);
|
rbml_w.emit_ty(ecx, *ty);
|
||||||
|
@ -1884,7 +1884,7 @@ fn decode_side_tables(dcx: &DecodeContext,
|
||||||
let ty = val_dsr.read_ty(dcx);
|
let ty = val_dsr.read_ty(dcx);
|
||||||
debug!("inserting ty for node {}: {}",
|
debug!("inserting ty for node {}: {}",
|
||||||
id, ty_to_string(dcx.tcx, ty));
|
id, ty_to_string(dcx.tcx, ty));
|
||||||
dcx.tcx.node_types.borrow_mut().insert(id, ty);
|
dcx.tcx.node_type_insert(id, ty);
|
||||||
}
|
}
|
||||||
c::tag_table_item_subst => {
|
c::tag_table_item_subst => {
|
||||||
let item_substs = ty::ItemSubsts {
|
let item_substs = ty::ItemSubsts {
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
|
|
||||||
pub use self::const_val::*;
|
pub use self::const_val::*;
|
||||||
|
|
||||||
|
use self::ErrKind::*;
|
||||||
|
|
||||||
use metadata::csearch;
|
use metadata::csearch;
|
||||||
use middle::{astencode, def};
|
use middle::{astencode, def};
|
||||||
use middle::pat_util::def_to_path;
|
use middle::pat_util::def_to_path;
|
||||||
|
@ -27,6 +29,7 @@ use syntax::{ast_map, ast_util, codemap};
|
||||||
|
|
||||||
use std::borrow::{Cow, IntoCow};
|
use std::borrow::{Cow, IntoCow};
|
||||||
use std::num::wrapping::OverflowingOps;
|
use std::num::wrapping::OverflowingOps;
|
||||||
|
use std::num::ToPrimitive;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::hash_map::Entry::Vacant;
|
use std::collections::hash_map::Entry::Vacant;
|
||||||
use std::{i8, i16, i32, i64};
|
use std::{i8, i16, i32, i64};
|
||||||
|
@ -234,6 +237,7 @@ pub enum ErrKind {
|
||||||
NotOnStruct,
|
NotOnStruct,
|
||||||
NotOnTuple,
|
NotOnTuple,
|
||||||
|
|
||||||
|
NegateWithOverflow(i64),
|
||||||
AddiWithOverflow(i64, i64),
|
AddiWithOverflow(i64, i64),
|
||||||
SubiWithOverflow(i64, i64),
|
SubiWithOverflow(i64, i64),
|
||||||
MuliWithOverflow(i64, i64),
|
MuliWithOverflow(i64, i64),
|
||||||
|
@ -244,6 +248,8 @@ pub enum ErrKind {
|
||||||
DivideWithOverflow,
|
DivideWithOverflow,
|
||||||
ModuloByZero,
|
ModuloByZero,
|
||||||
ModuloWithOverflow,
|
ModuloWithOverflow,
|
||||||
|
ShiftLeftWithOverflow,
|
||||||
|
ShiftRightWithOverflow,
|
||||||
MissingStructField,
|
MissingStructField,
|
||||||
NonConstPath,
|
NonConstPath,
|
||||||
ExpectedConstTuple,
|
ExpectedConstTuple,
|
||||||
|
@ -257,6 +263,7 @@ pub enum ErrKind {
|
||||||
impl ConstEvalErr {
|
impl ConstEvalErr {
|
||||||
pub fn description(&self) -> Cow<str> {
|
pub fn description(&self) -> Cow<str> {
|
||||||
use self::ErrKind::*;
|
use self::ErrKind::*;
|
||||||
|
|
||||||
match self.kind {
|
match self.kind {
|
||||||
CannotCast => "can't cast this type".into_cow(),
|
CannotCast => "can't cast this type".into_cow(),
|
||||||
CannotCastTo(s) => format!("can't cast this type to {}", s).into_cow(),
|
CannotCastTo(s) => format!("can't cast this type to {}", s).into_cow(),
|
||||||
|
@ -275,6 +282,7 @@ impl ConstEvalErr {
|
||||||
NotOnStruct => "not on struct".into_cow(),
|
NotOnStruct => "not on struct".into_cow(),
|
||||||
NotOnTuple => "not on tuple".into_cow(),
|
NotOnTuple => "not on tuple".into_cow(),
|
||||||
|
|
||||||
|
NegateWithOverflow(..) => "attempted to negate with overflow".into_cow(),
|
||||||
AddiWithOverflow(..) => "attempted to add with overflow".into_cow(),
|
AddiWithOverflow(..) => "attempted to add with overflow".into_cow(),
|
||||||
SubiWithOverflow(..) => "attempted to sub with overflow".into_cow(),
|
SubiWithOverflow(..) => "attempted to sub with overflow".into_cow(),
|
||||||
MuliWithOverflow(..) => "attempted to mul with overflow".into_cow(),
|
MuliWithOverflow(..) => "attempted to mul with overflow".into_cow(),
|
||||||
|
@ -285,6 +293,8 @@ impl ConstEvalErr {
|
||||||
DivideWithOverflow => "attempted to divide with overflow".into_cow(),
|
DivideWithOverflow => "attempted to divide with overflow".into_cow(),
|
||||||
ModuloByZero => "attempted remainder with a divisor of zero".into_cow(),
|
ModuloByZero => "attempted remainder with a divisor of zero".into_cow(),
|
||||||
ModuloWithOverflow => "attempted remainder with overflow".into_cow(),
|
ModuloWithOverflow => "attempted remainder with overflow".into_cow(),
|
||||||
|
ShiftLeftWithOverflow => "attempted left shift with overflow".into_cow(),
|
||||||
|
ShiftRightWithOverflow => "attempted right shift with overflow".into_cow(),
|
||||||
MissingStructField => "nonexistent struct field".into_cow(),
|
MissingStructField => "nonexistent struct field".into_cow(),
|
||||||
NonConstPath => "non-constant path in constant expr".into_cow(),
|
NonConstPath => "non-constant path in constant expr".into_cow(),
|
||||||
ExpectedConstTuple => "expected constant tuple".into_cow(),
|
ExpectedConstTuple => "expected constant tuple".into_cow(),
|
||||||
|
@ -297,57 +307,294 @@ impl ConstEvalErr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! signal {
|
pub type EvalResult = Result<const_val, ConstEvalErr>;
|
||||||
($e:expr, $ctor:ident) => {
|
pub type CastResult = Result<const_val, ErrKind>;
|
||||||
return Err(ConstEvalErr { span: $e.span, kind: ErrKind::$ctor })
|
|
||||||
};
|
|
||||||
|
|
||||||
($e:expr, $ctor:ident($($arg:expr),*)) => {
|
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||||
return Err(ConstEvalErr { span: $e.span, kind: ErrKind::$ctor($($arg),*) })
|
pub enum IntTy { I8, I16, I32, I64 }
|
||||||
|
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||||
|
pub enum UintTy { U8, U16, U32, U64 }
|
||||||
|
|
||||||
|
impl IntTy {
|
||||||
|
pub fn from(tcx: &ty::ctxt, t: ast::IntTy) -> IntTy {
|
||||||
|
let t = if let ast::TyIs = t {
|
||||||
|
tcx.sess.target.int_type
|
||||||
|
} else {
|
||||||
|
t
|
||||||
|
};
|
||||||
|
match t {
|
||||||
|
ast::TyIs => unreachable!(),
|
||||||
|
ast::TyI8 => IntTy::I8,
|
||||||
|
ast::TyI16 => IntTy::I16,
|
||||||
|
ast::TyI32 => IntTy::I32,
|
||||||
|
ast::TyI64 => IntTy::I64,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn checked_add_int(e: &Expr, a: i64, b: i64) -> Result<const_val, ConstEvalErr> {
|
impl UintTy {
|
||||||
let (ret, oflo) = a.overflowing_add(b);
|
pub fn from(tcx: &ty::ctxt, t: ast::UintTy) -> UintTy {
|
||||||
if !oflo { Ok(const_int(ret)) } else { signal!(e, AddiWithOverflow(a, b)) }
|
let t = if let ast::TyUs = t {
|
||||||
}
|
tcx.sess.target.uint_type
|
||||||
fn checked_sub_int(e: &Expr, a: i64, b: i64) -> Result<const_val, ConstEvalErr> {
|
} else {
|
||||||
let (ret, oflo) = a.overflowing_sub(b);
|
t
|
||||||
if !oflo { Ok(const_int(ret)) } else { signal!(e, SubiWithOverflow(a, b)) }
|
};
|
||||||
}
|
match t {
|
||||||
fn checked_mul_int(e: &Expr, a: i64, b: i64) -> Result<const_val, ConstEvalErr> {
|
ast::TyUs => unreachable!(),
|
||||||
let (ret, oflo) = a.overflowing_mul(b);
|
ast::TyU8 => UintTy::U8,
|
||||||
if !oflo { Ok(const_int(ret)) } else { signal!(e, MuliWithOverflow(a, b)) }
|
ast::TyU16 => UintTy::U16,
|
||||||
|
ast::TyU32 => UintTy::U32,
|
||||||
|
ast::TyU64 => UintTy::U64,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn checked_add_uint(e: &Expr, a: u64, b: u64) -> Result<const_val, ConstEvalErr> {
|
macro_rules! signal {
|
||||||
let (ret, oflo) = a.overflowing_add(b);
|
($e:expr, $exn:expr) => {
|
||||||
if !oflo { Ok(const_uint(ret)) } else { signal!(e, AdduWithOverflow(a, b)) }
|
return Err(ConstEvalErr { span: $e.span, kind: $exn })
|
||||||
}
|
}
|
||||||
fn checked_sub_uint(e: &Expr, a: u64, b: u64) -> Result<const_val, ConstEvalErr> {
|
|
||||||
let (ret, oflo) = a.overflowing_sub(b);
|
|
||||||
if !oflo { Ok(const_uint(ret)) } else { signal!(e, SubuWithOverflow(a, b)) }
|
|
||||||
}
|
|
||||||
fn checked_mul_uint(e: &Expr, a: u64, b: u64) -> Result<const_val, ConstEvalErr> {
|
|
||||||
let (ret, oflo) = a.overflowing_mul(b);
|
|
||||||
if !oflo { Ok(const_uint(ret)) } else { signal!(e, MuluWithOverflow(a, b)) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The const_{int,uint}_checked_{neg,add,sub,mul,div,shl,shr} family
|
||||||
|
// of functions catch and signal overflow errors during constant
|
||||||
|
// evaluation.
|
||||||
|
//
|
||||||
|
// They all take the operator's arguments (`a` and `b` if binary), the
|
||||||
|
// overall expression (`e`) and, if available, whole expression's
|
||||||
|
// concrete type (`opt_ety`).
|
||||||
|
//
|
||||||
|
// If the whole expression's concrete type is None, then this is a
|
||||||
|
// constant evaluation happening before type check (e.g. in the check
|
||||||
|
// to confirm that a pattern range's left-side is not greater than its
|
||||||
|
// right-side). We do not do arithmetic modulo the type's bitwidth in
|
||||||
|
// such a case; we just do 64-bit arithmetic and assume that later
|
||||||
|
// passes will do it again with the type information, and thus do the
|
||||||
|
// overflow checks then.
|
||||||
|
|
||||||
|
pub fn const_int_checked_neg<'a>(
|
||||||
|
a: i64, e: &'a Expr, opt_ety: Option<IntTy>) -> EvalResult {
|
||||||
|
|
||||||
|
let (min,max) = match opt_ety {
|
||||||
|
// (-i8::MIN is itself not an i8, etc, but this is an easy way
|
||||||
|
// to allow literals to pass the check. Of course that does
|
||||||
|
// not work for i64::MIN.)
|
||||||
|
Some(IntTy::I8) => (-(i8::MAX as i64), -(i8::MIN as i64)),
|
||||||
|
Some(IntTy::I16) => (-(i16::MAX as i64), -(i16::MIN as i64)),
|
||||||
|
Some(IntTy::I32) => (-(i32::MAX as i64), -(i32::MIN as i64)),
|
||||||
|
None | Some(IntTy::I64) => (-i64::MAX, -(i64::MIN+1)),
|
||||||
|
};
|
||||||
|
|
||||||
|
let oflo = a < min || a > max;
|
||||||
|
if oflo {
|
||||||
|
signal!(e, NegateWithOverflow(a));
|
||||||
|
} else {
|
||||||
|
Ok(const_int(-a))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn const_uint_checked_neg<'a>(
|
||||||
|
a: u64, _e: &'a Expr, _opt_ety: Option<UintTy>) -> EvalResult {
|
||||||
|
// This always succeeds, and by definition, returns `(!a)+1`.
|
||||||
|
Ok(const_uint(-a))
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! overflow_checking_body {
|
||||||
|
($a:ident, $b:ident, $ety:ident, $overflowing_op:ident,
|
||||||
|
lhs: $to_8_lhs:ident $to_16_lhs:ident $to_32_lhs:ident,
|
||||||
|
rhs: $to_8_rhs:ident $to_16_rhs:ident $to_32_rhs:ident $to_64_rhs:ident,
|
||||||
|
$EnumTy:ident $T8: ident $T16: ident $T32: ident $T64: ident,
|
||||||
|
$result_type: ident) => { {
|
||||||
|
let (a,b,opt_ety) = ($a,$b,$ety);
|
||||||
|
match opt_ety {
|
||||||
|
Some($EnumTy::$T8) => match (a.$to_8_lhs(), b.$to_8_rhs()) {
|
||||||
|
(Some(a), Some(b)) => {
|
||||||
|
let (a, oflo) = a.$overflowing_op(b);
|
||||||
|
(a as $result_type, oflo)
|
||||||
|
}
|
||||||
|
(None, _) | (_, None) => (0, true)
|
||||||
|
},
|
||||||
|
Some($EnumTy::$T16) => match (a.$to_16_lhs(), b.$to_16_rhs()) {
|
||||||
|
(Some(a), Some(b)) => {
|
||||||
|
let (a, oflo) = a.$overflowing_op(b);
|
||||||
|
(a as $result_type, oflo)
|
||||||
|
}
|
||||||
|
(None, _) | (_, None) => (0, true)
|
||||||
|
},
|
||||||
|
Some($EnumTy::$T32) => match (a.$to_32_lhs(), b.$to_32_rhs()) {
|
||||||
|
(Some(a), Some(b)) => {
|
||||||
|
let (a, oflo) = a.$overflowing_op(b);
|
||||||
|
(a as $result_type, oflo)
|
||||||
|
}
|
||||||
|
(None, _) | (_, None) => (0, true)
|
||||||
|
},
|
||||||
|
None | Some($EnumTy::$T64) => match b.$to_64_rhs() {
|
||||||
|
Some(b) => a.$overflowing_op(b),
|
||||||
|
None => (0, true),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} }
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! int_arith_body {
|
||||||
|
($a:ident, $b:ident, $ety:ident, $overflowing_op:ident) => {
|
||||||
|
overflow_checking_body!(
|
||||||
|
$a, $b, $ety, $overflowing_op,
|
||||||
|
lhs: to_i8 to_i16 to_i32,
|
||||||
|
rhs: to_i8 to_i16 to_i32 to_i64, IntTy I8 I16 I32 I64, i64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! uint_arith_body {
|
||||||
|
($a:ident, $b:ident, $ety:ident, $overflowing_op:ident) => {
|
||||||
|
overflow_checking_body!(
|
||||||
|
$a, $b, $ety, $overflowing_op,
|
||||||
|
lhs: to_u8 to_u16 to_u32,
|
||||||
|
rhs: to_u8 to_u16 to_u32 to_u64, UintTy U8 U16 U32 U64, u64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! int_shift_body {
|
||||||
|
($a:ident, $b:ident, $ety:ident, $overflowing_op:ident) => {
|
||||||
|
overflow_checking_body!(
|
||||||
|
$a, $b, $ety, $overflowing_op,
|
||||||
|
lhs: to_i8 to_i16 to_i32,
|
||||||
|
rhs: to_u32 to_u32 to_u32 to_u32, IntTy I8 I16 I32 I64, i64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! uint_shift_body {
|
||||||
|
($a:ident, $b:ident, $ety:ident, $overflowing_op:ident) => {
|
||||||
|
overflow_checking_body!(
|
||||||
|
$a, $b, $ety, $overflowing_op,
|
||||||
|
lhs: to_u8 to_u16 to_u32,
|
||||||
|
rhs: to_u32 to_u32 to_u32 to_u32, UintTy U8 U16 U32 U64, u64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! pub_fn_checked_op {
|
||||||
|
{$fn_name:ident ($a:ident : $a_ty:ty, $b:ident : $b_ty:ty,.. $WhichTy:ident) {
|
||||||
|
$ret_oflo_body:ident $overflowing_op:ident
|
||||||
|
$const_ty:ident $signal_exn:expr
|
||||||
|
}} => {
|
||||||
|
pub fn $fn_name<'a>($a: $a_ty,
|
||||||
|
$b: $b_ty,
|
||||||
|
e: &'a Expr,
|
||||||
|
opt_ety: Option<$WhichTy>) -> EvalResult {
|
||||||
|
let (ret, oflo) = $ret_oflo_body!($a, $b, opt_ety, $overflowing_op);
|
||||||
|
if !oflo { Ok($const_ty(ret)) } else { signal!(e, $signal_exn) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub_fn_checked_op!{ const_int_checked_add(a: i64, b: i64,.. IntTy) {
|
||||||
|
int_arith_body overflowing_add const_int AddiWithOverflow(a, b)
|
||||||
|
}}
|
||||||
|
|
||||||
|
pub_fn_checked_op!{ const_int_checked_sub(a: i64, b: i64,.. IntTy) {
|
||||||
|
int_arith_body overflowing_sub const_int SubiWithOverflow(a, b)
|
||||||
|
}}
|
||||||
|
|
||||||
|
pub_fn_checked_op!{ const_int_checked_mul(a: i64, b: i64,.. IntTy) {
|
||||||
|
int_arith_body overflowing_mul const_int MuliWithOverflow(a, b)
|
||||||
|
}}
|
||||||
|
|
||||||
|
pub fn const_int_checked_div<'a>(
|
||||||
|
a: i64, b: i64, e: &'a Expr, opt_ety: Option<IntTy>) -> EvalResult {
|
||||||
|
if b == 0 { signal!(e, DivideByZero); }
|
||||||
|
let (ret, oflo) = int_arith_body!(a, b, opt_ety, overflowing_div);
|
||||||
|
if !oflo { Ok(const_int(ret)) } else { signal!(e, DivideWithOverflow) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn const_int_checked_rem<'a>(
|
||||||
|
a: i64, b: i64, e: &'a Expr, opt_ety: Option<IntTy>) -> EvalResult {
|
||||||
|
if b == 0 { signal!(e, ModuloByZero); }
|
||||||
|
let (ret, oflo) = int_arith_body!(a, b, opt_ety, overflowing_rem);
|
||||||
|
if !oflo { Ok(const_int(ret)) } else { signal!(e, ModuloWithOverflow) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub_fn_checked_op!{ const_int_checked_shl(a: i64, b: i64,.. IntTy) {
|
||||||
|
int_shift_body overflowing_shl const_int ShiftLeftWithOverflow
|
||||||
|
}}
|
||||||
|
|
||||||
|
pub_fn_checked_op!{ const_int_checked_shl_via_uint(a: i64, b: u64,.. IntTy) {
|
||||||
|
int_shift_body overflowing_shl const_int ShiftLeftWithOverflow
|
||||||
|
}}
|
||||||
|
|
||||||
|
pub_fn_checked_op!{ const_int_checked_shr(a: i64, b: i64,.. IntTy) {
|
||||||
|
int_shift_body overflowing_shr const_int ShiftRightWithOverflow
|
||||||
|
}}
|
||||||
|
|
||||||
|
pub_fn_checked_op!{ const_int_checked_shr_via_uint(a: i64, b: u64,.. IntTy) {
|
||||||
|
int_shift_body overflowing_shr const_int ShiftRightWithOverflow
|
||||||
|
}}
|
||||||
|
|
||||||
|
pub_fn_checked_op!{ const_uint_checked_add(a: u64, b: u64,.. UintTy) {
|
||||||
|
uint_arith_body overflowing_add const_uint AdduWithOverflow(a, b)
|
||||||
|
}}
|
||||||
|
|
||||||
|
pub_fn_checked_op!{ const_uint_checked_sub(a: u64, b: u64,.. UintTy) {
|
||||||
|
uint_arith_body overflowing_sub const_uint SubuWithOverflow(a, b)
|
||||||
|
}}
|
||||||
|
|
||||||
|
pub_fn_checked_op!{ const_uint_checked_mul(a: u64, b: u64,.. UintTy) {
|
||||||
|
uint_arith_body overflowing_mul const_uint MuluWithOverflow(a, b)
|
||||||
|
}}
|
||||||
|
|
||||||
|
pub fn const_uint_checked_div<'a>(
|
||||||
|
a: u64, b: u64, e: &'a Expr, opt_ety: Option<UintTy>) -> EvalResult {
|
||||||
|
if b == 0 { signal!(e, DivideByZero); }
|
||||||
|
let (ret, oflo) = uint_arith_body!(a, b, opt_ety, overflowing_div);
|
||||||
|
if !oflo { Ok(const_uint(ret)) } else { signal!(e, DivideWithOverflow) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn const_uint_checked_rem<'a>(
|
||||||
|
a: u64, b: u64, e: &'a Expr, opt_ety: Option<UintTy>) -> EvalResult {
|
||||||
|
if b == 0 { signal!(e, ModuloByZero); }
|
||||||
|
let (ret, oflo) = uint_arith_body!(a, b, opt_ety, overflowing_rem);
|
||||||
|
if !oflo { Ok(const_uint(ret)) } else { signal!(e, ModuloWithOverflow) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub_fn_checked_op!{ const_uint_checked_shl(a: u64, b: u64,.. UintTy) {
|
||||||
|
uint_shift_body overflowing_shl const_uint ShiftLeftWithOverflow
|
||||||
|
}}
|
||||||
|
|
||||||
|
pub_fn_checked_op!{ const_uint_checked_shl_via_int(a: u64, b: i64,.. UintTy) {
|
||||||
|
uint_shift_body overflowing_shl const_uint ShiftLeftWithOverflow
|
||||||
|
}}
|
||||||
|
|
||||||
|
pub_fn_checked_op!{ const_uint_checked_shr(a: u64, b: u64,.. UintTy) {
|
||||||
|
uint_shift_body overflowing_shr const_uint ShiftRightWithOverflow
|
||||||
|
}}
|
||||||
|
|
||||||
|
pub_fn_checked_op!{ const_uint_checked_shr_via_int(a: u64, b: i64,.. UintTy) {
|
||||||
|
uint_shift_body overflowing_shr const_uint ShiftRightWithOverflow
|
||||||
|
}}
|
||||||
|
|
||||||
pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
|
pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||||
e: &Expr,
|
e: &Expr,
|
||||||
ty_hint: Option<Ty<'tcx>>)
|
ty_hint: Option<Ty<'tcx>>) -> EvalResult {
|
||||||
-> Result<const_val, ConstEvalErr> {
|
|
||||||
fn fromb(b: bool) -> const_val { const_int(b as i64) }
|
fn fromb(b: bool) -> const_val { const_int(b as i64) }
|
||||||
|
|
||||||
let ety = ty_hint.or_else(|| ty::expr_ty_opt(tcx, e));
|
let ety = ty_hint.or_else(|| ty::expr_ty_opt(tcx, e));
|
||||||
|
|
||||||
|
// If type of expression itself is int or uint, normalize in these
|
||||||
|
// bindings so that isize/usize is mapped to a type with an
|
||||||
|
// inherently known bitwidth.
|
||||||
|
let expr_int_type = ety.and_then(|ty| {
|
||||||
|
if let ty::ty_int(t) = ty.sty {
|
||||||
|
Some(IntTy::from(tcx, t)) } else { None }
|
||||||
|
});
|
||||||
|
let expr_uint_type = ety.and_then(|ty| {
|
||||||
|
if let ty::ty_uint(t) = ty.sty {
|
||||||
|
Some(UintTy::from(tcx, t)) } else { None }
|
||||||
|
});
|
||||||
|
|
||||||
let result = match e.node {
|
let result = match e.node {
|
||||||
ast::ExprUnary(ast::UnNeg, ref inner) => {
|
ast::ExprUnary(ast::UnNeg, ref inner) => {
|
||||||
match try!(eval_const_expr_partial(tcx, &**inner, ety)) {
|
match try!(eval_const_expr_partial(tcx, &**inner, ety)) {
|
||||||
const_float(f) => const_float(-f),
|
const_float(f) => const_float(-f),
|
||||||
const_int(i) => const_int(-i),
|
const_int(n) => try!(const_int_checked_neg(n, e, expr_int_type)),
|
||||||
const_uint(i) => const_uint(-i),
|
const_uint(n) => try!(const_uint_checked_neg(n, e, expr_uint_type)),
|
||||||
const_str(_) => signal!(e, NegateOnString),
|
const_str(_) => signal!(e, NegateOnString),
|
||||||
const_bool(_) => signal!(e, NegateOnBoolean),
|
const_bool(_) => signal!(e, NegateOnBoolean),
|
||||||
const_binary(_) => signal!(e, NegateOnBinary),
|
const_binary(_) => signal!(e, NegateOnBinary),
|
||||||
|
@ -391,51 +638,17 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(const_int(a), const_int(b)) => {
|
(const_int(a), const_int(b)) => {
|
||||||
let is_a_min_value = || {
|
|
||||||
let int_ty = match ty::expr_ty_opt(tcx, e).map(|ty| &ty.sty) {
|
|
||||||
Some(&ty::ty_int(int_ty)) => int_ty,
|
|
||||||
_ => return false
|
|
||||||
};
|
|
||||||
let int_ty = if let ast::TyIs = int_ty {
|
|
||||||
tcx.sess.target.int_type
|
|
||||||
} else {
|
|
||||||
int_ty
|
|
||||||
};
|
|
||||||
match int_ty {
|
|
||||||
ast::TyI8 => (a as i8) == i8::MIN,
|
|
||||||
ast::TyI16 => (a as i16) == i16::MIN,
|
|
||||||
ast::TyI32 => (a as i32) == i32::MIN,
|
|
||||||
ast::TyI64 => (a as i64) == i64::MIN,
|
|
||||||
ast::TyIs => unreachable!()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
match op.node {
|
match op.node {
|
||||||
ast::BiAdd => try!(checked_add_int(e, a, b)),
|
ast::BiAdd => try!(const_int_checked_add(a,b,e,expr_int_type)),
|
||||||
ast::BiSub => try!(checked_sub_int(e, a, b)),
|
ast::BiSub => try!(const_int_checked_sub(a,b,e,expr_int_type)),
|
||||||
ast::BiMul => try!(checked_mul_int(e, a, b)),
|
ast::BiMul => try!(const_int_checked_mul(a,b,e,expr_int_type)),
|
||||||
ast::BiDiv => {
|
ast::BiDiv => try!(const_int_checked_div(a,b,e,expr_int_type)),
|
||||||
if b == 0 {
|
ast::BiRem => try!(const_int_checked_rem(a,b,e,expr_int_type)),
|
||||||
signal!(e, DivideByZero);
|
|
||||||
} else if b == -1 && is_a_min_value() {
|
|
||||||
signal!(e, DivideWithOverflow);
|
|
||||||
} else {
|
|
||||||
const_int(a / b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ast::BiRem => {
|
|
||||||
if b == 0 {
|
|
||||||
signal!(e, ModuloByZero)
|
|
||||||
} else if b == -1 && is_a_min_value() {
|
|
||||||
signal!(e, ModuloWithOverflow)
|
|
||||||
} else {
|
|
||||||
const_int(a % b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ast::BiAnd | ast::BiBitAnd => const_int(a & b),
|
ast::BiAnd | ast::BiBitAnd => const_int(a & b),
|
||||||
ast::BiOr | ast::BiBitOr => const_int(a | b),
|
ast::BiOr | ast::BiBitOr => const_int(a | b),
|
||||||
ast::BiBitXor => const_int(a ^ b),
|
ast::BiBitXor => const_int(a ^ b),
|
||||||
ast::BiShl => const_int(a << b as usize),
|
ast::BiShl => try!(const_int_checked_shl(a,b,e,expr_int_type)),
|
||||||
ast::BiShr => const_int(a >> b as usize),
|
ast::BiShr => try!(const_int_checked_shr(a,b,e,expr_int_type)),
|
||||||
ast::BiEq => fromb(a == b),
|
ast::BiEq => fromb(a == b),
|
||||||
ast::BiLt => fromb(a < b),
|
ast::BiLt => fromb(a < b),
|
||||||
ast::BiLe => fromb(a <= b),
|
ast::BiLe => fromb(a <= b),
|
||||||
|
@ -446,18 +659,16 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||||
}
|
}
|
||||||
(const_uint(a), const_uint(b)) => {
|
(const_uint(a), const_uint(b)) => {
|
||||||
match op.node {
|
match op.node {
|
||||||
ast::BiAdd => try!(checked_add_uint(e, a, b)),
|
ast::BiAdd => try!(const_uint_checked_add(a,b,e,expr_uint_type)),
|
||||||
ast::BiSub => try!(checked_sub_uint(e, a, b)),
|
ast::BiSub => try!(const_uint_checked_sub(a,b,e,expr_uint_type)),
|
||||||
ast::BiMul => try!(checked_mul_uint(e, a, b)),
|
ast::BiMul => try!(const_uint_checked_mul(a,b,e,expr_uint_type)),
|
||||||
ast::BiDiv if b == 0 => signal!(e, DivideByZero),
|
ast::BiDiv => try!(const_uint_checked_div(a,b,e,expr_uint_type)),
|
||||||
ast::BiDiv => const_uint(a / b),
|
ast::BiRem => try!(const_uint_checked_rem(a,b,e,expr_uint_type)),
|
||||||
ast::BiRem if b == 0 => signal!(e, ModuloByZero),
|
|
||||||
ast::BiRem => const_uint(a % b),
|
|
||||||
ast::BiAnd | ast::BiBitAnd => const_uint(a & b),
|
ast::BiAnd | ast::BiBitAnd => const_uint(a & b),
|
||||||
ast::BiOr | ast::BiBitOr => const_uint(a | b),
|
ast::BiOr | ast::BiBitOr => const_uint(a | b),
|
||||||
ast::BiBitXor => const_uint(a ^ b),
|
ast::BiBitXor => const_uint(a ^ b),
|
||||||
ast::BiShl => const_uint(a << b as usize),
|
ast::BiShl => try!(const_uint_checked_shl(a,b,e,expr_uint_type)),
|
||||||
ast::BiShr => const_uint(a >> b as usize),
|
ast::BiShr => try!(const_uint_checked_shr(a,b,e,expr_uint_type)),
|
||||||
ast::BiEq => fromb(a == b),
|
ast::BiEq => fromb(a == b),
|
||||||
ast::BiLt => fromb(a < b),
|
ast::BiLt => fromb(a < b),
|
||||||
ast::BiLe => fromb(a <= b),
|
ast::BiLe => fromb(a <= b),
|
||||||
|
@ -469,15 +680,15 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||||
// shifts can have any integral type as their rhs
|
// shifts can have any integral type as their rhs
|
||||||
(const_int(a), const_uint(b)) => {
|
(const_int(a), const_uint(b)) => {
|
||||||
match op.node {
|
match op.node {
|
||||||
ast::BiShl => const_int(a << b as usize),
|
ast::BiShl => try!(const_int_checked_shl_via_uint(a,b,e,expr_int_type)),
|
||||||
ast::BiShr => const_int(a >> b as usize),
|
ast::BiShr => try!(const_int_checked_shr_via_uint(a,b,e,expr_int_type)),
|
||||||
_ => signal!(e, InvalidOpForIntUint(op.node)),
|
_ => signal!(e, InvalidOpForIntUint(op.node)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(const_uint(a), const_int(b)) => {
|
(const_uint(a), const_int(b)) => {
|
||||||
match op.node {
|
match op.node {
|
||||||
ast::BiShl => const_uint(a << b as usize),
|
ast::BiShl => try!(const_uint_checked_shl_via_int(a,b,e,expr_uint_type)),
|
||||||
ast::BiShr => const_uint(a >> b as usize),
|
ast::BiShr => try!(const_uint_checked_shr_via_int(a,b,e,expr_uint_type)),
|
||||||
_ => signal!(e, InvalidOpForUintInt(op.node)),
|
_ => signal!(e, InvalidOpForUintInt(op.node)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -506,10 +717,15 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||||
tcx.sess.span_fatal(target_ty.span,
|
tcx.sess.span_fatal(target_ty.span,
|
||||||
"target type not found for const cast")
|
"target type not found for const cast")
|
||||||
});
|
});
|
||||||
|
|
||||||
// Prefer known type to noop, but always have a type hint.
|
// Prefer known type to noop, but always have a type hint.
|
||||||
|
//
|
||||||
|
// FIXME (#23833): the type-hint can cause problems,
|
||||||
|
// e.g. `(i8::MAX + 1_i8) as u32` feeds in `u32` as result
|
||||||
|
// type to the sum, and thus no overflow is signaled.
|
||||||
let base_hint = ty::expr_ty_opt(tcx, &**base).unwrap_or(ety);
|
let base_hint = ty::expr_ty_opt(tcx, &**base).unwrap_or(ety);
|
||||||
let val = try!(eval_const_expr_partial(tcx, &**base, Some(base_hint)));
|
let val = try!(eval_const_expr_partial(tcx, &**base, Some(base_hint)));
|
||||||
match cast_const(val, ety) {
|
match cast_const(tcx, val, ety) {
|
||||||
Ok(val) => val,
|
Ok(val) => val,
|
||||||
Err(kind) => return Err(ConstEvalErr { span: e.span, kind: kind }),
|
Err(kind) => return Err(ConstEvalErr { span: e.span, kind: kind }),
|
||||||
}
|
}
|
||||||
|
@ -607,39 +823,49 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cast_const(val: const_val, ty: Ty) -> Result<const_val, ErrKind> {
|
fn cast_const<'tcx>(tcx: &ty::ctxt<'tcx>, val: const_val, ty: Ty) -> CastResult {
|
||||||
macro_rules! define_casts {
|
macro_rules! convert_val {
|
||||||
($($ty_pat:pat => (
|
($intermediate_ty:ty, $const_type:ident, $target_ty:ty) => {
|
||||||
$intermediate_ty:ty,
|
match val {
|
||||||
$const_type:ident,
|
const_bool(b) => Ok($const_type(b as $intermediate_ty as $target_ty)),
|
||||||
$target_ty:ty
|
const_uint(u) => Ok($const_type(u as $intermediate_ty as $target_ty)),
|
||||||
)),*) => (match ty.sty {
|
const_int(i) => Ok($const_type(i as $intermediate_ty as $target_ty)),
|
||||||
$($ty_pat => {
|
const_float(f) => Ok($const_type(f as $intermediate_ty as $target_ty)),
|
||||||
match val {
|
_ => Err(ErrKind::CannotCastTo(stringify!($const_type))),
|
||||||
const_bool(b) => Ok($const_type(b as $intermediate_ty as $target_ty)),
|
}
|
||||||
const_uint(u) => Ok($const_type(u as $intermediate_ty as $target_ty)),
|
}
|
||||||
const_int(i) => Ok($const_type(i as $intermediate_ty as $target_ty)),
|
|
||||||
const_float(f) => Ok($const_type(f as $intermediate_ty as $target_ty)),
|
|
||||||
_ => Err(ErrKind::CannotCastTo(stringify!($const_type))),
|
|
||||||
}
|
|
||||||
},)*
|
|
||||||
_ => Err(ErrKind::CannotCast),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
define_casts!{
|
// Issue #23890: If isize/usize, then dispatch to appropriate target representation type
|
||||||
ty::ty_int(ast::TyIs) => (isize, const_int, i64),
|
match (&ty.sty, tcx.sess.target.int_type, tcx.sess.target.uint_type) {
|
||||||
ty::ty_int(ast::TyI8) => (i8, const_int, i64),
|
(&ty::ty_int(ast::TyIs), ast::TyI32, _) => return convert_val!(i32, const_int, i64),
|
||||||
ty::ty_int(ast::TyI16) => (i16, const_int, i64),
|
(&ty::ty_int(ast::TyIs), ast::TyI64, _) => return convert_val!(i64, const_int, i64),
|
||||||
ty::ty_int(ast::TyI32) => (i32, const_int, i64),
|
(&ty::ty_int(ast::TyIs), _, _) => panic!("unexpected target.int_type"),
|
||||||
ty::ty_int(ast::TyI64) => (i64, const_int, i64),
|
|
||||||
ty::ty_uint(ast::TyUs) => (usize, const_uint, u64),
|
(&ty::ty_uint(ast::TyUs), _, ast::TyU32) => return convert_val!(u32, const_uint, u64),
|
||||||
ty::ty_uint(ast::TyU8) => (u8, const_uint, u64),
|
(&ty::ty_uint(ast::TyUs), _, ast::TyU64) => return convert_val!(u64, const_uint, u64),
|
||||||
ty::ty_uint(ast::TyU16) => (u16, const_uint, u64),
|
(&ty::ty_uint(ast::TyUs), _, _) => panic!("unexpected target.uint_type"),
|
||||||
ty::ty_uint(ast::TyU32) => (u32, const_uint, u64),
|
|
||||||
ty::ty_uint(ast::TyU64) => (u64, const_uint, u64),
|
_ => {}
|
||||||
ty::ty_float(ast::TyF32) => (f32, const_float, f64),
|
}
|
||||||
ty::ty_float(ast::TyF64) => (f64, const_float, f64)
|
|
||||||
|
match ty.sty {
|
||||||
|
ty::ty_int(ast::TyIs) => unreachable!(),
|
||||||
|
ty::ty_uint(ast::TyUs) => unreachable!(),
|
||||||
|
|
||||||
|
ty::ty_int(ast::TyI8) => convert_val!(i8, const_int, i64),
|
||||||
|
ty::ty_int(ast::TyI16) => convert_val!(i16, const_int, i64),
|
||||||
|
ty::ty_int(ast::TyI32) => convert_val!(i32, const_int, i64),
|
||||||
|
ty::ty_int(ast::TyI64) => convert_val!(i64, const_int, i64),
|
||||||
|
|
||||||
|
ty::ty_uint(ast::TyU8) => convert_val!(u8, const_uint, u64),
|
||||||
|
ty::ty_uint(ast::TyU16) => convert_val!(u16, const_uint, u64),
|
||||||
|
ty::ty_uint(ast::TyU32) => convert_val!(u32, const_uint, u64),
|
||||||
|
ty::ty_uint(ast::TyU64) => convert_val!(u64, const_uint, u64),
|
||||||
|
|
||||||
|
ty::ty_float(ast::TyF32) => convert_val!(f32, const_float, f64),
|
||||||
|
ty::ty_float(ast::TyF64) => convert_val!(f64, const_float, f64),
|
||||||
|
_ => Err(ErrKind::CannotCast),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,11 +68,12 @@ use util::nodemap::FnvHashMap;
|
||||||
|
|
||||||
use arena::TypedArena;
|
use arena::TypedArena;
|
||||||
use std::borrow::{Borrow, Cow};
|
use std::borrow::{Borrow, Cow};
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell, Ref};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::hash::{Hash, SipHasher, Hasher};
|
use std::hash::{Hash, SipHasher, Hasher};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
use std::num::ToPrimitive;
|
||||||
use std::ops;
|
use std::ops;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::vec::IntoIter;
|
use std::vec::IntoIter;
|
||||||
|
@ -83,9 +84,11 @@ use syntax::ast::{CrateNum, DefId, Ident, ItemTrait, LOCAL_CRATE};
|
||||||
use syntax::ast::{MutImmutable, MutMutable, Name, NamedField, NodeId};
|
use syntax::ast::{MutImmutable, MutMutable, Name, NamedField, NodeId};
|
||||||
use syntax::ast::{StmtExpr, StmtSemi, StructField, UnnamedField, Visibility};
|
use syntax::ast::{StmtExpr, StmtSemi, StructField, UnnamedField, Visibility};
|
||||||
use syntax::ast_util::{self, is_local, lit_is_str, local_def};
|
use syntax::ast_util::{self, is_local, lit_is_str, local_def};
|
||||||
use syntax::attr::{self, AttrMetaMethods};
|
use syntax::attr::{self, AttrMetaMethods, SignedInt, UnsignedInt};
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use syntax::parse::token::{self, InternedString, special_idents};
|
use syntax::parse::token::{self, InternedString, special_idents};
|
||||||
|
use syntax::print::pprust;
|
||||||
|
use syntax::ptr::P;
|
||||||
use syntax::{ast, ast_map};
|
use syntax::{ast, ast_map};
|
||||||
|
|
||||||
pub type Disr = u64;
|
pub type Disr = u64;
|
||||||
|
@ -685,7 +688,7 @@ pub struct ctxt<'tcx> {
|
||||||
/// Stores the types for various nodes in the AST. Note that this table
|
/// Stores the types for various nodes in the AST. Note that this table
|
||||||
/// is not guaranteed to be populated until after typeck. See
|
/// is not guaranteed to be populated until after typeck. See
|
||||||
/// typeck::check::fn_ctxt for details.
|
/// typeck::check::fn_ctxt for details.
|
||||||
pub node_types: RefCell<NodeMap<Ty<'tcx>>>,
|
node_types: RefCell<NodeMap<Ty<'tcx>>>,
|
||||||
|
|
||||||
/// Stores the type parameters which were substituted to obtain the type
|
/// Stores the type parameters which were substituted to obtain the type
|
||||||
/// of this node. This only applies to nodes that refer to entities
|
/// of this node. This only applies to nodes that refer to entities
|
||||||
|
@ -850,6 +853,13 @@ pub struct ctxt<'tcx> {
|
||||||
pub const_qualif_map: RefCell<NodeMap<check_const::ConstQualif>>,
|
pub const_qualif_map: RefCell<NodeMap<check_const::ConstQualif>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> ctxt<'tcx> {
|
||||||
|
pub fn node_types(&self) -> Ref<NodeMap<Ty<'tcx>>> { self.node_types.borrow() }
|
||||||
|
pub fn node_type_insert(&self, id: NodeId, ty: Ty<'tcx>) {
|
||||||
|
self.node_types.borrow_mut().insert(id, ty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Flags that we track on types. These flags are propagated upwards
|
// Flags that we track on types. These flags are propagated upwards
|
||||||
// through the type during type construction, so that we can quickly
|
// through the type during type construction, so that we can quickly
|
||||||
// check whether the type has various kinds of types in it without
|
// check whether the type has various kinds of types in it without
|
||||||
|
@ -5489,63 +5499,268 @@ pub fn type_is_empty(cx: &ctxt, ty: Ty) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait IntTypeExt {
|
||||||
|
fn to_ty<'tcx>(&self, cx: &ctxt<'tcx>) -> Ty<'tcx>;
|
||||||
|
fn i64_to_disr(&self, val: i64) -> Option<Disr>;
|
||||||
|
fn u64_to_disr(&self, val: u64) -> Option<Disr>;
|
||||||
|
fn disr_incr(&self, val: Disr) -> Option<Disr>;
|
||||||
|
fn disr_string(&self, val: Disr) -> String;
|
||||||
|
fn disr_wrap_incr(&self, val: Option<Disr>) -> Disr;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntTypeExt for attr::IntType {
|
||||||
|
fn to_ty<'tcx>(&self, cx: &ctxt<'tcx>) -> Ty<'tcx> {
|
||||||
|
match *self {
|
||||||
|
SignedInt(ast::TyI8) => cx.types.i8,
|
||||||
|
SignedInt(ast::TyI16) => cx.types.i16,
|
||||||
|
SignedInt(ast::TyI32) => cx.types.i32,
|
||||||
|
SignedInt(ast::TyI64) => cx.types.i64,
|
||||||
|
SignedInt(ast::TyIs) => cx.types.isize,
|
||||||
|
UnsignedInt(ast::TyU8) => cx.types.u8,
|
||||||
|
UnsignedInt(ast::TyU16) => cx.types.u16,
|
||||||
|
UnsignedInt(ast::TyU32) => cx.types.u32,
|
||||||
|
UnsignedInt(ast::TyU64) => cx.types.u64,
|
||||||
|
UnsignedInt(ast::TyUs) => cx.types.usize,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn i64_to_disr(&self, val: i64) -> Option<Disr> {
|
||||||
|
match *self {
|
||||||
|
SignedInt(ast::TyI8) => val.to_i8() .map(|v| v as Disr),
|
||||||
|
SignedInt(ast::TyI16) => val.to_i16() .map(|v| v as Disr),
|
||||||
|
SignedInt(ast::TyI32) => val.to_i32() .map(|v| v as Disr),
|
||||||
|
SignedInt(ast::TyI64) => val.to_i64() .map(|v| v as Disr),
|
||||||
|
UnsignedInt(ast::TyU8) => val.to_u8() .map(|v| v as Disr),
|
||||||
|
UnsignedInt(ast::TyU16) => val.to_u16() .map(|v| v as Disr),
|
||||||
|
UnsignedInt(ast::TyU32) => val.to_u32() .map(|v| v as Disr),
|
||||||
|
UnsignedInt(ast::TyU64) => val.to_u64() .map(|v| v as Disr),
|
||||||
|
|
||||||
|
UnsignedInt(ast::TyUs) |
|
||||||
|
SignedInt(ast::TyIs) => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn u64_to_disr(&self, val: u64) -> Option<Disr> {
|
||||||
|
match *self {
|
||||||
|
SignedInt(ast::TyI8) => val.to_i8() .map(|v| v as Disr),
|
||||||
|
SignedInt(ast::TyI16) => val.to_i16() .map(|v| v as Disr),
|
||||||
|
SignedInt(ast::TyI32) => val.to_i32() .map(|v| v as Disr),
|
||||||
|
SignedInt(ast::TyI64) => val.to_i64() .map(|v| v as Disr),
|
||||||
|
UnsignedInt(ast::TyU8) => val.to_u8() .map(|v| v as Disr),
|
||||||
|
UnsignedInt(ast::TyU16) => val.to_u16() .map(|v| v as Disr),
|
||||||
|
UnsignedInt(ast::TyU32) => val.to_u32() .map(|v| v as Disr),
|
||||||
|
UnsignedInt(ast::TyU64) => val.to_u64() .map(|v| v as Disr),
|
||||||
|
|
||||||
|
UnsignedInt(ast::TyUs) |
|
||||||
|
SignedInt(ast::TyIs) => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn disr_incr(&self, val: Disr) -> Option<Disr> {
|
||||||
|
macro_rules! add1 {
|
||||||
|
($e:expr) => { $e.and_then(|v|v.checked_add(1)).map(|v| v as Disr) }
|
||||||
|
}
|
||||||
|
match *self {
|
||||||
|
// SignedInt repr means we *want* to reinterpret the bits
|
||||||
|
// treating the highest bit of Disr as a sign-bit, so
|
||||||
|
// cast to i64 before range-checking.
|
||||||
|
SignedInt(ast::TyI8) => add1!((val as i64).to_i8()),
|
||||||
|
SignedInt(ast::TyI16) => add1!((val as i64).to_i16()),
|
||||||
|
SignedInt(ast::TyI32) => add1!((val as i64).to_i32()),
|
||||||
|
SignedInt(ast::TyI64) => add1!(Some(val as i64)),
|
||||||
|
|
||||||
|
UnsignedInt(ast::TyU8) => add1!(val.to_u8()),
|
||||||
|
UnsignedInt(ast::TyU16) => add1!(val.to_u16()),
|
||||||
|
UnsignedInt(ast::TyU32) => add1!(val.to_u32()),
|
||||||
|
UnsignedInt(ast::TyU64) => add1!(Some(val)),
|
||||||
|
|
||||||
|
UnsignedInt(ast::TyUs) |
|
||||||
|
SignedInt(ast::TyIs) => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This returns a String because (1.) it is only used for
|
||||||
|
// rendering an error message and (2.) a string can represent the
|
||||||
|
// full range from `i64::MIN` through `u64::MAX`.
|
||||||
|
fn disr_string(&self, val: Disr) -> String {
|
||||||
|
match *self {
|
||||||
|
SignedInt(ast::TyI8) => format!("{}", val as i8 ),
|
||||||
|
SignedInt(ast::TyI16) => format!("{}", val as i16),
|
||||||
|
SignedInt(ast::TyI32) => format!("{}", val as i32),
|
||||||
|
SignedInt(ast::TyI64) => format!("{}", val as i64),
|
||||||
|
UnsignedInt(ast::TyU8) => format!("{}", val as u8 ),
|
||||||
|
UnsignedInt(ast::TyU16) => format!("{}", val as u16),
|
||||||
|
UnsignedInt(ast::TyU32) => format!("{}", val as u32),
|
||||||
|
UnsignedInt(ast::TyU64) => format!("{}", val as u64),
|
||||||
|
|
||||||
|
UnsignedInt(ast::TyUs) |
|
||||||
|
SignedInt(ast::TyIs) => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn disr_wrap_incr(&self, val: Option<Disr>) -> Disr {
|
||||||
|
macro_rules! add1 {
|
||||||
|
($e:expr) => { ($e).wrapping_add(1) as Disr }
|
||||||
|
}
|
||||||
|
let val = val.unwrap_or(ty::INITIAL_DISCRIMINANT_VALUE);
|
||||||
|
match *self {
|
||||||
|
SignedInt(ast::TyI8) => add1!(val as i8 ),
|
||||||
|
SignedInt(ast::TyI16) => add1!(val as i16),
|
||||||
|
SignedInt(ast::TyI32) => add1!(val as i32),
|
||||||
|
SignedInt(ast::TyI64) => add1!(val as i64),
|
||||||
|
UnsignedInt(ast::TyU8) => add1!(val as u8 ),
|
||||||
|
UnsignedInt(ast::TyU16) => add1!(val as u16),
|
||||||
|
UnsignedInt(ast::TyU32) => add1!(val as u32),
|
||||||
|
UnsignedInt(ast::TyU64) => add1!(val as u64),
|
||||||
|
|
||||||
|
UnsignedInt(ast::TyUs) |
|
||||||
|
SignedInt(ast::TyIs) => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `(normalized_type, ty)`, where `normalized_type` is the
|
||||||
|
/// IntType representation of one of {i64,i32,i16,i8,u64,u32,u16,u8},
|
||||||
|
/// and `ty` is the original type (i.e. may include `isize` or
|
||||||
|
/// `usize`).
|
||||||
|
pub fn enum_repr_type<'tcx>(cx: &ctxt<'tcx>,
|
||||||
|
opt_hint: Option<&attr::ReprAttr>)
|
||||||
|
-> (attr::IntType, Ty<'tcx>)
|
||||||
|
{
|
||||||
|
let repr_type = match opt_hint {
|
||||||
|
// Feed in the given type
|
||||||
|
Some(&attr::ReprInt(_, int_t)) => int_t,
|
||||||
|
// ... but provide sensible default if none provided
|
||||||
|
//
|
||||||
|
// NB. Historically `fn enum_variants` generate i64 here, while
|
||||||
|
// rustc_typeck::check would generate isize.
|
||||||
|
_ => SignedInt(ast::TyIs),
|
||||||
|
};
|
||||||
|
|
||||||
|
let repr_type_ty = repr_type.to_ty(cx);
|
||||||
|
let repr_type = match repr_type {
|
||||||
|
SignedInt(ast::TyIs) =>
|
||||||
|
SignedInt(cx.sess.target.int_type),
|
||||||
|
UnsignedInt(ast::TyUs) =>
|
||||||
|
UnsignedInt(cx.sess.target.uint_type),
|
||||||
|
other => other
|
||||||
|
};
|
||||||
|
|
||||||
|
(repr_type, repr_type_ty)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn report_discrim_overflow(cx: &ctxt,
|
||||||
|
variant_span: Span,
|
||||||
|
variant_name: &str,
|
||||||
|
repr_type: attr::IntType,
|
||||||
|
prev_val: Disr) {
|
||||||
|
let computed_value = repr_type.disr_wrap_incr(Some(prev_val));
|
||||||
|
let computed_value = repr_type.disr_string(computed_value);
|
||||||
|
let prev_val = repr_type.disr_string(prev_val);
|
||||||
|
let repr_type = repr_type.to_ty(cx).user_string(cx);
|
||||||
|
span_err!(cx.sess, variant_span, E0370,
|
||||||
|
"enum discriminant overflowed on value after {}: {}; \
|
||||||
|
set explicitly via {} = {} if that is desired outcome",
|
||||||
|
prev_val, repr_type, variant_name, computed_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This computes the discriminant values for the sequence of Variants
|
||||||
|
// attached to a particular enum, taking into account the #[repr] (if
|
||||||
|
// any) provided via the `opt_hint`.
|
||||||
|
fn compute_enum_variants<'tcx>(cx: &ctxt<'tcx>,
|
||||||
|
vs: &'tcx [P<ast::Variant>],
|
||||||
|
opt_hint: Option<&attr::ReprAttr>)
|
||||||
|
-> Vec<Rc<ty::VariantInfo<'tcx>>> {
|
||||||
|
let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
|
||||||
|
let mut prev_disr_val: Option<ty::Disr> = None;
|
||||||
|
|
||||||
|
let (repr_type, repr_type_ty) = ty::enum_repr_type(cx, opt_hint);
|
||||||
|
|
||||||
|
for v in vs {
|
||||||
|
// If the discriminant value is specified explicitly in the
|
||||||
|
// enum, check whether the initialization expression is valid,
|
||||||
|
// otherwise use the last value plus one.
|
||||||
|
let current_disr_val;
|
||||||
|
|
||||||
|
// This closure marks cases where, when an error occurs during
|
||||||
|
// the computation, attempt to assign a (hopefully) fresh
|
||||||
|
// value to avoid spurious error reports downstream.
|
||||||
|
let attempt_fresh_value = move || -> Disr {
|
||||||
|
repr_type.disr_wrap_incr(prev_disr_val)
|
||||||
|
};
|
||||||
|
|
||||||
|
match v.node.disr_expr {
|
||||||
|
Some(ref e) => {
|
||||||
|
debug!("disr expr, checking {}", pprust::expr_to_string(&**e));
|
||||||
|
|
||||||
|
// check_expr (from check_const pass) doesn't guarantee
|
||||||
|
// that the expression is in a form that eval_const_expr can
|
||||||
|
// handle, so we may still get an internal compiler error
|
||||||
|
//
|
||||||
|
// pnkfelix: The above comment was transcribed from
|
||||||
|
// the version of this code taken from rustc_typeck.
|
||||||
|
// Presumably the implication is that we need to deal
|
||||||
|
// with such ICE's as they arise.
|
||||||
|
//
|
||||||
|
// Since this can be called from `ty::enum_variants`
|
||||||
|
// anyway, best thing is to make `eval_const_expr`
|
||||||
|
// more robust (on case-by-case basis).
|
||||||
|
|
||||||
|
match const_eval::eval_const_expr_partial(cx, &**e, Some(repr_type_ty)) {
|
||||||
|
Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
|
||||||
|
Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
|
||||||
|
Ok(_) => {
|
||||||
|
span_err!(cx.sess, e.span, E0079,
|
||||||
|
"expected signed integer constant");
|
||||||
|
current_disr_val = attempt_fresh_value();
|
||||||
|
}
|
||||||
|
Err(ref err) => {
|
||||||
|
span_err!(cx.sess, err.span, E0080,
|
||||||
|
"constant evaluation error: {}",
|
||||||
|
err.description());
|
||||||
|
current_disr_val = attempt_fresh_value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
current_disr_val = match prev_disr_val {
|
||||||
|
Some(prev_disr_val) => {
|
||||||
|
if let Some(v) = repr_type.disr_incr(prev_disr_val) {
|
||||||
|
v
|
||||||
|
} else {
|
||||||
|
report_discrim_overflow(cx, v.span, v.node.name.as_str(),
|
||||||
|
repr_type, prev_disr_val);
|
||||||
|
attempt_fresh_value()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => ty::INITIAL_DISCRIMINANT_VALUE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let variant_info = Rc::new(VariantInfo::from_ast_variant(cx, &**v, current_disr_val));
|
||||||
|
prev_disr_val = Some(current_disr_val);
|
||||||
|
|
||||||
|
variants.push(variant_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
return variants;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn enum_variants<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
|
pub fn enum_variants<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
|
||||||
-> Rc<Vec<Rc<VariantInfo<'tcx>>>> {
|
-> Rc<Vec<Rc<VariantInfo<'tcx>>>> {
|
||||||
memoized(&cx.enum_var_cache, id, |id: ast::DefId| {
|
memoized(&cx.enum_var_cache, id, |id: ast::DefId| {
|
||||||
if ast::LOCAL_CRATE != id.krate {
|
if ast::LOCAL_CRATE != id.krate {
|
||||||
Rc::new(csearch::get_enum_variants(cx, id))
|
Rc::new(csearch::get_enum_variants(cx, id))
|
||||||
} else {
|
} else {
|
||||||
/*
|
|
||||||
Although both this code and check_enum_variants in typeck/check
|
|
||||||
call eval_const_expr, it should never get called twice for the same
|
|
||||||
expr, since check_enum_variants also updates the enum_var_cache
|
|
||||||
*/
|
|
||||||
match cx.map.get(id.node) {
|
match cx.map.get(id.node) {
|
||||||
ast_map::NodeItem(ref item) => {
|
ast_map::NodeItem(ref item) => {
|
||||||
match item.node {
|
match item.node {
|
||||||
ast::ItemEnum(ref enum_definition, _) => {
|
ast::ItemEnum(ref enum_definition, _) => {
|
||||||
let mut last_discriminant: Option<Disr> = None;
|
Rc::new(compute_enum_variants(
|
||||||
Rc::new(enum_definition.variants.iter().map(|variant| {
|
cx,
|
||||||
|
&enum_definition.variants,
|
||||||
let mut discriminant = INITIAL_DISCRIMINANT_VALUE;
|
lookup_repr_hints(cx, id).get(0)))
|
||||||
if let Some(ref e) = variant.node.disr_expr {
|
|
||||||
// Preserve all values, and prefer signed.
|
|
||||||
let ty = Some(cx.types.i64);
|
|
||||||
match const_eval::eval_const_expr_partial(cx, &**e, ty) {
|
|
||||||
Ok(const_eval::const_int(val)) => {
|
|
||||||
discriminant = val as Disr;
|
|
||||||
}
|
|
||||||
Ok(const_eval::const_uint(val)) => {
|
|
||||||
discriminant = val as Disr;
|
|
||||||
}
|
|
||||||
Ok(_) => {
|
|
||||||
span_err!(cx.sess, e.span, E0304,
|
|
||||||
"expected signed integer constant");
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
span_err!(cx.sess, err.span, E0305,
|
|
||||||
"constant evaluation error: {}",
|
|
||||||
err.description());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if let Some(val) = last_discriminant {
|
|
||||||
if let Some(v) = val.checked_add(1) {
|
|
||||||
discriminant = v
|
|
||||||
} else {
|
|
||||||
cx.sess.span_err(
|
|
||||||
variant.span,
|
|
||||||
&format!("Discriminant overflowed!"));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
discriminant = INITIAL_DISCRIMINANT_VALUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
last_discriminant = Some(discriminant);
|
|
||||||
Rc::new(VariantInfo::from_ast_variant(cx, &**variant,
|
|
||||||
discriminant))
|
|
||||||
}).collect())
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
cx.sess.bug("enum_variants: id not bound to an enum")
|
cx.sess.bug("enum_variants: id not bound to an enum")
|
||||||
|
@ -5831,19 +6046,20 @@ pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> usize {
|
||||||
"expected positive integer for repeat count, found {}",
|
"expected positive integer for repeat count, found {}",
|
||||||
found);
|
found);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(err) => {
|
||||||
|
let err_description = err.description();
|
||||||
let found = match count_expr.node {
|
let found = match count_expr.node {
|
||||||
ast::ExprPath(None, ast::Path {
|
ast::ExprPath(None, ast::Path {
|
||||||
global: false,
|
global: false,
|
||||||
ref segments,
|
ref segments,
|
||||||
..
|
..
|
||||||
}) if segments.len() == 1 =>
|
}) if segments.len() == 1 =>
|
||||||
"variable",
|
format!("{}", "found variable"),
|
||||||
_ =>
|
_ =>
|
||||||
"non-constant expression"
|
format!("but {}", err_description),
|
||||||
};
|
};
|
||||||
span_err!(tcx.sess, count_expr.span, E0307,
|
span_err!(tcx.sess, count_expr.span, E0307,
|
||||||
"expected constant integer for repeat count, found {}",
|
"expected constant integer for repeat count, {}",
|
||||||
found);
|
found);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -228,8 +228,9 @@ pub fn memoized<T, U, S, F>(cache: &RefCell<HashMap<T, U, S>>, arg: T, f: F) ->
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
pub fn path2cstr(p: &Path) -> CString {
|
pub fn path2cstr(p: &Path) -> CString {
|
||||||
use std::os::unix::prelude::*;
|
use std::os::unix::prelude::*;
|
||||||
use std::ffi::AsOsStr;
|
use std::ffi::OsStr;
|
||||||
CString::new(p.as_os_str().as_bytes()).unwrap()
|
let p: &OsStr = p.as_ref();
|
||||||
|
CString::new(p.as_bytes()).unwrap()
|
||||||
}
|
}
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
pub fn path2cstr(p: &Path) -> CString {
|
pub fn path2cstr(p: &Path) -> CString {
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::io;
|
use std::io;
|
||||||
|
use std::env;
|
||||||
#[allow(deprecated)] use std::old_path::{self, GenericPath};
|
#[allow(deprecated)] use std::old_path::{self, GenericPath};
|
||||||
#[allow(deprecated)] use std::old_io;
|
#[allow(deprecated)] use std::old_io;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
@ -20,18 +21,16 @@ pub fn realpath(original: &Path) -> io::Result<PathBuf> {
|
||||||
let old = old_path::Path::new(original.to_str().unwrap());
|
let old = old_path::Path::new(original.to_str().unwrap());
|
||||||
match old_realpath(&old) {
|
match old_realpath(&old) {
|
||||||
Ok(p) => Ok(PathBuf::from(p.as_str().unwrap())),
|
Ok(p) => Ok(PathBuf::from(p.as_str().unwrap())),
|
||||||
Err(e) => Err(io::Error::new(io::ErrorKind::Other,
|
Err(e) => Err(io::Error::new(io::ErrorKind::Other, e))
|
||||||
"realpath error",
|
|
||||||
Some(e.to_string())))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
fn old_realpath(original: &old_path::Path) -> old_io::IoResult<old_path::Path> {
|
fn old_realpath(original: &old_path::Path) -> old_io::IoResult<old_path::Path> {
|
||||||
use std::old_io::fs;
|
use std::old_io::fs;
|
||||||
use std::os;
|
|
||||||
const MAX_LINKS_FOLLOWED: usize = 256;
|
const MAX_LINKS_FOLLOWED: usize = 256;
|
||||||
let original = try!(os::getcwd()).join(original);
|
let original = old_path::Path::new(env::current_dir().unwrap()
|
||||||
|
.to_str().unwrap()).join(original);
|
||||||
|
|
||||||
// Right now lstat on windows doesn't work quite well
|
// Right now lstat on windows doesn't work quite well
|
||||||
if cfg!(windows) {
|
if cfg!(windows) {
|
||||||
|
|
|
@ -36,17 +36,13 @@
|
||||||
#![feature(collections)]
|
#![feature(collections)]
|
||||||
#![feature(core)]
|
#![feature(core)]
|
||||||
#![feature(old_fs)]
|
#![feature(old_fs)]
|
||||||
#![feature(io)]
|
|
||||||
#![feature(old_io)]
|
#![feature(old_io)]
|
||||||
#![feature(old_path)]
|
#![feature(old_path)]
|
||||||
#![feature(os)]
|
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(staged_api)]
|
#![feature(staged_api)]
|
||||||
#![feature(rand)]
|
#![feature(rand)]
|
||||||
#![feature(path_ext)]
|
#![feature(path_ext)]
|
||||||
#![feature(std_misc)]
|
|
||||||
#![feature(step_by)]
|
#![feature(step_by)]
|
||||||
#![feature(convert)]
|
|
||||||
#![cfg_attr(test, feature(test, rand))]
|
#![cfg_attr(test, feature(test, rand))]
|
||||||
|
|
||||||
extern crate syntax;
|
extern crate syntax;
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
#![allow(deprecated)] // to_be32
|
#![allow(deprecated)] // to_be32
|
||||||
|
|
||||||
use std::iter::{range_step, repeat};
|
use std::iter::repeat;
|
||||||
use std::num::Int;
|
use std::num::Int;
|
||||||
use std::slice::bytes::{MutableByteVector, copy_memory};
|
use std::slice::bytes::{MutableByteVector, copy_memory};
|
||||||
use serialize::hex::ToHex;
|
use serialize::hex::ToHex;
|
||||||
|
@ -368,7 +368,7 @@ impl Engine256State {
|
||||||
|
|
||||||
// Putting the message schedule inside the same loop as the round calculations allows for
|
// Putting the message schedule inside the same loop as the round calculations allows for
|
||||||
// the compiler to generate better code.
|
// the compiler to generate better code.
|
||||||
for t in range_step(0, 48, 8) {
|
for t in (0..48).step_by(8) {
|
||||||
schedule_round!(t + 16);
|
schedule_round!(t + 16);
|
||||||
schedule_round!(t + 17);
|
schedule_round!(t + 17);
|
||||||
schedule_round!(t + 18);
|
schedule_round!(t + 18);
|
||||||
|
@ -388,7 +388,7 @@ impl Engine256State {
|
||||||
sha2_round!(b, c, d, e, f, g, h, a, K32, t + 7);
|
sha2_round!(b, c, d, e, f, g, h, a, K32, t + 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
for t in range_step(48, 64, 8) {
|
for t in (48..64).step_by(8) {
|
||||||
sha2_round!(a, b, c, d, e, f, g, h, K32, t);
|
sha2_round!(a, b, c, d, e, f, g, h, K32, t);
|
||||||
sha2_round!(h, a, b, c, d, e, f, g, K32, t + 1);
|
sha2_round!(h, a, b, c, d, e, f, g, K32, t + 1);
|
||||||
sha2_round!(g, h, a, b, c, d, e, f, K32, t + 2);
|
sha2_round!(g, h, a, b, c, d, e, f, K32, t + 2);
|
||||||
|
|
|
@ -47,9 +47,10 @@ pub fn get_sdk_root(sdk_name: &str) -> String {
|
||||||
Ok(String::from_utf8(output.stdout).unwrap())
|
Ok(String::from_utf8(output.stdout).unwrap())
|
||||||
} else {
|
} else {
|
||||||
let error = String::from_utf8(output.stderr);
|
let error = String::from_utf8(output.stderr);
|
||||||
|
let error = format!("process exit with error: {}",
|
||||||
|
error.unwrap());
|
||||||
Err(io::Error::new(io::ErrorKind::Other,
|
Err(io::Error::new(io::ErrorKind::Other,
|
||||||
"process exit with error",
|
&error[..]))
|
||||||
error.ok()))
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::io::{self, Error, ErrorKind};
|
use std::io::{self, Error, ErrorKind};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::{self, PathBuf, AsPath};
|
use std::path::{self, PathBuf, Path};
|
||||||
use std::rand::{thread_rng, Rng};
|
use std::rand::{thread_rng, Rng};
|
||||||
|
|
||||||
/// A wrapper for a path to temporary directory implementing automatic
|
/// A wrapper for a path to temporary directory implementing automatic
|
||||||
|
@ -36,10 +36,10 @@ impl TempDir {
|
||||||
///
|
///
|
||||||
/// If no directory can be created, `Err` is returned.
|
/// If no directory can be created, `Err` is returned.
|
||||||
#[allow(deprecated)] // rand usage
|
#[allow(deprecated)] // rand usage
|
||||||
pub fn new_in<P: AsPath + ?Sized>(tmpdir: &P, prefix: &str)
|
pub fn new_in<P: AsRef<Path>>(tmpdir: P, prefix: &str)
|
||||||
-> io::Result<TempDir> {
|
-> io::Result<TempDir> {
|
||||||
let storage;
|
let storage;
|
||||||
let mut tmpdir = tmpdir.as_path();
|
let mut tmpdir = tmpdir.as_ref();
|
||||||
if !tmpdir.is_absolute() {
|
if !tmpdir.is_absolute() {
|
||||||
let cur_dir = try!(env::current_dir());
|
let cur_dir = try!(env::current_dir());
|
||||||
storage = cur_dir.join(tmpdir);
|
storage = cur_dir.join(tmpdir);
|
||||||
|
@ -67,8 +67,7 @@ impl TempDir {
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(Error::new(ErrorKind::AlreadyExists,
|
Err(Error::new(ErrorKind::AlreadyExists,
|
||||||
"too many temporary directories already exist",
|
"too many temporary directories already exist"))
|
||||||
None))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to make a temporary directory inside of `env::temp_dir()` whose
|
/// Attempts to make a temporary directory inside of `env::temp_dir()` whose
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
|
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
#![feature(collections)]
|
#![feature(collections)]
|
||||||
#![feature(core)]
|
|
||||||
#![feature(libc)]
|
#![feature(libc)]
|
||||||
#![feature(quote)]
|
#![feature(quote)]
|
||||||
#![feature(rustc_diagnostic_macros)]
|
#![feature(rustc_diagnostic_macros)]
|
||||||
|
@ -35,10 +34,8 @@
|
||||||
#![feature(unsafe_destructor)]
|
#![feature(unsafe_destructor)]
|
||||||
#![feature(staged_api)]
|
#![feature(staged_api)]
|
||||||
#![feature(exit_status)]
|
#![feature(exit_status)]
|
||||||
#![feature(io)]
|
|
||||||
#![feature(set_stdio)]
|
#![feature(set_stdio)]
|
||||||
#![feature(unicode)]
|
#![feature(unicode)]
|
||||||
#![feature(convert)]
|
|
||||||
|
|
||||||
extern crate arena;
|
extern crate arena;
|
||||||
extern crate flate;
|
extern crate flate;
|
||||||
|
|
|
@ -699,8 +699,8 @@ fn print_flowgraph<W: Write>(variants: Vec<borrowck_dot::Variant>,
|
||||||
|
|
||||||
fn expand_err_details(r: io::Result<()>) -> io::Result<()> {
|
fn expand_err_details(r: io::Result<()>) -> io::Result<()> {
|
||||||
r.map_err(|ioerr| {
|
r.map_err(|ioerr| {
|
||||||
io::Error::new(io::ErrorKind::Other, "graphviz::render failed",
|
io::Error::new(io::ErrorKind::Other,
|
||||||
Some(ioerr.to_string()))
|
&format!("graphviz::render failed: {}", ioerr)[..])
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -808,12 +808,11 @@ fn walk_ty() {
|
||||||
let tup2_ty = ty::mk_tup(tcx, vec!(tup1_ty, tup1_ty, uint_ty));
|
let tup2_ty = ty::mk_tup(tcx, vec!(tup1_ty, tup1_ty, uint_ty));
|
||||||
let uniq_ty = ty::mk_uniq(tcx, tup2_ty);
|
let uniq_ty = ty::mk_uniq(tcx, tup2_ty);
|
||||||
let walked: Vec<_> = uniq_ty.walk().collect();
|
let walked: Vec<_> = uniq_ty.walk().collect();
|
||||||
assert_eq!([uniq_ty,
|
assert_eq!(walked, [uniq_ty,
|
||||||
tup2_ty,
|
tup2_ty,
|
||||||
tup1_ty, int_ty, uint_ty, int_ty, uint_ty,
|
tup1_ty, int_ty, uint_ty, int_ty, uint_ty,
|
||||||
tup1_ty, int_ty, uint_ty, int_ty, uint_ty,
|
tup1_ty, int_ty, uint_ty, int_ty, uint_ty,
|
||||||
uint_ty],
|
uint_ty]);
|
||||||
walked);
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,8 +42,9 @@ impl ArchiveRO {
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
fn path2cstr(p: &Path) -> CString {
|
fn path2cstr(p: &Path) -> CString {
|
||||||
use std::os::unix::prelude::*;
|
use std::os::unix::prelude::*;
|
||||||
use std::ffi::AsOsStr;
|
use std::ffi::OsStr;
|
||||||
CString::new(p.as_os_str().as_bytes()).unwrap()
|
let p: &OsStr = p.as_ref();
|
||||||
|
CString::new(p.as_bytes()).unwrap()
|
||||||
}
|
}
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn path2cstr(p: &Path) -> CString {
|
fn path2cstr(p: &Path) -> CString {
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
#![feature(libc)]
|
#![feature(libc)]
|
||||||
#![feature(link_args)]
|
#![feature(link_args)]
|
||||||
#![feature(staged_api)]
|
#![feature(staged_api)]
|
||||||
#![cfg_attr(unix, feature(std_misc))]
|
|
||||||
|
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
#[macro_use] #[no_link] extern crate rustc_bitflags;
|
#[macro_use] #[no_link] extern crate rustc_bitflags;
|
||||||
|
@ -1976,6 +1975,7 @@ extern {
|
||||||
pub fn LLVMIsAArgument(value_ref: ValueRef) -> ValueRef;
|
pub fn LLVMIsAArgument(value_ref: ValueRef) -> ValueRef;
|
||||||
|
|
||||||
pub fn LLVMIsAAllocaInst(value_ref: ValueRef) -> ValueRef;
|
pub fn LLVMIsAAllocaInst(value_ref: ValueRef) -> ValueRef;
|
||||||
|
pub fn LLVMIsAConstantInt(value_ref: ValueRef) -> ValueRef;
|
||||||
|
|
||||||
pub fn LLVMInitializeX86TargetInfo();
|
pub fn LLVMInitializeX86TargetInfo();
|
||||||
pub fn LLVMInitializeX86Target();
|
pub fn LLVMInitializeX86Target();
|
||||||
|
|
|
@ -39,7 +39,6 @@
|
||||||
#![feature(unicode)]
|
#![feature(unicode)]
|
||||||
#![feature(path_ext)]
|
#![feature(path_ext)]
|
||||||
#![feature(fs)]
|
#![feature(fs)]
|
||||||
#![feature(convert)]
|
|
||||||
#![feature(path_relative_from)]
|
#![feature(path_relative_from)]
|
||||||
|
|
||||||
#![allow(trivial_casts)]
|
#![allow(trivial_casts)]
|
||||||
|
|
|
@ -272,7 +272,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
|
||||||
let typ =
|
let typ =
|
||||||
ppaux::ty_to_string(
|
ppaux::ty_to_string(
|
||||||
&self.analysis.ty_cx,
|
&self.analysis.ty_cx,
|
||||||
*self.analysis.ty_cx.node_types.borrow().get(&id).unwrap());
|
*self.analysis.ty_cx.node_types().get(&id).unwrap());
|
||||||
// get the span only for the name of the variable (I hope the path is only ever a
|
// get the span only for the name of the variable (I hope the path is only ever a
|
||||||
// variable name, but who knows?)
|
// variable name, but who knows?)
|
||||||
self.fmt.formal_str(p.span,
|
self.fmt.formal_str(p.span,
|
||||||
|
@ -436,7 +436,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
|
||||||
let typ =
|
let typ =
|
||||||
ppaux::ty_to_string(
|
ppaux::ty_to_string(
|
||||||
&self.analysis.ty_cx,
|
&self.analysis.ty_cx,
|
||||||
*self.analysis.ty_cx.node_types.borrow().get(&field.node.id).unwrap());
|
*self.analysis.ty_cx.node_types().get(&field.node.id).unwrap());
|
||||||
match self.span.sub_span_before_token(field.span, token::Colon) {
|
match self.span.sub_span_before_token(field.span, token::Colon) {
|
||||||
Some(sub_span) => self.fmt.field_str(field.span,
|
Some(sub_span) => self.fmt.field_str(field.span,
|
||||||
Some(sub_span),
|
Some(sub_span),
|
||||||
|
@ -1471,7 +1471,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
|
||||||
|
|
||||||
for &(id, ref p, ref immut, _) in &self.collected_paths {
|
for &(id, ref p, ref immut, _) in &self.collected_paths {
|
||||||
let value = if *immut { value.to_string() } else { "<mutable>".to_string() };
|
let value = if *immut { value.to_string() } else { "<mutable>".to_string() };
|
||||||
let types = self.analysis.ty_cx.node_types.borrow();
|
let types = self.analysis.ty_cx.node_types();
|
||||||
let typ = ppaux::ty_to_string(&self.analysis.ty_cx, *types.get(&id).unwrap());
|
let typ = ppaux::ty_to_string(&self.analysis.ty_cx, *types.get(&id).unwrap());
|
||||||
// Get the span only for the name of the variable (I hope the path
|
// Get the span only for the name of the variable (I hope the path
|
||||||
// is only ever a variable name, but who knows?).
|
// is only ever a variable name, but who knows?).
|
||||||
|
|
|
@ -41,7 +41,7 @@ use middle::cfg;
|
||||||
use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
|
use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
|
||||||
use middle::weak_lang_items;
|
use middle::weak_lang_items;
|
||||||
use middle::subst::{Subst, Substs};
|
use middle::subst::{Subst, Substs};
|
||||||
use middle::ty::{self, Ty, ClosureTyper};
|
use middle::ty::{self, Ty, ClosureTyper, type_is_simd, simd_size};
|
||||||
use session::config::{self, NoDebugInfo};
|
use session::config::{self, NoDebugInfo};
|
||||||
use session::Session;
|
use session::Session;
|
||||||
use trans::_match;
|
use trans::_match;
|
||||||
|
@ -52,7 +52,7 @@ use trans::callee;
|
||||||
use trans::cleanup::CleanupMethods;
|
use trans::cleanup::CleanupMethods;
|
||||||
use trans::cleanup;
|
use trans::cleanup;
|
||||||
use trans::closure;
|
use trans::closure;
|
||||||
use trans::common::{Block, C_bool, C_bytes_in_context, C_i32, C_integral};
|
use trans::common::{Block, C_bool, C_bytes_in_context, C_i32, C_int, C_integral};
|
||||||
use trans::common::{C_null, C_struct_in_context, C_u64, C_u8, C_undef};
|
use trans::common::{C_null, C_struct_in_context, C_u64, C_u8, C_undef};
|
||||||
use trans::common::{CrateContext, ExternMap, FunctionContext};
|
use trans::common::{CrateContext, ExternMap, FunctionContext};
|
||||||
use trans::common::{Result, NodeIdAndSpan};
|
use trans::common::{Result, NodeIdAndSpan};
|
||||||
|
@ -824,6 +824,15 @@ pub fn fail_if_zero_or_overflows<'blk, 'tcx>(
|
||||||
let zero = C_integral(Type::uint_from_ty(cx.ccx(), t), 0, false);
|
let zero = C_integral(Type::uint_from_ty(cx.ccx(), t), 0, false);
|
||||||
(ICmp(cx, llvm::IntEQ, rhs, zero, debug_loc), false)
|
(ICmp(cx, llvm::IntEQ, rhs, zero, debug_loc), false)
|
||||||
}
|
}
|
||||||
|
ty::ty_struct(_, _) if type_is_simd(cx.tcx(), rhs_t) => {
|
||||||
|
let mut res = C_bool(cx.ccx(), false);
|
||||||
|
for i in 0 .. simd_size(cx.tcx(), rhs_t) {
|
||||||
|
res = Or(cx, res,
|
||||||
|
IsNull(cx,
|
||||||
|
ExtractElement(cx, rhs, C_int(cx.ccx(), i as i64))), debug_loc);
|
||||||
|
}
|
||||||
|
(res, false)
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
cx.sess().bug(&format!("fail-if-zero on unexpected type: {}",
|
cx.sess().bug(&format!("fail-if-zero on unexpected type: {}",
|
||||||
ty_to_string(cx.tcx(), rhs_t)));
|
ty_to_string(cx.tcx(), rhs_t)));
|
||||||
|
|
|
@ -963,6 +963,32 @@ pub fn const_to_uint(v: ValueRef) -> u64 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_const_integral(v: ValueRef) -> bool {
|
||||||
|
unsafe {
|
||||||
|
!llvm::LLVMIsAConstantInt(v).is_null()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn const_to_opt_int(v: ValueRef) -> Option<i64> {
|
||||||
|
unsafe {
|
||||||
|
if is_const_integral(v) {
|
||||||
|
Some(llvm::LLVMConstIntGetSExtValue(v))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn const_to_opt_uint(v: ValueRef) -> Option<u64> {
|
||||||
|
unsafe {
|
||||||
|
if is_const_integral(v) {
|
||||||
|
Some(llvm::LLVMConstIntGetZExtValue(v))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_undef(val: ValueRef) -> bool {
|
pub fn is_undef(val: ValueRef) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMIsUndef(val) != False
|
llvm::LLVMIsUndef(val) != False
|
||||||
|
|
|
@ -14,6 +14,14 @@ use llvm;
|
||||||
use llvm::{ConstFCmp, ConstICmp, SetLinkage, SetUnnamedAddr};
|
use llvm::{ConstFCmp, ConstICmp, SetLinkage, SetUnnamedAddr};
|
||||||
use llvm::{InternalLinkage, ValueRef, Bool, True};
|
use llvm::{InternalLinkage, ValueRef, Bool, True};
|
||||||
use middle::{check_const, const_eval, def};
|
use middle::{check_const, const_eval, def};
|
||||||
|
use middle::const_eval::{const_int_checked_neg, const_uint_checked_neg};
|
||||||
|
use middle::const_eval::{const_int_checked_add, const_uint_checked_add};
|
||||||
|
use middle::const_eval::{const_int_checked_sub, const_uint_checked_sub};
|
||||||
|
use middle::const_eval::{const_int_checked_mul, const_uint_checked_mul};
|
||||||
|
use middle::const_eval::{const_int_checked_div, const_uint_checked_div};
|
||||||
|
use middle::const_eval::{const_int_checked_rem, const_uint_checked_rem};
|
||||||
|
use middle::const_eval::{const_int_checked_shl, const_uint_checked_shl};
|
||||||
|
use middle::const_eval::{const_int_checked_shr, const_uint_checked_shr};
|
||||||
use trans::{adt, closure, debuginfo, expr, inline, machine};
|
use trans::{adt, closure, debuginfo, expr, inline, machine};
|
||||||
use trans::base::{self, push_ctxt};
|
use trans::base::{self, push_ctxt};
|
||||||
use trans::common::*;
|
use trans::common::*;
|
||||||
|
@ -336,6 +344,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||||
let csize = machine::llsize_of_alloc(cx, val_ty(llconst));
|
let csize = machine::llsize_of_alloc(cx, val_ty(llconst));
|
||||||
let tsize = machine::llsize_of_alloc(cx, llty);
|
let tsize = machine::llsize_of_alloc(cx, llty);
|
||||||
if csize != tsize {
|
if csize != tsize {
|
||||||
|
cx.sess().abort_if_errors();
|
||||||
unsafe {
|
unsafe {
|
||||||
// FIXME these values could use some context
|
// FIXME these values could use some context
|
||||||
llvm::LLVMDumpValue(llconst);
|
llvm::LLVMDumpValue(llconst);
|
||||||
|
@ -348,6 +357,100 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||||
(llconst, ety_adjusted)
|
(llconst, ety_adjusted)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_unary_expr_validity(cx: &CrateContext, e: &ast::Expr, t: Ty,
|
||||||
|
te: ValueRef) {
|
||||||
|
// The only kind of unary expression that we check for validity
|
||||||
|
// here is `-expr`, to check if it "overflows" (e.g. `-i32::MIN`).
|
||||||
|
if let ast::ExprUnary(ast::UnNeg, ref inner_e) = e.node {
|
||||||
|
|
||||||
|
// An unfortunate special case: we parse e.g. -128 as a
|
||||||
|
// negation of the literal 128, which means if we're expecting
|
||||||
|
// a i8 (or if it was already suffixed, e.g. `-128_i8`), then
|
||||||
|
// 128 will have already overflowed to -128, and so then the
|
||||||
|
// constant evaluator thinks we're trying to negate -128.
|
||||||
|
//
|
||||||
|
// Catch this up front by looking for ExprLit directly,
|
||||||
|
// and just accepting it.
|
||||||
|
if let ast::ExprLit(_) = inner_e.node { return; }
|
||||||
|
|
||||||
|
let result = match t.sty {
|
||||||
|
ty::ty_int(int_type) => {
|
||||||
|
let input = match const_to_opt_int(te) {
|
||||||
|
Some(v) => v,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
const_int_checked_neg(
|
||||||
|
input, e, Some(const_eval::IntTy::from(cx.tcx(), int_type)))
|
||||||
|
}
|
||||||
|
ty::ty_uint(uint_type) => {
|
||||||
|
let input = match const_to_opt_uint(te) {
|
||||||
|
Some(v) => v,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
const_uint_checked_neg(
|
||||||
|
input, e, Some(const_eval::UintTy::from(cx.tcx(), uint_type)))
|
||||||
|
}
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
// We do not actually care about a successful result.
|
||||||
|
if let Err(err) = result {
|
||||||
|
cx.tcx().sess.span_err(e.span, &err.description());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_binary_expr_validity(cx: &CrateContext, e: &ast::Expr, t: Ty,
|
||||||
|
te1: ValueRef, te2: ValueRef) {
|
||||||
|
let b = if let ast::ExprBinary(b, _, _) = e.node { b } else { return };
|
||||||
|
|
||||||
|
let result = match t.sty {
|
||||||
|
ty::ty_int(int_type) => {
|
||||||
|
let (lhs, rhs) = match (const_to_opt_int(te1),
|
||||||
|
const_to_opt_int(te2)) {
|
||||||
|
(Some(v1), Some(v2)) => (v1, v2),
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
let opt_ety = Some(const_eval::IntTy::from(cx.tcx(), int_type));
|
||||||
|
match b.node {
|
||||||
|
ast::BiAdd => const_int_checked_add(lhs, rhs, e, opt_ety),
|
||||||
|
ast::BiSub => const_int_checked_sub(lhs, rhs, e, opt_ety),
|
||||||
|
ast::BiMul => const_int_checked_mul(lhs, rhs, e, opt_ety),
|
||||||
|
ast::BiDiv => const_int_checked_div(lhs, rhs, e, opt_ety),
|
||||||
|
ast::BiRem => const_int_checked_rem(lhs, rhs, e, opt_ety),
|
||||||
|
ast::BiShl => const_int_checked_shl(lhs, rhs, e, opt_ety),
|
||||||
|
ast::BiShr => const_int_checked_shr(lhs, rhs, e, opt_ety),
|
||||||
|
_ => return,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ty::ty_uint(uint_type) => {
|
||||||
|
let (lhs, rhs) = match (const_to_opt_uint(te1),
|
||||||
|
const_to_opt_uint(te2)) {
|
||||||
|
(Some(v1), Some(v2)) => (v1, v2),
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
let opt_ety = Some(const_eval::UintTy::from(cx.tcx(), uint_type));
|
||||||
|
match b.node {
|
||||||
|
ast::BiAdd => const_uint_checked_add(lhs, rhs, e, opt_ety),
|
||||||
|
ast::BiSub => const_uint_checked_sub(lhs, rhs, e, opt_ety),
|
||||||
|
ast::BiMul => const_uint_checked_mul(lhs, rhs, e, opt_ety),
|
||||||
|
ast::BiDiv => const_uint_checked_div(lhs, rhs, e, opt_ety),
|
||||||
|
ast::BiRem => const_uint_checked_rem(lhs, rhs, e, opt_ety),
|
||||||
|
ast::BiShl => const_uint_checked_shl(lhs, rhs, e, opt_ety),
|
||||||
|
ast::BiShr => const_uint_checked_shr(lhs, rhs, e, opt_ety),
|
||||||
|
_ => return,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
// We do not actually care about a successful result.
|
||||||
|
if let Err(err) = result {
|
||||||
|
cx.tcx().sess.span_err(e.span, &err.description());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||||
e: &ast::Expr,
|
e: &ast::Expr,
|
||||||
ety: Ty<'tcx>,
|
ety: Ty<'tcx>,
|
||||||
|
@ -386,7 +489,8 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||||
let signed = ty::type_is_signed(intype);
|
let signed = ty::type_is_signed(intype);
|
||||||
|
|
||||||
let (te2, _) = const_expr(cx, &**e2, param_substs);
|
let (te2, _) = const_expr(cx, &**e2, param_substs);
|
||||||
let te2 = base::cast_shift_const_rhs(b.node, te1, te2);
|
|
||||||
|
check_binary_expr_validity(cx, e, ty, te1, te2);
|
||||||
|
|
||||||
match b.node {
|
match b.node {
|
||||||
ast::BiAdd => {
|
ast::BiAdd => {
|
||||||
|
@ -416,8 +520,12 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||||
ast::BiBitXor => llvm::LLVMConstXor(te1, te2),
|
ast::BiBitXor => llvm::LLVMConstXor(te1, te2),
|
||||||
ast::BiBitAnd => llvm::LLVMConstAnd(te1, te2),
|
ast::BiBitAnd => llvm::LLVMConstAnd(te1, te2),
|
||||||
ast::BiBitOr => llvm::LLVMConstOr(te1, te2),
|
ast::BiBitOr => llvm::LLVMConstOr(te1, te2),
|
||||||
ast::BiShl => llvm::LLVMConstShl(te1, te2),
|
ast::BiShl => {
|
||||||
|
let te2 = base::cast_shift_const_rhs(b.node, te1, te2);
|
||||||
|
llvm::LLVMConstShl(te1, te2)
|
||||||
|
}
|
||||||
ast::BiShr => {
|
ast::BiShr => {
|
||||||
|
let te2 = base::cast_shift_const_rhs(b.node, te1, te2);
|
||||||
if signed { llvm::LLVMConstAShr(te1, te2) }
|
if signed { llvm::LLVMConstAShr(te1, te2) }
|
||||||
else { llvm::LLVMConstLShr(te1, te2) }
|
else { llvm::LLVMConstLShr(te1, te2) }
|
||||||
}
|
}
|
||||||
|
@ -439,8 +547,11 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ast::ExprUnary(u, ref e) => {
|
ast::ExprUnary(u, ref inner_e) => {
|
||||||
let (te, ty) = const_expr(cx, &**e, param_substs);
|
let (te, ty) = const_expr(cx, &**inner_e, param_substs);
|
||||||
|
|
||||||
|
check_unary_expr_validity(cx, e, ty, te);
|
||||||
|
|
||||||
let is_float = ty::type_is_fp(ty);
|
let is_float = ty::type_is_fp(ty);
|
||||||
match u {
|
match u {
|
||||||
ast::UnUniq | ast::UnDeref => {
|
ast::UnUniq | ast::UnDeref => {
|
||||||
|
@ -661,11 +772,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||||
ast::ExprRepeat(ref elem, ref count) => {
|
ast::ExprRepeat(ref elem, ref count) => {
|
||||||
let unit_ty = ty::sequence_element_type(cx.tcx(), ety);
|
let unit_ty = ty::sequence_element_type(cx.tcx(), ety);
|
||||||
let llunitty = type_of::type_of(cx, unit_ty);
|
let llunitty = type_of::type_of(cx, unit_ty);
|
||||||
let n = match const_eval::eval_const_expr_partial(cx.tcx(), &**count, None) {
|
let n = ty::eval_repeat_count(cx.tcx(), count);
|
||||||
Ok(const_eval::const_int(i)) => i as usize,
|
|
||||||
Ok(const_eval::const_uint(i)) => i as usize,
|
|
||||||
_ => cx.sess().span_bug(count.span, "count must be integral const expression.")
|
|
||||||
};
|
|
||||||
let unit_val = const_expr(cx, &**elem, param_substs).0;
|
let unit_val = const_expr(cx, &**elem, param_substs).0;
|
||||||
let vs: Vec<_> = repeat(unit_val).take(n).collect();
|
let vs: Vec<_> = repeat(unit_val).take(n).collect();
|
||||||
if val_ty(unit_val) != llunitty {
|
if val_ty(unit_val) != llunitty {
|
||||||
|
|
|
@ -3207,7 +3207,7 @@ fn fn_should_be_ignored(fcx: &FunctionContext) -> bool {
|
||||||
fn assert_type_for_node_id(cx: &CrateContext,
|
fn assert_type_for_node_id(cx: &CrateContext,
|
||||||
node_id: ast::NodeId,
|
node_id: ast::NodeId,
|
||||||
error_reporting_span: Span) {
|
error_reporting_span: Span) {
|
||||||
if !cx.tcx().node_types.borrow().contains_key(&node_id) {
|
if !cx.tcx().node_types().contains_key(&node_id) {
|
||||||
cx.sess().span_bug(error_reporting_span,
|
cx.sess().span_bug(error_reporting_span,
|
||||||
"debuginfo: Could not find type for node id!");
|
"debuginfo: Could not find type for node id!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,7 @@ use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv, PathParamMode};
|
||||||
use check::_match::pat_ctxt;
|
use check::_match::pat_ctxt;
|
||||||
use fmt_macros::{Parser, Piece, Position};
|
use fmt_macros::{Parser, Piece, Position};
|
||||||
use middle::astconv_util::{check_path_args, NO_TPS, NO_REGIONS};
|
use middle::astconv_util::{check_path_args, NO_TPS, NO_REGIONS};
|
||||||
use middle::{const_eval, def};
|
use middle::def;
|
||||||
use middle::infer;
|
use middle::infer;
|
||||||
use middle::mem_categorization as mc;
|
use middle::mem_categorization as mc;
|
||||||
use middle::mem_categorization::McResult;
|
use middle::mem_categorization::McResult;
|
||||||
|
@ -94,7 +94,7 @@ use middle::privacy::{AllPublic, LastMod};
|
||||||
use middle::region::{self, CodeExtent};
|
use middle::region::{self, CodeExtent};
|
||||||
use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace};
|
use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace};
|
||||||
use middle::traits;
|
use middle::traits;
|
||||||
use middle::ty::{FnSig, GenericPredicates, VariantInfo, TypeScheme};
|
use middle::ty::{FnSig, GenericPredicates, TypeScheme};
|
||||||
use middle::ty::{Disr, ParamTy, ParameterEnvironment};
|
use middle::ty::{Disr, ParamTy, ParameterEnvironment};
|
||||||
use middle::ty::{self, HasProjectionTypes, RegionEscape, ToPolyTraitRef, Ty};
|
use middle::ty::{self, HasProjectionTypes, RegionEscape, ToPolyTraitRef, Ty};
|
||||||
use middle::ty::liberate_late_bound_regions;
|
use middle::ty::liberate_late_bound_regions;
|
||||||
|
@ -4283,68 +4283,30 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
|
||||||
fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||||
vs: &'tcx [P<ast::Variant>],
|
vs: &'tcx [P<ast::Variant>],
|
||||||
id: ast::NodeId,
|
id: ast::NodeId,
|
||||||
hint: attr::ReprAttr)
|
hint: attr::ReprAttr) {
|
||||||
-> Vec<Rc<ty::VariantInfo<'tcx>>> {
|
|
||||||
#![allow(trivial_numeric_casts)]
|
#![allow(trivial_numeric_casts)]
|
||||||
|
|
||||||
let rty = ty::node_id_to_type(ccx.tcx, id);
|
let rty = ty::node_id_to_type(ccx.tcx, id);
|
||||||
let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
|
|
||||||
let mut disr_vals: Vec<ty::Disr> = Vec::new();
|
let mut disr_vals: Vec<ty::Disr> = Vec::new();
|
||||||
let mut prev_disr_val: Option<ty::Disr> = None;
|
|
||||||
|
|
||||||
|
let inh = static_inherited_fields(ccx);
|
||||||
|
let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), id);
|
||||||
|
|
||||||
|
let (_, repr_type_ty) = ty::enum_repr_type(ccx.tcx, Some(&hint));
|
||||||
for v in vs {
|
for v in vs {
|
||||||
|
if let Some(ref e) = v.node.disr_expr {
|
||||||
|
check_const_with_ty(&fcx, e.span, e, repr_type_ty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If the discriminant value is specified explicitly in the enum check whether the
|
let def_id = local_def(id);
|
||||||
// initialization expression is valid, otherwise use the last value plus one.
|
|
||||||
let mut current_disr_val = match prev_disr_val {
|
|
||||||
Some(prev_disr_val) => {
|
|
||||||
if let Some(v) = prev_disr_val.checked_add(1) {
|
|
||||||
v
|
|
||||||
} else {
|
|
||||||
ty::INITIAL_DISCRIMINANT_VALUE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => ty::INITIAL_DISCRIMINANT_VALUE
|
|
||||||
};
|
|
||||||
|
|
||||||
match v.node.disr_expr {
|
// ty::enum_variants guards against discriminant overflows, so
|
||||||
Some(ref e) => {
|
// we need not check for that.
|
||||||
debug!("disr expr, checking {}", pprust::expr_to_string(&**e));
|
let variants = ty::enum_variants(ccx.tcx, def_id);
|
||||||
|
|
||||||
let inh = static_inherited_fields(ccx);
|
for (v, variant) in vs.iter().zip(variants.iter()) {
|
||||||
let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
|
let current_disr_val = variant.disr_val;
|
||||||
let declty = match hint {
|
|
||||||
attr::ReprAny | attr::ReprPacked |
|
|
||||||
attr::ReprExtern => fcx.tcx().types.isize,
|
|
||||||
|
|
||||||
attr::ReprInt(_, attr::SignedInt(ity)) => {
|
|
||||||
ty::mk_mach_int(fcx.tcx(), ity)
|
|
||||||
}
|
|
||||||
attr::ReprInt(_, attr::UnsignedInt(ity)) => {
|
|
||||||
ty::mk_mach_uint(fcx.tcx(), ity)
|
|
||||||
},
|
|
||||||
};
|
|
||||||
check_const_with_ty(&fcx, e.span, &**e, declty);
|
|
||||||
// check_expr (from check_const pass) doesn't guarantee
|
|
||||||
// that the expression is in a form that eval_const_expr can
|
|
||||||
// handle, so we may still get an internal compiler error
|
|
||||||
|
|
||||||
match const_eval::eval_const_expr_partial(ccx.tcx, &**e, Some(declty)) {
|
|
||||||
Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
|
|
||||||
Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
|
|
||||||
Ok(_) => {
|
|
||||||
span_err!(ccx.tcx.sess, e.span, E0079,
|
|
||||||
"expected signed integer constant");
|
|
||||||
}
|
|
||||||
Err(ref err) => {
|
|
||||||
span_err!(ccx.tcx.sess, err.span, E0080,
|
|
||||||
"constant evaluation error: {}",
|
|
||||||
err.description());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => ()
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check for duplicate discriminant values
|
// Check for duplicate discriminant values
|
||||||
match disr_vals.iter().position(|&x| x == current_disr_val) {
|
match disr_vals.iter().position(|&x| x == current_disr_val) {
|
||||||
|
@ -4372,15 +4334,7 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
disr_vals.push(current_disr_val);
|
disr_vals.push(current_disr_val);
|
||||||
|
|
||||||
let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &**v,
|
|
||||||
current_disr_val));
|
|
||||||
prev_disr_val = Some(current_disr_val);
|
|
||||||
|
|
||||||
variants.push(variant_info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return variants;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id })
|
let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id })
|
||||||
|
@ -4396,10 +4350,7 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
let variants = do_check(ccx, vs, id, hint);
|
do_check(ccx, vs, id, hint);
|
||||||
|
|
||||||
// cache so that ty::enum_variants won't repeat this work
|
|
||||||
ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
|
|
||||||
|
|
||||||
check_representable(ccx.tcx, sp, id, "enum");
|
check_representable(ccx.tcx, sp, id, "enum");
|
||||||
|
|
||||||
|
|
|
@ -215,25 +215,21 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
|
||||||
match traits::orphan_check(self.tcx, def_id) {
|
match traits::orphan_check(self.tcx, def_id) {
|
||||||
Ok(()) => { }
|
Ok(()) => { }
|
||||||
Err(traits::OrphanCheckErr::NoLocalInputType) => {
|
Err(traits::OrphanCheckErr::NoLocalInputType) => {
|
||||||
if !ty::has_attr(self.tcx, trait_def_id, "old_orphan_check") {
|
span_err!(
|
||||||
span_err!(
|
self.tcx.sess, item.span, E0117,
|
||||||
self.tcx.sess, item.span, E0117,
|
"the impl does not reference any \
|
||||||
"the impl does not reference any \
|
types defined in this crate; \
|
||||||
types defined in this crate; \
|
only traits defined in the current crate can be \
|
||||||
only traits defined in the current crate can be \
|
implemented for arbitrary types");
|
||||||
implemented for arbitrary types");
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => {
|
Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => {
|
||||||
if !ty::has_attr(self.tcx, trait_def_id, "old_orphan_check") {
|
span_err!(self.tcx.sess, item.span, E0210,
|
||||||
span_err!(self.tcx.sess, item.span, E0210,
|
"type parameter `{}` must be used as the type parameter for \
|
||||||
"type parameter `{}` must be used as the type parameter for \
|
some local type (e.g. `MyStruct<T>`); only traits defined in \
|
||||||
some local type (e.g. `MyStruct<T>`); only traits defined in \
|
the current crate can be implemented for a type parameter",
|
||||||
the current crate can be implemented for a type parameter",
|
param_ty.user_string(self.tcx));
|
||||||
param_ty.user_string(self.tcx));
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,8 +51,6 @@ register_diagnostics! {
|
||||||
E0075,
|
E0075,
|
||||||
E0076,
|
E0076,
|
||||||
E0077,
|
E0077,
|
||||||
E0079,
|
|
||||||
E0080,
|
|
||||||
E0081,
|
E0081,
|
||||||
E0082,
|
E0082,
|
||||||
E0083,
|
E0083,
|
||||||
|
|
|
@ -146,7 +146,7 @@ pub struct CrateCtxt<'a, 'tcx: 'a> {
|
||||||
fn write_ty_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>, node_id: ast::NodeId, ty: Ty<'tcx>) {
|
fn write_ty_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>, node_id: ast::NodeId, ty: Ty<'tcx>) {
|
||||||
debug!("write_ty_to_tcx({}, {})", node_id, ppaux::ty_to_string(tcx, ty));
|
debug!("write_ty_to_tcx({}, {})", node_id, ppaux::ty_to_string(tcx, ty));
|
||||||
assert!(!ty::type_needs_infer(ty));
|
assert!(!ty::type_needs_infer(ty));
|
||||||
tcx.node_types.borrow_mut().insert(node_id, ty);
|
tcx.node_type_insert(node_id, ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_substs_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>,
|
fn write_substs_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||||
|
|
|
@ -20,7 +20,7 @@ pub use self::imp::Lock;
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
mod imp {
|
mod imp {
|
||||||
use std::ffi::{AsOsStr, CString};
|
use std::ffi::{CString, OsStr};
|
||||||
use std::os::unix::prelude::*;
|
use std::os::unix::prelude::*;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
@ -116,7 +116,8 @@ mod imp {
|
||||||
|
|
||||||
impl Lock {
|
impl Lock {
|
||||||
pub fn new(p: &Path) -> Lock {
|
pub fn new(p: &Path) -> Lock {
|
||||||
let buf = CString::new(p.as_os_str().as_bytes()).unwrap();
|
let os: &OsStr = p.as_ref();
|
||||||
|
let buf = CString::new(os.as_bytes()).unwrap();
|
||||||
let fd = unsafe {
|
let fd = unsafe {
|
||||||
libc::open(buf.as_ptr(), libc::O_RDWR | libc::O_CREAT,
|
libc::open(buf.as_ptr(), libc::O_RDWR | libc::O_CREAT,
|
||||||
libc::S_IRWXU)
|
libc::S_IRWXU)
|
||||||
|
@ -164,9 +165,9 @@ mod imp {
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
mod imp {
|
mod imp {
|
||||||
use libc;
|
use libc;
|
||||||
use std::ffi::AsOsStr;
|
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
use std::ffi::OsStr;
|
||||||
use std::os::windows::prelude::*;
|
use std::os::windows::prelude::*;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
@ -194,7 +195,8 @@ mod imp {
|
||||||
|
|
||||||
impl Lock {
|
impl Lock {
|
||||||
pub fn new(p: &Path) -> Lock {
|
pub fn new(p: &Path) -> Lock {
|
||||||
let mut p_16: Vec<_> = p.as_os_str().encode_wide().collect();
|
let os: &OsStr = p.as_ref();
|
||||||
|
let mut p_16: Vec<_> = os.encode_wide().collect();
|
||||||
p_16.push(0);
|
p_16.push(0);
|
||||||
let handle = unsafe {
|
let handle = unsafe {
|
||||||
libc::CreateFileW(p_16.as_ptr(),
|
libc::CreateFileW(p_16.as_ptr(),
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
#![feature(collections)]
|
#![feature(collections)]
|
||||||
#![feature(core)]
|
|
||||||
#![feature(exit_status)]
|
#![feature(exit_status)]
|
||||||
#![feature(set_stdio)]
|
#![feature(set_stdio)]
|
||||||
#![feature(libc)]
|
#![feature(libc)]
|
||||||
|
@ -36,7 +35,6 @@
|
||||||
#![feature(file_path)]
|
#![feature(file_path)]
|
||||||
#![feature(path_ext)]
|
#![feature(path_ext)]
|
||||||
#![feature(path_relative_from)]
|
#![feature(path_relative_from)]
|
||||||
#![feature(convert)]
|
|
||||||
#![feature(slice_patterns)]
|
#![feature(slice_patterns)]
|
||||||
|
|
||||||
extern crate arena;
|
extern crate arena;
|
||||||
|
|
|
@ -100,7 +100,7 @@
|
||||||
//! let encoded = json::encode(&object).unwrap();
|
//! let encoded = json::encode(&object).unwrap();
|
||||||
//!
|
//!
|
||||||
//! // Deserialize using `json::decode`
|
//! // Deserialize using `json::decode`
|
||||||
//! let decoded: TestStruct = json::decode(encoded.as_slice()).unwrap();
|
//! let decoded: TestStruct = json::decode(&encoded[..]).unwrap();
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
|
@ -367,8 +367,8 @@ impl std::error::Error for EncoderError {
|
||||||
fn description(&self) -> &str { "encoder error" }
|
fn description(&self) -> &str { "encoder error" }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::error::FromError<fmt::Error> for EncoderError {
|
impl From<fmt::Error> for EncoderError {
|
||||||
fn from_error(err: fmt::Error) -> EncoderError { EncoderError::FmtError(err) }
|
fn from(err: fmt::Error) -> EncoderError { EncoderError::FmtError(err) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type EncodeResult = Result<(), EncoderError>;
|
pub type EncodeResult = Result<(), EncoderError>;
|
||||||
|
|
|
@ -36,7 +36,6 @@ Core encoding and decoding interfaces.
|
||||||
#![feature(std_misc)]
|
#![feature(std_misc)]
|
||||||
#![feature(unicode)]
|
#![feature(unicode)]
|
||||||
#![feature(str_char)]
|
#![feature(str_char)]
|
||||||
#![feature(convert)]
|
|
||||||
#![cfg_attr(test, feature(test, old_io))]
|
#![cfg_attr(test, feature(test, old_io))]
|
||||||
|
|
||||||
// test harness access
|
// test harness access
|
||||||
|
|
|
@ -1482,8 +1482,7 @@ impl<'a, K, V> Entry<'a, K, V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "collections",
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
reason = "matches entry v3 specification, waiting for dust to settle")]
|
|
||||||
/// Ensures a value is in the entry by inserting the default if empty, and returns
|
/// Ensures a value is in the entry by inserting the default if empty, and returns
|
||||||
/// a mutable reference to the value in the entry.
|
/// a mutable reference to the value in the entry.
|
||||||
pub fn or_insert(self, default: V) -> &'a mut V {
|
pub fn or_insert(self, default: V) -> &'a mut V {
|
||||||
|
@ -1493,8 +1492,7 @@ impl<'a, K, V> Entry<'a, K, V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "collections",
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
reason = "matches entry v3 specification, waiting for dust to settle")]
|
|
||||||
/// Ensures a value is in the entry by inserting the result of the default function if empty,
|
/// Ensures a value is in the entry by inserting the result of the default function if empty,
|
||||||
/// and returns a mutable reference to the value in the entry.
|
/// and returns a mutable reference to the value in the entry.
|
||||||
pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
|
pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
|
||||||
|
|
|
@ -1192,7 +1192,7 @@ mod test_set {
|
||||||
};
|
};
|
||||||
|
|
||||||
let v = hs.into_iter().collect::<Vec<char>>();
|
let v = hs.into_iter().collect::<Vec<char>>();
|
||||||
assert!(['a', 'b'] == v || ['b', 'a'] == v);
|
assert!(v == ['a', 'b'] || v == ['b', 'a']);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -15,7 +15,7 @@ use self::BucketState::*;
|
||||||
use clone::Clone;
|
use clone::Clone;
|
||||||
use cmp;
|
use cmp;
|
||||||
use hash::{Hash, Hasher};
|
use hash::{Hash, Hasher};
|
||||||
use iter::{Iterator, ExactSizeIterator, count};
|
use iter::{Iterator, ExactSizeIterator};
|
||||||
use marker::{Copy, Send, Sync, Sized, self};
|
use marker::{Copy, Send, Sync, Sized, self};
|
||||||
use mem::{min_align_of, size_of};
|
use mem::{min_align_of, size_of};
|
||||||
use mem;
|
use mem;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue