Auto merge of #23936 - pnkfelix:rollup, r=pnkfelix

This is an attempt to fix #23922
This commit is contained in:
bors 2015-04-01 10:02:37 +00:00
commit 8943653624
284 changed files with 3826 additions and 5197 deletions

View File

@ -18,7 +18,6 @@
#![feature(std_misc)]
#![feature(test)]
#![feature(path_ext)]
#![feature(convert)]
#![feature(str_char)]
#![deny(warnings)]

View File

@ -977,7 +977,6 @@ An example of `use` declarations:
```
# #![feature(core)]
use std::iter::range_step;
use std::option::Option::{Some, None};
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 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),
// std::option::Option::None]);'
foo(vec![Some(1.0f64), None]);

View File

@ -42,5 +42,6 @@
* [Intrinsics](intrinsics.md)
* [Lang items](lang-items.md)
* [Link args](link-args.md)
* [Benchmark Tests](benchmark-tests.md)
* [Conclusion](conclusion.md)
* [Glossary](glossary.md)

View File

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

View File

@ -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
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
time to wait, but it's entirely possible that we've picked too high, and that
we could be taking less time. It's also possible that we've picked too low,
and that we aren't actually finishing this computation.
Lastly, while the threads are running, we wait on a short timer. But
this is not ideal: we may have picked a reasonable amount of time to
wait but it's more likely we'll either be waiting longer than
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
synchronize with each other. Let's talk about one: channels.
A more precise alternative to the timer would be to use one of the
mechanisms provided by the Rust standard library for synchronizing
threads with each other. Let's talk about one of them: channels.
## Channels

View File

@ -243,11 +243,12 @@ for num in nums.iter() {
```
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
# #![feature(core)]
std::iter::count(1, 5);
# #![feature(step_by)]
(1..).step_by(5);
```
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
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
iterator from before, `count()`:
iterator from before:
```rust
# #![feature(core)]
for i in std::iter::count(1, 5).take(5) {
# #![feature(step_by)]
for i in (1..).step_by(5).take(5) {
println!("{}", i);
}
```

View File

@ -37,7 +37,7 @@ number of elements.
```rust
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.
@ -51,7 +51,7 @@ let x: Vec<u32> = {
temp_vec.push(3);
temp_vec
};
# assert_eq!(&[1,2,3], &x);
# assert_eq!(x, [1, 2, 3]);
```
We can implement this shorthand, using a macro: [^actual]
@ -73,7 +73,7 @@ macro_rules! vec {
};
}
# fn main() {
# assert_eq!([1,2,3], vec![1,2,3]);
# assert_eq!(vec![1,2,3], [1, 2, 3]);
# }
```

View File

@ -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
secondary inference algorithm called “lifetime elision” applies in function
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
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.

View File

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

View File

@ -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
dispatch](static-and-dynamic-dispatch.html) for more.
## Multiple trait bounds
Youve 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
Writing functions with only a few generic types and a small number of trait

View File

@ -110,7 +110,7 @@ use heap::deallocate;
/// let child_numbers = shared_numbers.clone();
///
/// thread::spawn(move || {
/// let local_numbers = child_numbers.as_slice();
/// let local_numbers = &child_numbers[..];
///
/// // Work with the local numbers
/// });

View File

@ -51,13 +51,15 @@ use core::prelude::*;
use core::any::Any;
use core::cmp::Ordering;
use core::default::Default;
use core::error::{Error, FromError};
use core::error::Error;
use core::fmt;
use core::hash::{self, Hash};
use core::mem;
use core::ops::{Deref, DerefMut};
use core::ptr::Unique;
use core::raw::TraitObject;
use core::ptr::{self, Unique};
use core::raw::{TraitObject, Slice};
use heap;
/// A value that represents the heap. This is the default place that the `box`
/// 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.
#[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> {
impl Box<Any> {
#[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>() {
unsafe {
// 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 BoxAny for Box<Any+Send> {
impl Box<Any+Send> {
#[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)
}
}
@ -322,8 +310,48 @@ impl<I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for Box<I> {
impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for Box<I> {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, E: Error + 'a> FromError<E> for Box<Error + 'a> {
fn from_error(err: E) -> Box<Error + 'a> {
impl<'a, E: Error + 'a> From<E> for Box<Error + 'a> {
fn from(err: E) -> Box<Error + 'a> {
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(),
})))
}
}
}

View File

@ -17,7 +17,6 @@ use core::clone::Clone;
use std::boxed;
use std::boxed::Box;
use std::boxed::BoxAny;
#[test]
fn test_owned_clone() {

View File

@ -38,7 +38,7 @@
//! [sieve]: http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
//!
//! ```
//! # #![feature(collections, core)]
//! # #![feature(collections, core, step_by)]
//! use std::collections::{BitSet, BitVec};
//! use std::num::Float;
//! use std::iter;
@ -60,7 +60,7 @@
//! if bv[i] {
//! // Mark all multiples of i as non-prime (any multiples below i * i
//! // 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)
@ -1264,14 +1264,6 @@ impl BitSet {
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
/// element less than this amount will not trigger a resizing.
///

View File

@ -40,6 +40,24 @@ use self::Cow::*;
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Borrow<Borrowed: ?Sized> {
/// 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")]
fn borrow(&self) -> &Borrowed;
}
@ -50,6 +68,20 @@ pub trait Borrow<Borrowed: ?Sized> {
#[stable(feature = "rust1", since = "1.0.0")]
pub trait BorrowMut<Borrowed: ?Sized> : Borrow<Borrowed> {
/// 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")]
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.
///
/// 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")]
pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {
match *self {
@ -185,6 +229,18 @@ impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned {
/// Extract the owned data.
///
/// 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")]
pub fn into_owned(self) -> <B as ToOwned>::Owned {
match self {
@ -192,26 +248,6 @@ impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned {
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")]

View File

@ -1134,8 +1134,7 @@ impl<'a, K: Ord, V> Entry<'a, K, V> {
}
}
#[unstable(feature = "collections",
reason = "matches entry v3 specification, waiting for dust to settle")]
#[stable(feature = "rust1", since = "1.0.0")]
/// Ensures a value is in the entry by inserting the default if empty, and returns
/// a mutable reference to the value in the entry.
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",
reason = "matches entry v3 specification, waiting for dust to settle")]
#[stable(feature = "rust1", since = "1.0.0")]
/// 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.
pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {

View File

@ -38,7 +38,6 @@
#![feature(unsafe_no_drop_flag, filling_drop)]
#![feature(step_by)]
#![feature(str_char)]
#![feature(convert)]
#![feature(slice_patterns)]
#![feature(debug_builders)]
#![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_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
pub use alloc::boxed;
@ -108,10 +91,6 @@ pub mod vec_map;
reason = "RFC 509")]
pub mod bit_vec {
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",
@ -119,10 +98,6 @@ pub mod bit_vec {
pub mod bit_set {
pub use bit::{BitSet, Union, Intersection, Difference, SymmetricDifference};
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")]

View File

@ -32,10 +32,6 @@ use core::iter::{self, FromIterator, IntoIterator};
use core::mem;
use core::ptr;
#[deprecated(since = "1.0.0", reason = "renamed to LinkedList")]
#[unstable(feature = "collections")]
pub use LinkedList as DList;
/// A doubly-linked list.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct LinkedList<T> {
@ -252,6 +248,7 @@ impl<T> LinkedList<T> {
/// }
/// println!("{}", b.len()); // prints 0
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn append(&mut self, other: &mut LinkedList<T>) {
match self.list_tail.resolve() {
None => {
@ -844,7 +841,7 @@ impl<A> ExactSizeIterator for IntoIter<A> {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<A> FromIterator<A> for 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
}
@ -1079,7 +1076,7 @@ mod test {
thread::spawn(move || {
check_links(&n);
let a: &[_] = &[&1,&2,&3];
assert_eq!(a, n.iter().collect::<Vec<_>>());
assert_eq!(a, &n.iter().collect::<Vec<_>>()[..]);
}).join().ok().unwrap();
}

View File

@ -89,8 +89,6 @@ use core::iter::MultiplicativeIterator;
use core::marker::Sized;
use core::mem::size_of;
use core::mem;
#[cfg(stage0)]
use core::num::wrapping::WrappingOps;
use core::ops::FnMut;
use core::option::Option::{self, Some, None};
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::{bytes, mut_ref_slice, ref_slice};
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
@ -281,33 +278,6 @@ impl<T> [T] {
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.
///
/// The first will contain all indices from `[0, mid)` (excluding
@ -557,7 +527,6 @@ impl<T> [T] {
/// ```rust
/// # #![feature(core)]
/// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
/// let s = s.as_slice();
///
/// let seek = 13;
/// 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)
}
/// 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
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
@ -924,7 +857,6 @@ impl<T> [T] {
/// ```rust
/// # #![feature(core)]
/// 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(&4), Err(7));
@ -937,13 +869,6 @@ impl<T> [T] {
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.
///
/// Returns `true` if successful and `false` if the slice is at the

View File

@ -10,13 +10,12 @@
//
// 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
//! types of the language. `&str` is the borrowed string type. This type of
//! string can only be created from other strings, unless it is a `&'static str`
//! (see below). It is not possible to move out of borrowed strings because they
//! are owned elsewhere.
//! Rust's `str` type is one of the core primitive types of the language. `&str`
//! is the borrowed string type. This type of string can only be created from
//! other strings, unless it is a `&'static str` (see below). It is not possible
//! to move out of borrowed strings because they are owned elsewhere.
//!
//! # Examples
//!
@ -70,11 +69,11 @@ use vec::Vec;
use slice::SliceConcatExt;
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::{RSplit, RSplitN};
pub use core::str::{from_utf8, CharEq, Chars, CharIndices, Bytes};
pub use core::str::{from_utf8_unchecked, from_c_str, ParseBoolError};
pub use core::str::{from_utf8, Chars, CharIndices, Bytes};
pub use core::str::{from_utf8_unchecked, ParseBoolError};
pub use unicode::str::{Words, Graphemes, GraphemeIndices};
pub use core::str::Pattern;
pub use core::str::{Searcher, ReverseSearcher, DoubleEndedSearcher, SearchStep};
@ -536,22 +535,6 @@ impl str {
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`.
///
/// # Examples
@ -778,25 +761,6 @@ impl str {
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`.
///
/// This does not include the empty string after a trailing `\n`.
@ -848,31 +812,6 @@ impl str {
pub fn lines_any(&self) -> LinesAny {
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`).
///
/// 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)
}
/// 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.
///
/// 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 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 b: &[_] = &["a", "\r\n", "b", "🇷🇺🇸🇹"];
///
/// assert_eq!(gr2.as_slice(), b);
/// assert_eq!(&gr2[..], b);
/// ```
#[unstable(feature = "unicode",
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 b: &[_] = &[(0, "a̐"), (3, "é"), (6, "ö̲"), (11, "\r\n")];
///
/// assert_eq!(gr_inds.as_slice(), b);
/// assert_eq!(&gr_inds[..], b);
/// ```
#[unstable(feature = "unicode",
reason = "this functionality may only be provided by libunicode")]

View File

@ -93,7 +93,7 @@ impl String {
/// ```
/// # #![feature(collections, core)]
/// let s = String::from_str("hello");
/// assert_eq!(s.as_slice(), "hello");
/// assert_eq!(&s[..], "hello");
/// ```
#[inline]
#[unstable(feature = "collections",
@ -364,6 +364,14 @@ impl String {
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.
///
/// # Examples
@ -848,7 +856,6 @@ impl<'a, 'b> PartialEq<Cow<'a, str>> for &'b str {
#[allow(deprecated)]
impl Str for String {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn as_slice(&self) -> &str {
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")]
impl fmt::Write for String {
#[inline]

View File

@ -389,7 +389,7 @@ impl<T> Vec<T> {
/// Note that this will drop any excess capacity. Calling this and
/// converting back to a vector with `into_vec()` is equivalent to calling
/// `shrink_to_fit()`.
#[unstable(feature = "collections")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_boxed_slice(mut self) -> Box<[T]> {
self.shrink_to_fit();
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.
#[inline]
#[unstable(feature = "collections",
reason = "will be replaced by slice syntax")]
#[deprecated(since = "1.0.0", reason = "use &mut s[..] instead")]
#[unstable(feature = "convert",
reason = "waiting on RFC revision")]
pub fn as_mut_slice(&mut self) -> &mut [T] {
&mut self[..]
}
@ -823,13 +830,13 @@ impl<T> Vec<T> {
/// # #![feature(collections, core)]
/// let v = vec![0, 1, 2];
/// 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)]
/// struct Newtype(u8);
/// let bytes = vec![0x11, 0x22];
/// 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",
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_eq2! { Vec<A>, &'b [B] }
__impl_slice_eq2! { Vec<A>, &'b mut [B] }
__impl_slice_eq2! { Cow<'a, [A]>, &'b [B], Clone }
__impl_slice_eq2! { Cow<'a, [A]>, &'b mut [B], Clone }
__impl_slice_eq2! { Cow<'a, [A]>, Vec<B>, Clone }
__impl_slice_eq1! { Vec<A>, &'b [B] }
__impl_slice_eq1! { Vec<A>, &'b mut [B] }
__impl_slice_eq1! { Cow<'a, [A]>, &'b [B], Clone }
__impl_slice_eq1! { Cow<'a, [A]>, &'b mut [B], Clone }
__impl_slice_eq1! { Cow<'a, [A]>, Vec<B>, Clone }
macro_rules! array_impls {
($($N: expr)+) => {
$(
// NOTE: some less important impls are omitted to reduce code bloat
__impl_slice_eq2! { Vec<A>, [B; $N] }
__impl_slice_eq2! { Vec<A>, &'b [B; $N] }
// __impl_slice_eq2! { Vec<A>, &'b mut [B; $N] }
// __impl_slice_eq2! { Cow<'a, [A]>, [B; $N], Clone }
// __impl_slice_eq2! { Cow<'a, [A]>, &'b [B; $N], Clone }
// __impl_slice_eq2! { Cow<'a, [A]>, &'b mut [B; $N], Clone }
__impl_slice_eq1! { Vec<A>, [B; $N] }
__impl_slice_eq1! { Vec<A>, &'b [B; $N] }
// __impl_slice_eq1! { Vec<A>, &'b mut [B; $N] }
// __impl_slice_eq1! { Cow<'a, [A]>, [B; $N], Clone }
// __impl_slice_eq1! { Cow<'a, [A]>, &'b [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")]
impl<T> AsRef<[T]> for Vec<T> {
fn as_ref(&self) -> &[T] {
@ -1679,11 +1679,6 @@ impl<'a> From<&'a str> for Vec<u8> {
// 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")]
impl<'a, T> FromIterator<T> for Cow<'a, [T]> where T: Clone {
fn from_iter<I: IntoIterator<Item=T>>(it: I) -> Cow<'a, [T]> {

View File

@ -25,8 +25,6 @@ use core::default::Default;
use core::fmt;
use core::iter::{self, repeat, FromIterator, IntoIterator, RandomAccessIterator};
use core::mem;
#[cfg(stage0)]
use core::num::wrapping::WrappingOps;
use core::ops::{Index, IndexMut};
use core::ptr::{self, Unique};
use core::slice;
@ -36,10 +34,6 @@ use core::cmp;
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 MINIMUM_CAPACITY: usize = 1; // 2 - 1
@ -527,7 +521,8 @@ impl<T> VecDeque<T> {
/// buf.push_back(3);
/// buf.push_back(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")]
pub fn iter(&self) -> Iter<T> {
@ -1902,7 +1897,7 @@ mod test {
// len is the length *after* insertion
for len in 1..cap {
// 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 to_insert in 0..len {
tester.tail = tail_pos;
@ -1935,7 +1930,7 @@ mod test {
// len is the length *after* removal
for len in 0..cap - 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 to_remove in 0..len + 1 {
tester.tail = tail_pos;
@ -1973,7 +1968,7 @@ mod test {
for len in 0..cap + 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 {
tester.tail = tail_pos;
tester.head = tail_pos;
@ -2006,9 +2001,9 @@ mod test {
// index to split at
for at in 0..len + 1 {
// 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)
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 {
tester.tail = tail_pos;

View File

@ -10,7 +10,6 @@
use std::cmp::Ordering::{Equal, Greater, Less};
use std::collections::{BitSet, BitVec};
use std::iter::range_step;
#[test]
fn test_bit_set_show() {
@ -42,7 +41,7 @@ fn test_bit_set_iterator() {
assert_eq!(idxs, [0, 2, 3]);
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();
assert_eq!(idxs, real);

View File

@ -153,19 +153,19 @@ fn test_iterator() {
e1.insert(A);
let elems: Vec<_> = e1.iter().collect();
assert_eq!([A], elems);
assert_eq!(elems, [A]);
e1.insert(C);
let elems: Vec<_> = e1.iter().collect();
assert_eq!([A,C], elems);
assert_eq!(elems, [A,C]);
e1.insert(C);
let elems: Vec<_> = e1.iter().collect();
assert_eq!([A,C], elems);
assert_eq!(elems, [A,C]);
e1.insert(B);
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 elems: Vec<_> = e_union.iter().collect();
assert_eq!([A,B,C], elems);
assert_eq!(elems, [A,B,C]);
let e_intersection = e1 & e2;
let elems: Vec<_> = e_intersection.iter().collect();
assert_eq!([C], elems);
assert_eq!(elems, [C]);
// Another way to express intersection
let e_intersection = e1 - (e1 - e2);
let elems: Vec<_> = e_intersection.iter().collect();
assert_eq!([C], elems);
assert_eq!(elems, [C]);
let e_subtract = e1 - e2;
let elems: Vec<_> = e_subtract.iter().collect();
assert_eq!([A], elems);
assert_eq!(elems, [A]);
// Bitwise XOR of two sets, aka symmetric difference
let e_symmetric_diff = e1 ^ e2;
let elems: Vec<_> = e_symmetric_diff.iter().collect();
assert_eq!([A,B], elems);
assert_eq!(elems, [A,B]);
// Another way to express symmetric difference
let e_symmetric_diff = (e1 - e2) | (e2 - e1);
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
let e_symmetric_diff = (e1 | e2) - (e1 & e2);
let elems: Vec<_> = e_symmetric_diff.iter().collect();
assert_eq!([A,B], elems);
assert_eq!(elems, [A,B]);
}
#[test]

View File

@ -13,5 +13,5 @@ use std::fmt;
#[test]
fn test_format() {
let s = fmt::format(format_args!("Hello, {}!", "world"));
assert_eq!(s.as_slice(), "Hello, world!");
assert_eq!(s, "Hello, world!");
}

View File

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(deprecated)]
#![feature(box_syntax)]
#![feature(collections)]
#![feature(core)]
@ -21,6 +20,7 @@
#![feature(unicode)]
#![feature(unsafe_destructor)]
#![feature(into_cow)]
#![feature(step_by)]
#![cfg_attr(test, feature(str_char))]
#[macro_use] extern crate log;

View File

@ -59,7 +59,7 @@ fn test_from_elem() {
// Test on-heap from_elem.
v = vec![20; 6];
{
let v = v.as_slice();
let v = &v[..];
assert_eq!(v[0], 20);
assert_eq!(v[1], 20);
assert_eq!(v[2], 20);
@ -685,7 +685,7 @@ fn test_capacity() {
#[test]
fn test_slice_2() {
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[0], 2);
assert_eq!(v[1], 3);

View File

@ -83,38 +83,38 @@ fn test_collect() {
fn test_into_bytes() {
let data = String::from_str("asdf");
let buf = data.into_bytes();
assert_eq!(b"asdf", buf);
assert_eq!(buf, b"asdf");
}
#[test]
fn test_find_str() {
// byte positions
assert_eq!("".find_str(""), Some(0));
assert!("banana".find_str("apple pie").is_none());
assert_eq!("".find(""), Some(0));
assert!("banana".find("apple pie").is_none());
let data = "abcabc";
assert_eq!(data[0..6].find_str("ab"), Some(0));
assert_eq!(data[2..6].find_str("ab"), Some(3 - 2));
assert!(data[2..4].find_str("ab").is_none());
assert_eq!(data[0..6].find("ab"), Some(0));
assert_eq!(data[2..6].find("ab"), Some(3 - 2));
assert!(data[2..4].find("ab").is_none());
let string = "ประเทศไทย中华Việt Nam";
let mut data = String::from_str(string);
data.push_str(string);
assert!(data.find_str("ไท华").is_none());
assert_eq!(data[0..43].find_str(""), Some(0));
assert_eq!(data[6..43].find_str(""), Some(6 - 6));
assert!(data.find("ไท华").is_none());
assert_eq!(data[0..43].find(""), Some(0));
assert_eq!(data[6..43].find(""), Some(6 - 6));
assert_eq!(data[0..43].find_str("ประ"), Some( 0));
assert_eq!(data[0..43].find_str("ทศไ"), Some(12));
assert_eq!(data[0..43].find_str("ย中"), Some(24));
assert_eq!(data[0..43].find_str("iệt"), Some(34));
assert_eq!(data[0..43].find_str("Nam"), Some(40));
assert_eq!(data[0..43].find("ประ"), Some( 0));
assert_eq!(data[0..43].find("ทศไ"), Some(12));
assert_eq!(data[0..43].find("ย中"), Some(24));
assert_eq!(data[0..43].find("iệt"), Some(34));
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_str("ทศไ"), Some(55 - 43));
assert_eq!(data[43..86].find_str("ย中"), Some(67 - 43));
assert_eq!(data[43..86].find_str("iệt"), Some(77 - 43));
assert_eq!(data[43..86].find_str("Nam"), Some(83 - 43));
assert_eq!(data[43..86].find("ประ"), Some(43 - 43));
assert_eq!(data[43..86].find("ทศไ"), Some(55 - 43));
assert_eq!(data[43..86].find("ย中"), Some(67 - 43));
assert_eq!(data[43..86].find("iệt"), Some(77 - 43));
assert_eq!(data[43..86].find("Nam"), Some(83 - 43));
}
#[test]
@ -297,16 +297,16 @@ fn test_replace_2d() {
#[test]
fn test_slice() {
assert_eq!("ab", "abc".slice(0, 2));
assert_eq!("bc", "abc".slice(1, 3));
assert_eq!("", "abc".slice(1, 1));
assert_eq!("\u{65e5}", "\u{65e5}\u{672c}".slice(0, 3));
assert_eq!("ab", &"abc"[0..2]);
assert_eq!("bc", &"abc"[1..3]);
assert_eq!("", &"abc"[1..1]);
assert_eq!("\u{65e5}", &"\u{65e5}\u{672c}"[0..3]);
let data = "ประเทศไทย中华";
assert_eq!("", data.slice(0, 3));
assert_eq!("", data.slice(3, 6));
assert_eq!("", data.slice(3, 3));
assert_eq!("", data.slice(30, 33));
assert_eq!("", &data[0..3]);
assert_eq!("", &data[3..6]);
assert_eq!("", &data[3..3]);
assert_eq!("", &data[30..33]);
fn a_million_letter_x() -> String {
let mut i = 0;
@ -328,23 +328,23 @@ fn test_slice() {
}
let letters = 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]
fn test_slice_2() {
let ss = "中华Việt Nam";
assert_eq!("", ss.slice(3, 6));
assert_eq!("Việt Nam", ss.slice(6, 16));
assert_eq!("", &ss[3..6]);
assert_eq!("Việt Nam", &ss[6..16]);
assert_eq!("ab", "abc".slice(0, 2));
assert_eq!("bc", "abc".slice(1, 3));
assert_eq!("", "abc".slice(1, 1));
assert_eq!("ab", &"abc"[0..2]);
assert_eq!("bc", &"abc"[1..3]);
assert_eq!("", &"abc"[1..1]);
assert_eq!("", ss.slice(0, 3));
assert_eq!("华V", ss.slice(3, 7));
assert_eq!("", ss.slice(3, 3));
assert_eq!("", &ss[0..3]);
assert_eq!("华V", &ss[3..7]);
assert_eq!("", &ss[3..3]);
/*0: 中
3:
6: V
@ -360,20 +360,20 @@ fn test_slice_2() {
#[test]
#[should_panic]
fn test_slice_fail() {
"中华Việt Nam".slice(0, 2);
&"中华Việt Nam"[0..2];
}
#[test]
fn test_slice_from() {
assert_eq!("abcd".slice_from(0), "abcd");
assert_eq!("abcd".slice_from(2), "cd");
assert_eq!("abcd".slice_from(4), "");
assert_eq!(&"abcd"[0..], "abcd");
assert_eq!(&"abcd"[2..], "cd");
assert_eq!(&"abcd"[4..], "");
}
#[test]
fn test_slice_to() {
assert_eq!("abcd".slice_to(0), "");
assert_eq!("abcd".slice_to(2), "ab");
assert_eq!("abcd".slice_to(4), "abcd");
assert_eq!(&"abcd"[..0], "");
assert_eq!(&"abcd"[..2], "ab");
assert_eq!(&"abcd"[..4], "abcd");
}
#[test]
@ -660,10 +660,10 @@ fn test_contains() {
#[test]
fn test_contains_char() {
assert!("abc".contains_char('b'));
assert!("a".contains_char('a'));
assert!(!"abc".contains_char('d'));
assert!(!"".contains_char('a'));
assert!("abc".contains('b'));
assert!("a".contains('a'));
assert!(!"abc".contains('d'));
assert!(!"".contains('a'));
}
#[test]
@ -1445,9 +1445,9 @@ fn test_graphemes() {
}
#[test]
fn test_split_strator() {
fn test_splitator() {
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);
}
t("--1233345--", "12345", &["--1233345--"]);
@ -1470,9 +1470,9 @@ fn test_split_strator() {
fn test_str_default() {
use std::default::Default;
fn t<S: Default + Str>() {
fn t<S: Default + AsRef<str>>() {
let s: S = Default::default();
assert_eq!(s.as_slice(), "");
assert_eq!(s.as_ref(), "");
}
t::<&str>();

View File

@ -8,10 +8,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::borrow::IntoCow;
use std::borrow::{IntoCow, Cow};
use std::iter::repeat;
use std::str::Utf8Error;
use std::string::{CowString, as_string};
use std::string::as_string;
use test::Bencher;
@ -52,11 +52,11 @@ fn test_from_utf8() {
#[test]
fn test_from_utf8_lossy() {
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);
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);
let xs = b"Hello\xC2 There\xFF Goodbye";

View File

@ -18,7 +18,6 @@ use self::Taggy::*;
use self::Taggypar::*;
#[test]
#[allow(deprecated)]
fn test_simple() {
let mut d = VecDeque::new();
assert_eq!(d.len(), 0);
@ -545,7 +544,7 @@ fn test_from_iter() {
let u: Vec<_> = deq.iter().cloned().collect();
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();
for (i, &x) in deq.iter().enumerate() {
assert_eq!(2*i, x);
@ -821,7 +820,7 @@ fn test_as_slices() {
let (left, right) = ring.as_slices();
let expected: Vec<_> = (0..i+1).collect();
assert_eq!(left, expected);
assert_eq!(left, &expected[..]);
assert_eq!(right, []);
}
@ -830,8 +829,8 @@ fn test_as_slices() {
let (left, right) = ring.as_slices();
let expected_left: Vec<_> = (-last..j+1).rev().collect();
let expected_right: Vec<_> = (0..first).collect();
assert_eq!(left, expected_left);
assert_eq!(right, expected_right);
assert_eq!(left, &expected_left[..]);
assert_eq!(right, &expected_right[..]);
}
assert_eq!(ring.len() as i32, cap);
@ -849,7 +848,7 @@ fn test_as_mut_slices() {
let (left, right) = ring.as_mut_slices();
let expected: Vec<_> = (0..i+1).collect();
assert_eq!(left, expected);
assert_eq!(left, &expected[..]);
assert_eq!(right, []);
}
@ -858,8 +857,8 @@ fn test_as_mut_slices() {
let (left, right) = ring.as_mut_slices();
let expected_left: Vec<_> = (-last..j+1).rev().collect();
let expected_right: Vec<_> = (0..first).collect();
assert_eq!(left, expected_left);
assert_eq!(right, expected_right);
assert_eq!(left, &expected_left[..]);
assert_eq!(right, &expected_right[..]);
}
assert_eq!(ring.len() as i32, cap);

View File

@ -202,8 +202,7 @@ pub struct TypeId {
impl TypeId {
/// Returns the `TypeId` of the type this generic function has been
/// instantiated with
#[unstable(feature = "core",
reason = "may grow a `Reflect` bound soon via marker traits")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn of<T: ?Sized + Any>() -> TypeId {
TypeId {
t: unsafe { intrinsics::type_id::<T>() },

View File

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

View File

@ -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.
///
/// 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.
///
/// The borrow lasts until the returned `RefMut` exits scope. The value

View File

@ -64,7 +64,6 @@ use option::Option::{self, Some, None};
/// inverse of `ne`; that is, `!(a == b)` if and only if `a != b`.
#[lang="eq"]
#[stable(feature = "rust1", since = "1.0.0")]
#[old_orphan_check]
pub trait PartialEq<Rhs: ?Sized = Self> {
/// This method tests for `self` and `other` values to be equal, and is used by `==`.
#[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.
///
/// Returns the first argument if the comparison determines them to be equal.
///
/// # Examples
///
/// ```
@ -371,11 +372,13 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
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.
///
/// Returns the second argument if the comparison determines them to be equal.
///
/// # Examples
///
/// ```
@ -387,7 +390,7 @@ pub fn min<T: Ord>(v1: T, v2: T) -> T {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
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.
@ -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.
///
/// 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
///
@ -450,8 +453,8 @@ pub fn partial_min<T: PartialOrd>(v1: T, v2: T) -> Option<T> {
#[unstable(feature = "core")]
pub fn partial_max<T: PartialOrd>(v1: T, v2: T) -> Option<T> {
match v1.partial_cmp(&v2) {
Some(Less) => Some(v2),
Some(Equal) | Some(Greater) => Some(v1),
Some(Equal) | Some(Less) => Some(v2),
Some(Greater) => Some(v1),
None => None
}
}

View File

@ -15,8 +15,11 @@
#[macro_export]
macro_rules! __impl_slice_eq1 {
($Lhs: ty, $Rhs: ty) => {
__impl_slice_eq1! { $Lhs, $Rhs, Sized }
};
($Lhs: ty, $Rhs: ty, $Bound: ident) => {
#[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]
fn eq(&self, other: &$Rhs) -> bool { &self[..] == &other[..] }
#[inline]
@ -31,13 +34,7 @@ macro_rules! __impl_slice_eq2 {
__impl_slice_eq2! { $Lhs, $Rhs, Sized }
};
($Lhs: ty, $Rhs: ty, $Bound: ident) => {
#[stable(feature = "rust1", since = "1.0.0")]
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[..] }
}
__impl_slice_eq1!($Lhs, $Rhs, $Bound);
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, 'b, A: $Bound, B> PartialEq<$Lhs> for $Rhs where B: PartialEq<A> {

View File

@ -14,33 +14,40 @@
//! conversions from one type to another. They follow the standard
//! Rust conventions of `as`/`to`/`into`/`from`.
#![unstable(feature = "convert",
reason = "recently added, experimental traits")]
#![stable(feature = "rust1", since = "1.0.0")]
use marker::Sized;
/// A cheap, reference-to-reference conversion.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait AsRef<T: ?Sized> {
/// Perform the conversion.
#[stable(feature = "rust1", since = "1.0.0")]
fn as_ref(&self) -> &T;
}
/// A cheap, mutable reference-to-mutable reference conversion.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait AsMut<T: ?Sized> {
/// Perform the conversion.
#[stable(feature = "rust1", since = "1.0.0")]
fn as_mut(&mut self) -> &mut T;
}
/// A conversion that consumes `self`, which may or may not be
/// expensive.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Into<T>: Sized {
/// Perform the conversion.
#[stable(feature = "rust1", since = "1.0.0")]
fn into(self) -> T;
}
/// Construct `Self` via a conversion.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait From<T> {
/// Perform the conversion.
#[stable(feature = "rust1", since = "1.0.0")]
fn from(T) -> Self;
}
@ -48,14 +55,8 @@ pub trait From<T> {
// 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 &
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a T where T: AsRef<U> {
fn as_ref(&self) -> &U {
<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
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a mut T where T: AsRef<U> {
fn as_ref(&self) -> &U {
<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
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized, U: ?Sized> AsMut<U> for &'a mut T where T: AsMut<U> {
fn as_mut(&mut self) -> &mut U {
(*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
#[stable(feature = "rust1", since = "1.0.0")]
impl<T, U> Into<U> for T where U: From<T> {
fn into(self) -> U {
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
////////////////////////////////////////////////////////////////////////////////
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> AsRef<[T]> for [T] {
fn as_ref(&self) -> &[T] {
self
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> AsMut<[T]> for [T] {
fn as_mut(&mut self) -> &mut [T] {
self
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<str> for str {
fn as_ref(&self) -> &str {
self

View File

@ -33,49 +33,6 @@
//! high-level module to provide its own errors that do not commit to any
//! particular implementation, but also reveal some of its implementation for
//! 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")]
@ -97,19 +54,3 @@ pub trait Error: Debug + Display {
#[stable(feature = "rust1", since = "1.0.0")]
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
}
}

View File

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

View File

@ -114,11 +114,6 @@ impl SipHasher {
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) {
self.length = 0;
self.v0 = self.k0 ^ 0x736f6d6570736575;

View File

@ -197,7 +197,6 @@ extern "rust-intrinsic" {
/// Rust moves to non-zeroing dynamic drop (and thus removes the
/// embedded drop flags that are being established by this
/// intrinsic).
#[cfg(not(stage0))]
pub fn init_dropped<T>() -> T;
/// Create a value initialized to zero.

View File

@ -12,39 +12,40 @@
//!
//! # The `Iterator` trait
//!
//! This module defines Rust's core iteration trait. The `Iterator` trait has one
//! unimplemented method, `next`. All other methods are derived through default
//! methods to perform operations such as `zip`, `chain`, `enumerate`, and `fold`.
//! This module defines Rust's core iteration trait. The `Iterator` trait has
//! one unimplemented method, `next`. All other methods are derived through
//! 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.
//! An iterator can be considered as a state machine which is used to track which
//! element will be yielded next.
//! An iterator can be considered as a state machine which is used to track
//! which element will be yielded next.
//!
//! There are various extensions also defined in this module to assist with various
//! types of iteration, such as the `DoubleEndedIterator` for iterating in reverse,
//! the `FromIterator` trait for creating a container from an iterator, and much
//! more.
//! There are various extensions also defined in this module to assist with
//! various types of iteration, such as the `DoubleEndedIterator` for iterating
//! in reverse, the `FromIterator` trait for creating a container from an
//! 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`
//! trait defined in this module. For loops can be viewed as a syntactical expansion
//! into a `loop`, for example, the `for` loop in this example is essentially
//! translated to the `loop` below.
//! The special syntax used by rust's `for` loop is based around the
//! `IntoIterator` trait defined in this module. `for` loops can be viewed as a
//! syntactical expansion into a `loop`, for example, the `for` loop in this
//! example is essentially translated to the `loop` below.
//!
//! ```
//! let values = vec![1, 2, 3];
//!
//! // "Syntactical sugar" taking advantage of an iterator
//! for &x in values.iter() {
//! for x in values {
//! println!("{}", x);
//! }
//!
//! // 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 {
//! match it.next() {
//! Some(&x) => {
//! Some(x) => {
//! println!("{}", x);
//! }
//! 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")]
@ -64,10 +66,9 @@ use cmp::Ord;
use default::Default;
use marker;
use mem;
use num::{Int, Zero, One, ToPrimitive};
use ops::{Add, Sub, FnMut, RangeFrom};
use option::Option;
use option::Option::{Some, None};
use num::{Int, Zero, One};
use ops::{self, Add, Sub, FnMut, RangeFrom};
use option::Option::{self, Some, None};
use marker::Sized;
use usize;
@ -85,21 +86,22 @@ fn _assert_is_object_safe(_: &Iterator) {}
/// else.
#[lang="iterator"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented = "`{Self}` is not an iterator; maybe try calling `.iter()` or a similar \
method"]
#[rustc_on_unimplemented = "`{Self}` is not an iterator; maybe try calling \
`.iter()` or a similar method"]
pub trait Iterator {
/// The type of the elements being iterated
#[stable(feature = "rust1", since = "1.0.0")]
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")]
fn next(&mut self) -> Option<Self::Item>;
/// 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
/// does not fit within a `usize`.
/// An upper bound of `None` means either there is no known upper bound, or
/// the upper bound does not fit within a `usize`.
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn size_hint(&self) -> (usize, Option<usize>) { (0, None) }
@ -275,7 +277,8 @@ pub trait Iterator {
/// iterator plus the current index of iteration.
///
/// `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
///
@ -433,7 +436,7 @@ pub trait Iterator {
/// # #![feature(core)]
/// let xs = [2, 3];
/// 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`
/// for (i, x) in it.enumerate() {
/// assert_eq!(x, ys[i]);
@ -530,10 +533,9 @@ pub trait Iterator {
/// # Examples
///
/// ```
/// # #![feature(core)]
/// let a = [1, 2, 3, 4, 5];
/// let b: Vec<_> = a.iter().cloned().collect();
/// assert_eq!(a, b);
/// let expected = [1, 2, 3, 4, 5];
/// let actual: Vec<_> = expected.iter().cloned().collect();
/// assert_eq!(actual, expected);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@ -553,8 +555,7 @@ pub trait Iterator {
/// assert_eq!(even, [2, 4]);
/// assert_eq!(odd, [1, 3]);
/// ```
#[unstable(feature = "core",
reason = "recently added as part of collections reform")]
#[stable(feature = "rust1", since = "1.0.0")]
fn partition<B, F>(self, mut f: F) -> (B, B) where
Self: Sized,
B: Default + Extend<Self::Item>,
@ -613,7 +614,8 @@ pub trait Iterator {
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.
///
@ -624,7 +626,7 @@ pub trait Iterator {
/// let a = [1, 2, 3, 4, 5];
/// let mut it = a.iter();
/// assert!(it.any(|x| *x == 3));
/// assert_eq!(it.as_slice(), [4, 5]);
/// assert_eq!(&it[..], [4, 5]);
///
/// ```
#[inline]
@ -648,7 +650,7 @@ pub trait Iterator {
/// let a = [1, 2, 3, 4, 5];
/// let mut it = a.iter();
/// assert_eq!(it.find(|&x| *x == 3).unwrap(), &3);
/// assert_eq!(it.as_slice(), [4, 5]);
/// assert_eq!(&it[..], [4, 5]);
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
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 mut it = a.iter();
/// assert_eq!(it.position(|x| *x == 3).unwrap(), 2);
/// assert_eq!(it.as_slice(), [4, 5]);
/// assert_eq!(&it[..], [4, 5]);
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
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 mut it = a.iter();
/// assert_eq!(it.rposition(|x| *x == 2).unwrap(), 2);
/// assert_eq!(it.as_slice(), [1, 2]);
/// assert_eq!(&it[..], [1, 2]);
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
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.
///
/// Returns the rightmost element if the comparison determines two elements
/// to be equally maximum.
///
/// # Examples
///
/// ```
@ -732,16 +737,19 @@ pub trait Iterator {
#[stable(feature = "rust1", since = "1.0.0")]
fn max(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord
{
self.fold(None, |max, x| {
self.fold(None, |max, y| {
match max {
None => Some(x),
Some(y) => Some(cmp::max(x, y))
None => Some(y),
Some(x) => Some(cmp::max(x, y))
}
})
}
/// Consumes the entire iterator to return the minimum element.
///
/// Returns the leftmost element if the comparison determines two elements
/// to be equally minimum.
///
/// # Examples
///
/// ```
@ -752,10 +760,10 @@ pub trait Iterator {
#[stable(feature = "rust1", since = "1.0.0")]
fn min(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord
{
self.fold(None, |min, x| {
self.fold(None, |min, y| {
match min {
None => Some(x),
Some(y) => Some(cmp::min(x, y))
None => Some(y),
Some(x) => Some(cmp::min(x, y))
}
})
}
@ -771,7 +779,8 @@ pub trait Iterator {
/// element in the iterator and all elements are equal.
///
/// 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
///
@ -799,16 +808,17 @@ pub trait Iterator {
Some(x) => {
match self.next() {
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 {
// `first` and `second` are the two next elements we want to look at.
// We first compare `first` and `second` (#1). The smaller one is then compared to
// current minimum (#2). The larger one is compared to current maximum (#3). This
// way we do 3 comparisons for 2 elements.
// `first` and `second` are the two next elements we want to look
// at. We first compare `first` and `second` (#1). The smaller one
// is then compared to current minimum (#2). The larger one is
// compared to current maximum (#3). This way we do 3 comparisons
// for 2 elements.
let first = match self.next() {
None => break,
Some(x) => x
@ -817,19 +827,19 @@ pub trait Iterator {
None => {
if first < min {
min = first;
} else if first > max {
} else if first >= max {
max = first;
}
break;
}
Some(x) => x
};
if first < second {
if first < min {min = first;}
if max < second {max = second;}
if first <= second {
if first < min { min = first }
if second >= max { max = second }
} else {
if second < min {min = second;}
if max < first {max = first;}
if second < min { min = second }
if first >= max { max = first }
}
}
@ -839,6 +849,9 @@ pub trait Iterator {
/// Return the element that gives the maximum value from the
/// specified function.
///
/// Returns the rightmost element if the comparison determines two elements
/// to be equally maximum.
///
/// # Examples
///
/// ```
@ -854,14 +867,14 @@ pub trait Iterator {
Self: Sized,
F: FnMut(&Self::Item) -> B,
{
self.fold(None, |max: Option<(Self::Item, B)>, x| {
let x_val = f(&x);
self.fold(None, |max: Option<(Self::Item, B)>, y| {
let y_val = f(&y);
match max {
None => Some((x, x_val)),
Some((y, y_val)) => if x_val > y_val {
Some((x, x_val))
} else {
None => Some((y, y_val)),
Some((x, x_val)) => if y_val >= x_val {
Some((y, y_val))
} else {
Some((x, x_val))
}
}
}).map(|(x, _)| x)
@ -870,6 +883,9 @@ pub trait Iterator {
/// Return the element that gives the minimum value from the
/// specified function.
///
/// Returns the leftmost element if the comparison determines two elements
/// to be equally minimum.
///
/// # Examples
///
/// ```
@ -885,11 +901,11 @@ pub trait Iterator {
Self: Sized,
F: FnMut(&Self::Item) -> B,
{
self.fold(None, |min: Option<(Self::Item, B)>, x| {
let x_val = f(&x);
self.fold(None, |min: Option<(Self::Item, B)>, y| {
let y_val = f(&y);
match min {
None => Some((x, x_val)),
Some((y, y_val)) => if x_val < y_val {
None => Some((y, y_val)),
Some((x, x_val)) => if x_val <= y_val {
Some((x, x_val))
} else {
Some((y, y_val))
@ -927,10 +943,10 @@ pub trait Iterator {
/// # #![feature(core)]
/// let a = [(1, 2), (3, 4)];
/// let (left, right): (Vec<_>, Vec<_>) = a.iter().cloned().unzip();
/// assert_eq!([1, 3], left);
/// assert_eq!([2, 4], right);
/// assert_eq!(left, [1, 3]);
/// 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
FromA: Default + Extend<A>,
FromB: Default + Extend<B>,
@ -1027,7 +1043,8 @@ pub trait FromIterator<A> {
/// 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;
@ -1041,6 +1058,9 @@ pub trait FromIterator<A> {
}
/// 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")]
pub trait IntoIterator {
/// 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`
///
/// A `RandomAccessIterator` should be either infinite or a `DoubleEndedIterator`.
/// Calling `next()` or `next_back()` on a `RandomAccessIterator`
/// reduces the indexable range accordingly. That is, `it.idx(1)` will become `it.idx(0)`
/// after `it.next()` is called.
/// A `RandomAccessIterator` should be either infinite or a
/// `DoubleEndedIterator`. Calling `next()` or `next_back()` on a
/// `RandomAccessIterator` reduces the indexable range accordingly. That is,
/// `it.idx(1)` will become `it.idx(0)` after `it.next()` is called.
#[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 {
/// Return the number of indexable elements. At most `std::usize::MAX`
/// 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),
{}
#[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")]
impl<B, I: ExactSizeIterator, F> ExactSizeIterator for Map<I, F> where
F: FnMut(I::Item) -> B,
{}
#[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
#[derive(Clone)]
@ -1177,7 +1200,9 @@ impl<I> DoubleEndedIterator for Rev<I> where I: DoubleEndedIterator {
}
#[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]
fn indexable(&self) -> usize { self.iter.indexable() }
#[inline]
@ -1244,10 +1269,10 @@ pub trait MultiplicativeIterator<A> {
///
/// ```
/// # #![feature(core)]
/// use std::iter::{count, MultiplicativeIterator};
/// use std::iter::MultiplicativeIterator;
///
/// 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(1) == 1);
@ -1280,7 +1305,8 @@ impl_multiplicative! { usize, 1 }
impl_multiplicative! { f32, 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)]
#[unstable(feature = "core",
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
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)
}
impl<T: Clone> MinMaxResult<T> {
/// `into_option` creates an `Option` of type `(T,T)`. The returned `Option` has variant
/// `None` if and only if the `MinMaxResult` has variant `NoElements`. Otherwise variant
/// `Some(x,y)` is returned where `x <= y`. If `MinMaxResult` has variant `OneElement(x)`,
/// performing this operation will make one clone of `x`.
/// `into_option` creates an `Option` of type `(T,T)`. The returned `Option`
/// has variant `None` if and only if the `MinMaxResult` has variant
/// `NoElements`. Otherwise variant `Some(x,y)` is returned where `x <= y`.
/// If `MinMaxResult` has variant `OneElement(x)`, performing this operation
/// will make one clone of `x`.
///
/// # Examples
///
@ -2511,7 +2539,7 @@ impl<A: Step> RangeFrom<A> {
}
#[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
/// 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")]
impl<A> Iterator for StepBy<A, RangeFrom<A>> where
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]
#[derive(Clone)]
#[unstable(feature = "core",
reason = "likely to be replaced by range notation and adapters")]
#[allow(deprecated)]
pub struct RangeInclusive<A> {
range: Range<A>,
range: ops::Range<A>,
done: bool,
}
@ -2693,18 +2605,18 @@ pub struct RangeInclusive<A> {
#[inline]
#[unstable(feature = "core",
reason = "likely to be replaced by range notation and adapters")]
#[allow(deprecated)]
pub fn range_inclusive<A: Int>(start: A, stop: A) -> RangeInclusive<A> {
pub fn range_inclusive<A>(start: A, stop: A) -> RangeInclusive<A>
where A: Step + One + Clone
{
RangeInclusive {
range: range(start, stop),
range: start..stop,
done: false,
}
}
#[unstable(feature = "core",
reason = "likely to be replaced by range notation and adapters")]
#[allow(deprecated)]
impl<A: Int + ToPrimitive> Iterator for RangeInclusive<A> {
impl<A: Step + One + Clone> Iterator for RangeInclusive<A> {
type Item = A;
#[inline]
@ -2712,9 +2624,9 @@ impl<A: Int + ToPrimitive> Iterator for RangeInclusive<A> {
match self.range.next() {
Some(x) => Some(x),
None => {
if !self.done && self.range.state == self.range.stop {
if !self.done && self.range.start == self.range.end {
self.done = true;
Some(self.range.stop.clone())
Some(self.range.end.clone())
} else {
None
}
@ -2740,46 +2652,28 @@ impl<A: Int + ToPrimitive> Iterator for RangeInclusive<A> {
#[unstable(feature = "core",
reason = "likely to be replaced by range notation and adapters")]
#[allow(deprecated)]
impl<A: Int + ToPrimitive> DoubleEndedIterator for RangeInclusive<A> {
impl<A> DoubleEndedIterator for RangeInclusive<A>
where A: Step + One + Clone,
for<'a> &'a A: Sub<Output=A>
{
#[inline]
fn next_back(&mut self) -> Option<A> {
if self.range.stop > self.range.state {
let result = self.range.stop.clone();
self.range.stop = self.range.stop - self.range.one;
if self.range.end > self.range.start {
let result = self.range.end.clone();
self.range.end = &self.range.end - &A::one();
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;
Some(self.range.stop.clone())
Some(self.range.end.clone())
} else {
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")]
#[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;
#[inline]
@ -2882,13 +2776,13 @@ impl<A: Int> Iterator for RangeStepInclusive<A> {
macro_rules! range_exact_iter_impl {
($($t:ty)*) => ($(
#[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")]
#[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;
#[inline]
@ -2927,7 +2821,7 @@ range_exact_iter_impl!(usize u8 u16 u32 isize i8 i16 i32);
#[stable(feature = "rust1", since = "1.0.0")]
#[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>
{
#[inline]
@ -2943,7 +2837,7 @@ impl<A: Step + One + Clone> DoubleEndedIterator for ::ops::Range<A> where
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
impl<A: Step + One> Iterator for ::ops::RangeFrom<A> {
impl<A: Step + One> Iterator for ops::RangeFrom<A> {
type Item = A;
#[inline]

View File

@ -136,7 +136,6 @@ pub mod atomic;
pub mod cell;
pub mod char;
pub mod panicking;
pub mod finally;
pub mod iter;
pub mod option;
pub mod raw;

View File

@ -66,10 +66,10 @@ macro_rules! assert {
);
}
/// Asserts that two expressions are equal to each other, testing equality in
/// both directions.
/// Asserts that two expressions are equal to each other.
///
/// 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
///
@ -84,10 +84,8 @@ macro_rules! assert_eq {
($left:expr , $right:expr) => ({
match (&($left), &($right)) {
(left_val, right_val) => {
// check both directions of equality....
if !((*left_val == *right_val) &&
(*right_val == *left_val)) {
panic!("assertion failed: `(left == right) && (right == left)` \
if !(*left_val == *right_val) {
panic!("assertion failed: `(left == right)` \
(left: `{:?}`, right: `{:?}`)", *left_val, *right_val)
}
}
@ -156,7 +154,7 @@ macro_rules! debug_assert_eq {
/// 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_rules! try {
($e:expr) => ({
@ -233,7 +231,7 @@ macro_rules! writeln {
/// ```
/// # #![feature(core)]
/// 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 x < 3*i { return i-1; }
/// }

View File

@ -415,42 +415,6 @@ mod impls {
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
/// trait is implemented for all types. Its purpose is to ensure that
/// when you write a generic function that will employ reflection,
@ -487,9 +451,5 @@ pub struct InvariantType<T>;
pub trait Reflect : MarkerTrait {
}
#[cfg(stage0)]
impl<T> Reflect for T { }
#[cfg(not(stage0))]
impl Reflect for .. { }

View File

@ -173,11 +173,6 @@ pub unsafe fn zeroed<T>() -> T {
#[inline]
#[unstable(feature = "filling_drop")]
pub unsafe fn dropped<T>() -> T {
#[cfg(stage0)]
#[inline(always)]
unsafe fn dropped_impl<T>() -> T { zeroed() }
#[cfg(not(stage0))]
#[inline(always)]
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.
//
// 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;
#[cfg(not(stage0))] #[unstable(feature = "filling_drop")]
#[unstable(feature = "filling_drop")]
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);
#[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;
#[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;
#[cfg(stage0)] #[unstable(feature = "filling_drop")]
pub const POST_DROP_U8: u8 = 0;
#[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.
/// 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
/// transmuting `&T` to `&U` and then reading the `&U`. It will also unsafely create a copy of the
/// contained value instead of moving out of `src`.
/// This function will unsafely assume the pointer `src` is valid for
/// `sizeof(U)` bytes by transmuting `&T` to `&U` and then reading the `&U`. It
/// 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
/// to only invoke this function where `T` and `U` have the same size. This function triggers
/// undefined behavior if `U` is larger than `T`.
/// It is not a compile-time error if `T` and `U` have different sizes, but it
/// is highly encouraged to only invoke this function where `T` and `U` have the
/// same size. This function triggers undefined behavior if `U` is larger than
/// `T`.
///
/// # Examples
///

View File

@ -46,7 +46,7 @@ use str::{FromStr, StrExt};
/// intended to have wrapping semantics.
#[stable(feature = "rust1", since = "1.0.0")]
#[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")]
pub mod wrapping;

View File

@ -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::{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")]
#[deprecated(since = "1.0.0", reason = "moved to inherent methods")]
pub trait WrappingOps {
@ -43,6 +45,12 @@ pub trait OverflowingOps {
fn overflowing_add(self, rhs: Self) -> (Self, bool);
fn overflowing_sub(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 {
@ -184,6 +192,20 @@ macro_rules! wrapping_impl {
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 {
($($t:ident)*) => ($(
impl OverflowingOps for $t {
@ -205,6 +227,34 @@ macro_rules! overflowing_impl {
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)
}
}
#[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")]
@ -259,6 +329,26 @@ impl OverflowingOps for usize {
(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")]
@ -284,6 +374,26 @@ impl OverflowingOps for isize {
(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")]
@ -309,4 +419,24 @@ impl OverflowingOps for isize {
(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)
}
}

View File

@ -154,8 +154,6 @@ use mem;
use ops::FnOnce;
use result::Result::{Ok, Err};
use result::Result;
#[allow(deprecated)]
use slice::AsSlice;
use slice;
// 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
/////////////////////////////////////////////////////////////////////////////
#[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")]
impl<T> Default for Option<T> {
#[inline]

View File

@ -37,10 +37,11 @@ pub use char::CharExt;
pub use clone::Clone;
pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
pub use convert::{AsRef, AsMut, Into, From};
pub use iter::Extend;
pub use iter::{Iterator, DoubleEndedIterator};
pub use iter::{ExactSizeIterator};
pub use iter::{Iterator, DoubleEndedIterator, Extend, ExactSizeIterator};
pub use option::Option::{self, Some, None};
pub use result::Result::{self, Ok, Err};
pub use slice::{AsSlice, SliceExt};
pub use str::{Str, StrExt};
pub use slice::SliceExt;
pub use str::StrExt;
#[allow(deprecated)] pub use slice::AsSlice;
#[allow(deprecated)] pub use str::Str;

View File

@ -157,21 +157,6 @@ pub fn null<T>() -> *const T { 0 as *const T }
#[stable(feature = "rust1", since = "1.0.0")]
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
/// deinitialising either. They may overlap, unlike `mem::swap` which is
/// otherwise equivalent.

View File

@ -64,19 +64,6 @@ pub struct 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`.
///
/// This struct has the same layout as types like `&SomeTrait` and

View File

@ -88,10 +88,6 @@ pub trait SliceExt {
fn len(&self) -> usize;
fn is_empty(&self) -> bool { self.len() == 0 }
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 first_mut<'a>(&'a mut self) -> Option<&'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 }
}
#[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]
fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
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 })
}
/// 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
//

View File

@ -28,8 +28,6 @@ use iter::ExactSizeIterator;
use iter::{Map, Iterator, DoubleEndedIterator};
use marker::Sized;
use mem;
#[allow(deprecated)]
use num::Int;
use ops::{Fn, FnMut, FnOnce};
use option::Option::{self, None, Some};
use raw::{Repr, Slice};
@ -243,78 +241,6 @@ pub unsafe fn from_utf8_unchecked<'a>(v: &'a [u8]) -> &'a str {
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")]
impl Error for Utf8Error {
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> {
#[inline]
#[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>
where P::Searcher: ReverseSearcher<'a>;
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_any<'a>(&'a self) -> LinesAny<'a>;
fn char_len(&self) -> usize;
@ -1565,12 +1473,6 @@ impl StrExt for str {
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]
fn lines(&self) -> Lines {
Lines { inner: self.split_terminator('\n').0 }

View File

@ -8,10 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(deprecated) /* for CharEq */ ]
use prelude::*;
use super::CharEq;
// Pattern
@ -228,6 +225,40 @@ pub trait DoubleEndedSearcher<'a>: ReverseSearcher<'a> {}
// 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 CharEqSearcher<'a, C: CharEq> {
@ -425,65 +456,116 @@ fn str_search_step<F, G>(mut m: &mut StrSearcher,
}
}
macro_rules! associated_items {
($t:ty, $s:ident, $e:expr) => {
// FIXME: #22463
//type Searcher = $t;
fn into_searcher(self, haystack: &'a str) -> $t {
let $s = self;
$e.into_searcher(haystack)
macro_rules! char_eq_pattern_impl {
($wrapper:ty, $wrapper_ident:ident) => {
fn into_searcher(self, haystack: &'a str) -> $wrapper {
$wrapper_ident(CharEqPattern(self).into_searcher(haystack))
}
#[inline]
fn is_contained_in(self, haystack: &'a str) -> bool {
let $s = self;
$e.is_contained_in(haystack)
CharEqPattern(self).is_contained_in(haystack)
}
#[inline]
fn is_prefix_of(self, haystack: &'a str) -> bool {
let $s = self;
$e.is_prefix_of(haystack)
CharEqPattern(self).is_prefix_of(haystack)
}
// FIXME: #21750
/*#[inline]
#[inline]
fn is_suffix_of(self, haystack: &'a str) -> bool
where $t: ReverseSearcher<'a>
where $wrapper: ReverseSearcher<'a>
{
let $s = self;
$e.is_suffix_of(haystack)
}*/
CharEqPattern(self).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 {
type Searcher = <CharEqPattern<Self> as Pattern<'a>>::Searcher;
associated_items!(<CharEqPattern<Self> as Pattern<'a>>::Searcher,
s, CharEqPattern(s));
type Searcher = CharSearcher<'a>;
char_eq_pattern_impl!(CharSearcher<'a>, CharSearcher);
}
/// 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] {
type Searcher = <CharEqPattern<Self> as Pattern<'a>>::Searcher;
associated_items!(<CharEqPattern<Self> as Pattern<'a>>::Searcher,
s, CharEqPattern(s));
type Searcher = CharSliceSearcher<'a, 'b>;
char_eq_pattern_impl!(CharSliceSearcher<'a, 'b>, CharSliceSearcher);
}
/// 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 {
type Searcher = <&'b str as Pattern<'a>>::Searcher;
associated_items!(<&'b str as Pattern<'a>>::Searcher,
s, (*s));
}
/// Searches for chars that match the given predicate
impl<'a, F> Pattern<'a> for F where F: FnMut(char) -> bool {
type Searcher = <CharEqPattern<Self> as Pattern<'a>>::Searcher;
associated_items!(<CharEqPattern<Self> as Pattern<'a>>::Searcher,
s, CharEqPattern(s));
type Searcher = <&'b str as Pattern<'a>>::Searcher;
#[inline]
fn into_searcher(self, haystack: &'a str)
-> <&'b str as Pattern<'a>>::Searcher {
(*self).into_searcher(haystack)
}
#[inline]
fn is_contained_in(self, haystack: &'a str) -> bool {
(*self).is_contained_in(haystack)
}
#[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)
}
}

View File

@ -59,7 +59,6 @@ fn double_imm_borrow() {
fn no_mut_then_imm_borrow() {
let x = RefCell::new(0);
let _b1 = x.borrow_mut();
assert!(x.try_borrow().is_none());
assert_eq!(x.borrow_state(), BorrowState::Writing);
}
@ -67,7 +66,6 @@ fn no_mut_then_imm_borrow() {
fn no_imm_then_borrow_mut() {
let x = RefCell::new(0);
let _b1 = x.borrow();
assert!(x.try_borrow_mut().is_none());
assert_eq!(x.borrow_state(), BorrowState::Reading);
}
@ -76,7 +74,6 @@ fn no_double_borrow_mut() {
let x = RefCell::new(0);
assert_eq!(x.borrow_state(), BorrowState::Unused);
let _b1 = x.borrow_mut();
assert!(x.try_borrow_mut().is_none());
assert_eq!(x.borrow_state(), BorrowState::Writing);
}
@ -105,7 +102,7 @@ fn double_borrow_single_release_no_borrow_mut() {
{
let _b2 = x.borrow();
}
assert!(x.try_borrow_mut().is_none());
assert_eq!(x.borrow_state(), BorrowState::Reading);
}
#[test]
@ -122,14 +119,14 @@ fn clone_ref_updates_flag() {
let x = RefCell::new(0);
{
let b1 = x.borrow();
assert!(x.try_borrow_mut().is_none());
assert_eq!(x.borrow_state(), BorrowState::Reading);
{
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]

View File

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

View File

@ -72,7 +72,7 @@ fn test_multi_iter() {
#[test]
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);
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());
let ys = count(30, 10).take(4);
let ys = (30..).step_by(10).take(4);
let it = xs.iter().cloned().chain(ys);
let mut i = 0;
for x in it {
@ -102,7 +102,7 @@ fn test_iterator_chain() {
#[test]
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 });
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() {
let xs = [0, 3, 6];
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;
for x in it {
assert_eq!(x, ys[i]);
@ -291,13 +291,13 @@ fn test_unfoldr() {
#[test]
fn test_cycle() {
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));
for (i, x) in it.take(100).enumerate() {
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.next(), None);
}
@ -360,7 +360,7 @@ fn test_iterator_min() {
#[test]
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 v2 = &[10, 11, 12];
let vi = v.iter();

View File

@ -39,7 +39,6 @@ mod atomic;
mod cell;
mod char;
mod cmp;
mod finally;
mod fmt;
mod hash;
mod iter;

View File

@ -103,7 +103,7 @@ fn test_transmute() {
}
unsafe {
assert_eq!([76], transmute::<_, Vec<u8>>("L".to_string()));
assert_eq!(transmute::<_, Vec<u8>>("L".to_string()), [76]);
}
}

View File

@ -20,7 +20,7 @@ mod tests {
fn test_overflows() {
assert!(MAX > 0);
assert!(MIN <= 0);
assert!(MIN + MAX + 1 == 0);
assert!((MIN + MAX).wrapping_add(1) == 0);
}
#[test]

View File

@ -163,9 +163,9 @@ fn starts_short_long() {
#[test]
fn contains_weird_cases() {
assert!("* \t".contains_char(' '));
assert!(!"* \t".contains_char('?'));
assert!(!"* \t".contains_char('\u{1F4A9}'));
assert!("* \t".contains(' '));
assert!(!"* \t".contains('?'));
assert!(!"* \t".contains('\u{1F4A9}'));
}
#[test]
@ -347,11 +347,11 @@ malesuada sollicitudin quam eu fermentum!");
make_test!(chars_count, s, s.chars().count());
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!(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, {
use std::ascii::AsciiExt;
@ -368,11 +368,11 @@ malesuada sollicitudin quam eu fermentum!");
make_test!(find_underscore_char, s, s.find('_'));
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!(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_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!(rsplitn_space_char, s, s.rsplitn(10, ' ').count());
make_test!(split_str_space_str, s, s.split_str(" ").count());
make_test!(split_str_ad_str, s, s.split_str("ad").count());
make_test!(split_space_str, s, s.split(" ").count());
make_test!(split_ad_str, s, s.split("ad").count());
}

View File

@ -446,7 +446,7 @@ mod tests {
fn same(fmt: &'static str, p: &[Piece<'static>]) {
let parser = Parser::new(fmt);
assert!(p == parser.collect::<Vec<Piece<'static>>>());
assert!(parser.collect::<Vec<Piece<'static>>>() == p);
}
fn fmtdflt() -> FormatSpec<'static> {

View File

@ -84,7 +84,7 @@
//!
//! fn edges(&'a self) -> dot::Edges<'a,Ed> {
//! let &Edges(ref edges) = self;
//! edges.as_slice().into_cow()
//! (&edges[..]).into_cow()
//! }
//!
//! fn source(&self, e: &Ed) -> Nd { let &(s,_) = e; s }

View File

@ -198,7 +198,7 @@ impl Rand for ChaChaRng {
for word in &mut key {
*word = other.gen();
}
SeedableRng::from_seed(key.as_slice())
SeedableRng::from_seed(&key[..])
}
}

View File

@ -154,7 +154,7 @@ pub trait Rng : Sized {
///
/// let mut v = [0; 13579];
/// thread_rng().fill_bytes(&mut v);
/// println!("{:?}", v.as_slice());
/// println!("{:?}", &v[..]);
/// ```
fn fill_bytes(&mut self, dest: &mut [u8]) {
// 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 y = [1, 2, 3];
/// rng.shuffle(&mut y);
/// println!("{:?}", y.as_slice());
/// println!("{:?}", y);
/// rng.shuffle(&mut y);
/// println!("{:?}", y.as_slice());
/// println!("{:?}", y);
/// ```
fn shuffle<T>(&mut self, values: &mut [T]) {
let mut i = values.len();

View File

@ -123,7 +123,6 @@
html_root_url = "http://doc.rust-lang.org/nightly/",
html_playground_url = "http://play.rust-lang.org/")]
#![feature(io)]
#![feature(core)]
#![feature(rustc_private)]
#![feature(staged_api)]
@ -862,8 +861,8 @@ pub mod writer {
} else if 0x100 <= n && n < NUM_TAGS {
w.write_all(&[0xf0 | (n >> 8) as u8, n as u8])
} else {
Err(io::Error::new(io::ErrorKind::Other, "invalid tag",
Some(n.to_string())))
Err(io::Error::new(io::ErrorKind::Other,
&format!("invalid tag: {}", n)[..]))
}
}
@ -876,7 +875,7 @@ pub mod writer {
4 => w.write_all(&[0x10 | ((n >> 24) as u8), (n >> 16) as u8,
(n >> 8) as u8, n as u8]),
_ => 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 < 0x200000 { return write_sized_vuint(w, n, 3); }
if n < 0x10000000 { return write_sized_vuint(w, n, 4); }
Err(io::Error::new(io::ErrorKind::Other, "isize too big",
Some(n.to_string())))
Err(io::Error::new(io::ErrorKind::Other,
&format!("isize too big: {}", n)[..]))
}
impl<'a> Encoder<'a> {
@ -1077,8 +1076,8 @@ pub mod writer {
self.wr_tagged_raw_u32(EsSub32 as usize, v)
} else {
Err(io::Error::new(io::ErrorKind::Other,
"length or variant id too big",
Some(v.to_string())))
&format!("length or variant id too big: {}",
v)[..]))
}
}

View File

@ -68,6 +68,8 @@ register_diagnostics! {
E0019,
E0020,
E0022,
E0079, // enum variant: expected signed integer constant
E0080, // enum variant: constant evaluation error
E0109,
E0110,
E0133,
@ -128,7 +130,8 @@ register_diagnostics! {
E0313, // lifetime of borrowed pointer outlives lifetime of captured variable
E0314, // closure outlives stack frame
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 }

View File

@ -37,11 +37,9 @@
#![feature(unsafe_destructor)]
#![feature(staged_api)]
#![feature(std_misc)]
#![feature(io)]
#![feature(path_ext)]
#![feature(str_words)]
#![feature(str_char)]
#![feature(convert)]
#![feature(into_cow)]
#![feature(slice_patterns)]
#![cfg_attr(test, feature(test))]

View File

@ -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.id(id);
rbml_w.emit_ty(ecx, *ty);
@ -1884,7 +1884,7 @@ fn decode_side_tables(dcx: &DecodeContext,
let ty = val_dsr.read_ty(dcx);
debug!("inserting ty for node {}: {}",
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 => {
let item_substs = ty::ItemSubsts {

View File

@ -13,6 +13,8 @@
pub use self::const_val::*;
use self::ErrKind::*;
use metadata::csearch;
use middle::{astencode, def};
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::num::wrapping::OverflowingOps;
use std::num::ToPrimitive;
use std::cmp::Ordering;
use std::collections::hash_map::Entry::Vacant;
use std::{i8, i16, i32, i64};
@ -234,6 +237,7 @@ pub enum ErrKind {
NotOnStruct,
NotOnTuple,
NegateWithOverflow(i64),
AddiWithOverflow(i64, i64),
SubiWithOverflow(i64, i64),
MuliWithOverflow(i64, i64),
@ -244,6 +248,8 @@ pub enum ErrKind {
DivideWithOverflow,
ModuloByZero,
ModuloWithOverflow,
ShiftLeftWithOverflow,
ShiftRightWithOverflow,
MissingStructField,
NonConstPath,
ExpectedConstTuple,
@ -257,6 +263,7 @@ pub enum ErrKind {
impl ConstEvalErr {
pub fn description(&self) -> Cow<str> {
use self::ErrKind::*;
match self.kind {
CannotCast => "can't cast this type".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(),
NotOnTuple => "not on tuple".into_cow(),
NegateWithOverflow(..) => "attempted to negate with overflow".into_cow(),
AddiWithOverflow(..) => "attempted to add with overflow".into_cow(),
SubiWithOverflow(..) => "attempted to sub 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(),
ModuloByZero => "attempted remainder with a divisor of zero".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(),
NonConstPath => "non-constant path in constant expr".into_cow(),
ExpectedConstTuple => "expected constant tuple".into_cow(),
@ -297,57 +307,294 @@ impl ConstEvalErr {
}
}
macro_rules! signal {
($e:expr, $ctor:ident) => {
return Err(ConstEvalErr { span: $e.span, kind: ErrKind::$ctor })
};
pub type EvalResult = Result<const_val, ConstEvalErr>;
pub type CastResult = Result<const_val, ErrKind>;
($e:expr, $ctor:ident($($arg:expr),*)) => {
return Err(ConstEvalErr { span: $e.span, kind: ErrKind::$ctor($($arg),*) })
#[derive(Copy, Clone, PartialEq, Debug)]
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> {
let (ret, oflo) = a.overflowing_add(b);
if !oflo { Ok(const_int(ret)) } else { signal!(e, AddiWithOverflow(a, b)) }
}
fn checked_sub_int(e: &Expr, a: i64, b: i64) -> Result<const_val, ConstEvalErr> {
let (ret, oflo) = a.overflowing_sub(b);
if !oflo { Ok(const_int(ret)) } else { signal!(e, SubiWithOverflow(a, b)) }
}
fn checked_mul_int(e: &Expr, a: i64, b: i64) -> Result<const_val, ConstEvalErr> {
let (ret, oflo) = a.overflowing_mul(b);
if !oflo { Ok(const_int(ret)) } else { signal!(e, MuliWithOverflow(a, b)) }
impl UintTy {
pub fn from(tcx: &ty::ctxt, t: ast::UintTy) -> UintTy {
let t = if let ast::TyUs = t {
tcx.sess.target.uint_type
} else {
t
};
match t {
ast::TyUs => unreachable!(),
ast::TyU8 => UintTy::U8,
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> {
let (ret, oflo) = a.overflowing_add(b);
if !oflo { Ok(const_uint(ret)) } else { signal!(e, AdduWithOverflow(a, b)) }
}
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)) }
macro_rules! signal {
($e:expr, $exn:expr) => {
return Err(ConstEvalErr { span: $e.span, kind: $exn })
}
}
// 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>,
e: &Expr,
ty_hint: Option<Ty<'tcx>>)
-> Result<const_val, ConstEvalErr> {
ty_hint: Option<Ty<'tcx>>) -> EvalResult {
fn fromb(b: bool) -> const_val { const_int(b as i64) }
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 {
ast::ExprUnary(ast::UnNeg, ref inner) => {
match try!(eval_const_expr_partial(tcx, &**inner, ety)) {
const_float(f) => const_float(-f),
const_int(i) => const_int(-i),
const_uint(i) => const_uint(-i),
const_int(n) => try!(const_int_checked_neg(n, e, expr_int_type)),
const_uint(n) => try!(const_uint_checked_neg(n, e, expr_uint_type)),
const_str(_) => signal!(e, NegateOnString),
const_bool(_) => signal!(e, NegateOnBoolean),
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)) => {
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 {
ast::BiAdd => try!(checked_add_int(e, a, b)),
ast::BiSub => try!(checked_sub_int(e, a, b)),
ast::BiMul => try!(checked_mul_int(e, a, b)),
ast::BiDiv => {
if b == 0 {
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::BiAdd => try!(const_int_checked_add(a,b,e,expr_int_type)),
ast::BiSub => try!(const_int_checked_sub(a,b,e,expr_int_type)),
ast::BiMul => try!(const_int_checked_mul(a,b,e,expr_int_type)),
ast::BiDiv => try!(const_int_checked_div(a,b,e,expr_int_type)),
ast::BiRem => try!(const_int_checked_rem(a,b,e,expr_int_type)),
ast::BiAnd | ast::BiBitAnd => const_int(a & b),
ast::BiOr | ast::BiBitOr => const_int(a | b),
ast::BiBitXor => const_int(a ^ b),
ast::BiShl => const_int(a << b as usize),
ast::BiShr => const_int(a >> b as usize),
ast::BiShl => try!(const_int_checked_shl(a,b,e,expr_int_type)),
ast::BiShr => try!(const_int_checked_shr(a,b,e,expr_int_type)),
ast::BiEq => fromb(a == b),
ast::BiLt => 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)) => {
match op.node {
ast::BiAdd => try!(checked_add_uint(e, a, b)),
ast::BiSub => try!(checked_sub_uint(e, a, b)),
ast::BiMul => try!(checked_mul_uint(e, a, b)),
ast::BiDiv if b == 0 => signal!(e, DivideByZero),
ast::BiDiv => const_uint(a / b),
ast::BiRem if b == 0 => signal!(e, ModuloByZero),
ast::BiRem => const_uint(a % b),
ast::BiAdd => try!(const_uint_checked_add(a,b,e,expr_uint_type)),
ast::BiSub => try!(const_uint_checked_sub(a,b,e,expr_uint_type)),
ast::BiMul => try!(const_uint_checked_mul(a,b,e,expr_uint_type)),
ast::BiDiv => try!(const_uint_checked_div(a,b,e,expr_uint_type)),
ast::BiRem => try!(const_uint_checked_rem(a,b,e,expr_uint_type)),
ast::BiAnd | ast::BiBitAnd => const_uint(a & b),
ast::BiOr | ast::BiBitOr => const_uint(a | b),
ast::BiBitXor => const_uint(a ^ b),
ast::BiShl => const_uint(a << b as usize),
ast::BiShr => const_uint(a >> b as usize),
ast::BiShl => try!(const_uint_checked_shl(a,b,e,expr_uint_type)),
ast::BiShr => try!(const_uint_checked_shr(a,b,e,expr_uint_type)),
ast::BiEq => fromb(a == b),
ast::BiLt => 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
(const_int(a), const_uint(b)) => {
match op.node {
ast::BiShl => const_int(a << b as usize),
ast::BiShr => const_int(a >> b as usize),
ast::BiShl => try!(const_int_checked_shl_via_uint(a,b,e,expr_int_type)),
ast::BiShr => try!(const_int_checked_shr_via_uint(a,b,e,expr_int_type)),
_ => signal!(e, InvalidOpForIntUint(op.node)),
}
}
(const_uint(a), const_int(b)) => {
match op.node {
ast::BiShl => const_uint(a << b as usize),
ast::BiShr => const_uint(a >> b as usize),
ast::BiShl => try!(const_uint_checked_shl_via_int(a,b,e,expr_uint_type)),
ast::BiShr => try!(const_uint_checked_shr_via_int(a,b,e,expr_uint_type)),
_ => 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,
"target type not found for const cast")
});
// 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 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,
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)
}
fn cast_const(val: const_val, ty: Ty) -> Result<const_val, ErrKind> {
macro_rules! define_casts {
($($ty_pat:pat => (
$intermediate_ty:ty,
$const_type:ident,
$target_ty:ty
)),*) => (match ty.sty {
$($ty_pat => {
match val {
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),
})
fn cast_const<'tcx>(tcx: &ty::ctxt<'tcx>, val: const_val, ty: Ty) -> CastResult {
macro_rules! convert_val {
($intermediate_ty:ty, $const_type:ident, $target_ty:ty) => {
match val {
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))),
}
}
}
define_casts!{
ty::ty_int(ast::TyIs) => (isize, const_int, i64),
ty::ty_int(ast::TyI8) => (i8, const_int, i64),
ty::ty_int(ast::TyI16) => (i16, const_int, i64),
ty::ty_int(ast::TyI32) => (i32, const_int, i64),
ty::ty_int(ast::TyI64) => (i64, const_int, i64),
ty::ty_uint(ast::TyUs) => (usize, const_uint, u64),
ty::ty_uint(ast::TyU8) => (u8, const_uint, u64),
ty::ty_uint(ast::TyU16) => (u16, const_uint, u64),
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)
// Issue #23890: If isize/usize, then dispatch to appropriate target representation type
match (&ty.sty, tcx.sess.target.int_type, tcx.sess.target.uint_type) {
(&ty::ty_int(ast::TyIs), ast::TyI32, _) => return convert_val!(i32, const_int, i64),
(&ty::ty_int(ast::TyIs), ast::TyI64, _) => return convert_val!(i64, const_int, i64),
(&ty::ty_int(ast::TyIs), _, _) => panic!("unexpected target.int_type"),
(&ty::ty_uint(ast::TyUs), _, ast::TyU32) => return convert_val!(u32, const_uint, u64),
(&ty::ty_uint(ast::TyUs), _, ast::TyU64) => return convert_val!(u64, const_uint, u64),
(&ty::ty_uint(ast::TyUs), _, _) => panic!("unexpected target.uint_type"),
_ => {}
}
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),
}
}

View File

@ -68,11 +68,12 @@ use util::nodemap::FnvHashMap;
use arena::TypedArena;
use std::borrow::{Borrow, Cow};
use std::cell::{Cell, RefCell};
use std::cell::{Cell, RefCell, Ref};
use std::cmp;
use std::fmt;
use std::hash::{Hash, SipHasher, Hasher};
use std::mem;
use std::num::ToPrimitive;
use std::ops;
use std::rc::Rc;
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::{StmtExpr, StmtSemi, StructField, UnnamedField, Visibility};
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::parse::token::{self, InternedString, special_idents};
use syntax::print::pprust;
use syntax::ptr::P;
use syntax::{ast, ast_map};
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
/// is not guaranteed to be populated until after typeck. See
/// 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
/// 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>>,
}
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
// through the type during type construction, so that we can quickly
// 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)
-> Rc<Vec<Rc<VariantInfo<'tcx>>>> {
memoized(&cx.enum_var_cache, id, |id: ast::DefId| {
if ast::LOCAL_CRATE != id.krate {
Rc::new(csearch::get_enum_variants(cx, id))
} 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) {
ast_map::NodeItem(ref item) => {
match item.node {
ast::ItemEnum(ref enum_definition, _) => {
let mut last_discriminant: Option<Disr> = None;
Rc::new(enum_definition.variants.iter().map(|variant| {
let mut discriminant = INITIAL_DISCRIMINANT_VALUE;
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())
Rc::new(compute_enum_variants(
cx,
&enum_definition.variants,
lookup_repr_hints(cx, id).get(0)))
}
_ => {
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 {}",
found);
}
Err(_) => {
Err(err) => {
let err_description = err.description();
let found = match count_expr.node {
ast::ExprPath(None, ast::Path {
global: false,
ref segments,
..
}) if segments.len() == 1 =>
"variable",
format!("{}", "found variable"),
_ =>
"non-constant expression"
format!("but {}", err_description),
};
span_err!(tcx.sess, count_expr.span, E0307,
"expected constant integer for repeat count, found {}",
"expected constant integer for repeat count, {}",
found);
}
}

View File

@ -228,8 +228,9 @@ pub fn memoized<T, U, S, F>(cache: &RefCell<HashMap<T, U, S>>, arg: T, f: F) ->
#[cfg(unix)]
pub fn path2cstr(p: &Path) -> CString {
use std::os::unix::prelude::*;
use std::ffi::AsOsStr;
CString::new(p.as_os_str().as_bytes()).unwrap()
use std::ffi::OsStr;
let p: &OsStr = p.as_ref();
CString::new(p.as_bytes()).unwrap()
}
#[cfg(windows)]
pub fn path2cstr(p: &Path) -> CString {

View File

@ -9,6 +9,7 @@
// except according to those terms.
use std::io;
use std::env;
#[allow(deprecated)] use std::old_path::{self, GenericPath};
#[allow(deprecated)] use std::old_io;
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());
match old_realpath(&old) {
Ok(p) => Ok(PathBuf::from(p.as_str().unwrap())),
Err(e) => Err(io::Error::new(io::ErrorKind::Other,
"realpath error",
Some(e.to_string())))
Err(e) => Err(io::Error::new(io::ErrorKind::Other, e))
}
}
#[allow(deprecated)]
fn old_realpath(original: &old_path::Path) -> old_io::IoResult<old_path::Path> {
use std::old_io::fs;
use std::os;
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
if cfg!(windows) {

View File

@ -36,17 +36,13 @@
#![feature(collections)]
#![feature(core)]
#![feature(old_fs)]
#![feature(io)]
#![feature(old_io)]
#![feature(old_path)]
#![feature(os)]
#![feature(rustc_private)]
#![feature(staged_api)]
#![feature(rand)]
#![feature(path_ext)]
#![feature(std_misc)]
#![feature(step_by)]
#![feature(convert)]
#![cfg_attr(test, feature(test, rand))]
extern crate syntax;

View File

@ -14,7 +14,7 @@
#![allow(deprecated)] // to_be32
use std::iter::{range_step, repeat};
use std::iter::repeat;
use std::num::Int;
use std::slice::bytes::{MutableByteVector, copy_memory};
use serialize::hex::ToHex;
@ -368,7 +368,7 @@ impl Engine256State {
// Putting the message schedule inside the same loop as the round calculations allows for
// 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 + 17);
schedule_round!(t + 18);
@ -388,7 +388,7 @@ impl Engine256State {
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!(h, a, b, c, d, e, f, g, K32, t + 1);
sha2_round!(g, h, a, b, c, d, e, f, K32, t + 2);

View File

@ -47,9 +47,10 @@ pub fn get_sdk_root(sdk_name: &str) -> String {
Ok(String::from_utf8(output.stdout).unwrap())
} else {
let error = String::from_utf8(output.stderr);
let error = format!("process exit with error: {}",
error.unwrap());
Err(io::Error::new(io::ErrorKind::Other,
"process exit with error",
error.ok()))
&error[..]))
}
});

View File

@ -11,7 +11,7 @@
use std::env;
use std::io::{self, Error, ErrorKind};
use std::fs;
use std::path::{self, PathBuf, AsPath};
use std::path::{self, PathBuf, Path};
use std::rand::{thread_rng, Rng};
/// 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.
#[allow(deprecated)] // rand usage
pub fn new_in<P: AsPath + ?Sized>(tmpdir: &P, prefix: &str)
-> io::Result<TempDir> {
pub fn new_in<P: AsRef<Path>>(tmpdir: P, prefix: &str)
-> io::Result<TempDir> {
let storage;
let mut tmpdir = tmpdir.as_path();
let mut tmpdir = tmpdir.as_ref();
if !tmpdir.is_absolute() {
let cur_dir = try!(env::current_dir());
storage = cur_dir.join(tmpdir);
@ -67,8 +67,7 @@ impl TempDir {
}
Err(Error::new(ErrorKind::AlreadyExists,
"too many temporary directories already exist",
None))
"too many temporary directories already exist"))
}
/// Attempts to make a temporary directory inside of `env::temp_dir()` whose

View File

@ -27,7 +27,6 @@
#![feature(box_syntax)]
#![feature(collections)]
#![feature(core)]
#![feature(libc)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
@ -35,10 +34,8 @@
#![feature(unsafe_destructor)]
#![feature(staged_api)]
#![feature(exit_status)]
#![feature(io)]
#![feature(set_stdio)]
#![feature(unicode)]
#![feature(convert)]
extern crate arena;
extern crate flate;

View File

@ -699,8 +699,8 @@ fn print_flowgraph<W: Write>(variants: Vec<borrowck_dot::Variant>,
fn expand_err_details(r: io::Result<()>) -> io::Result<()> {
r.map_err(|ioerr| {
io::Error::new(io::ErrorKind::Other, "graphviz::render failed",
Some(ioerr.to_string()))
io::Error::new(io::ErrorKind::Other,
&format!("graphviz::render failed: {}", ioerr)[..])
})
}
}

View File

@ -808,12 +808,11 @@ fn walk_ty() {
let tup2_ty = ty::mk_tup(tcx, vec!(tup1_ty, tup1_ty, uint_ty));
let uniq_ty = ty::mk_uniq(tcx, tup2_ty);
let walked: Vec<_> = uniq_ty.walk().collect();
assert_eq!([uniq_ty,
tup2_ty,
tup1_ty, int_ty, uint_ty, int_ty, uint_ty,
tup1_ty, int_ty, uint_ty, int_ty, uint_ty,
uint_ty],
walked);
assert_eq!(walked, [uniq_ty,
tup2_ty,
tup1_ty, int_ty, uint_ty, int_ty, uint_ty,
tup1_ty, int_ty, uint_ty, int_ty, uint_ty,
uint_ty]);
})
}

View File

@ -42,8 +42,9 @@ impl ArchiveRO {
#[cfg(unix)]
fn path2cstr(p: &Path) -> CString {
use std::os::unix::prelude::*;
use std::ffi::AsOsStr;
CString::new(p.as_os_str().as_bytes()).unwrap()
use std::ffi::OsStr;
let p: &OsStr = p.as_ref();
CString::new(p.as_bytes()).unwrap()
}
#[cfg(windows)]
fn path2cstr(p: &Path) -> CString {

View File

@ -30,7 +30,6 @@
#![feature(libc)]
#![feature(link_args)]
#![feature(staged_api)]
#![cfg_attr(unix, feature(std_misc))]
extern crate libc;
#[macro_use] #[no_link] extern crate rustc_bitflags;
@ -1976,6 +1975,7 @@ extern {
pub fn LLVMIsAArgument(value_ref: ValueRef) -> ValueRef;
pub fn LLVMIsAAllocaInst(value_ref: ValueRef) -> ValueRef;
pub fn LLVMIsAConstantInt(value_ref: ValueRef) -> ValueRef;
pub fn LLVMInitializeX86TargetInfo();
pub fn LLVMInitializeX86Target();

View File

@ -39,7 +39,6 @@
#![feature(unicode)]
#![feature(path_ext)]
#![feature(fs)]
#![feature(convert)]
#![feature(path_relative_from)]
#![allow(trivial_casts)]

View File

@ -272,7 +272,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
let typ =
ppaux::ty_to_string(
&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
// variable name, but who knows?)
self.fmt.formal_str(p.span,
@ -436,7 +436,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
let typ =
ppaux::ty_to_string(
&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) {
Some(sub_span) => self.fmt.field_str(field.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 {
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());
// Get the span only for the name of the variable (I hope the path
// is only ever a variable name, but who knows?).

View File

@ -41,7 +41,7 @@ use middle::cfg;
use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
use middle::weak_lang_items;
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::Session;
use trans::_match;
@ -52,7 +52,7 @@ use trans::callee;
use trans::cleanup::CleanupMethods;
use trans::cleanup;
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::{CrateContext, ExternMap, FunctionContext};
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);
(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: {}",
ty_to_string(cx.tcx(), rhs_t)));

View File

@ -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 {
unsafe {
llvm::LLVMIsUndef(val) != False

View File

@ -14,6 +14,14 @@ use llvm;
use llvm::{ConstFCmp, ConstICmp, SetLinkage, SetUnnamedAddr};
use llvm::{InternalLinkage, ValueRef, Bool, True};
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::base::{self, push_ctxt};
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 tsize = machine::llsize_of_alloc(cx, llty);
if csize != tsize {
cx.sess().abort_if_errors();
unsafe {
// FIXME these values could use some context
llvm::LLVMDumpValue(llconst);
@ -348,6 +357,100 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
(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>,
e: &ast::Expr,
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 (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 {
ast::BiAdd => {
@ -416,8 +520,12 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
ast::BiBitXor => llvm::LLVMConstXor(te1, te2),
ast::BiBitAnd => llvm::LLVMConstAnd(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 => {
let te2 = base::cast_shift_const_rhs(b.node, te1, te2);
if signed { llvm::LLVMConstAShr(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) => {
let (te, ty) = const_expr(cx, &**e, param_substs);
ast::ExprUnary(u, ref inner_e) => {
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);
match u {
ast::UnUniq | ast::UnDeref => {
@ -661,11 +772,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
ast::ExprRepeat(ref elem, ref count) => {
let unit_ty = ty::sequence_element_type(cx.tcx(), ety);
let llunitty = type_of::type_of(cx, unit_ty);
let n = match const_eval::eval_const_expr_partial(cx.tcx(), &**count, None) {
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 n = ty::eval_repeat_count(cx.tcx(), count);
let unit_val = const_expr(cx, &**elem, param_substs).0;
let vs: Vec<_> = repeat(unit_val).take(n).collect();
if val_ty(unit_val) != llunitty {

View File

@ -3207,7 +3207,7 @@ fn fn_should_be_ignored(fcx: &FunctionContext) -> bool {
fn assert_type_for_node_id(cx: &CrateContext,
node_id: ast::NodeId,
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,
"debuginfo: Could not find type for node id!");
}

View File

@ -85,7 +85,7 @@ use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv, PathParamMode};
use check::_match::pat_ctxt;
use fmt_macros::{Parser, Piece, Position};
use middle::astconv_util::{check_path_args, NO_TPS, NO_REGIONS};
use middle::{const_eval, def};
use middle::def;
use middle::infer;
use middle::mem_categorization as mc;
use middle::mem_categorization::McResult;
@ -94,7 +94,7 @@ use middle::privacy::{AllPublic, LastMod};
use middle::region::{self, CodeExtent};
use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace};
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::{self, HasProjectionTypes, RegionEscape, ToPolyTraitRef, Ty};
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>,
vs: &'tcx [P<ast::Variant>],
id: ast::NodeId,
hint: attr::ReprAttr)
-> Vec<Rc<ty::VariantInfo<'tcx>>> {
hint: attr::ReprAttr) {
#![allow(trivial_numeric_casts)]
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 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 {
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
// 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
};
let def_id = local_def(id);
match v.node.disr_expr {
Some(ref e) => {
debug!("disr expr, checking {}", pprust::expr_to_string(&**e));
// ty::enum_variants guards against discriminant overflows, so
// we need not check for that.
let variants = ty::enum_variants(ccx.tcx, def_id);
let inh = static_inherited_fields(ccx);
let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
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 => ()
};
for (v, variant) in vs.iter().zip(variants.iter()) {
let current_disr_val = variant.disr_val;
// Check for duplicate discriminant values
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);
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 })
@ -4396,10 +4350,7 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
};
}
let variants = 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));
do_check(ccx, vs, id, hint);
check_representable(ccx.tcx, sp, id, "enum");

View File

@ -215,25 +215,21 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
match traits::orphan_check(self.tcx, def_id) {
Ok(()) => { }
Err(traits::OrphanCheckErr::NoLocalInputType) => {
if !ty::has_attr(self.tcx, trait_def_id, "old_orphan_check") {
span_err!(
self.tcx.sess, item.span, E0117,
"the impl does not reference any \
types defined in this crate; \
only traits defined in the current crate can be \
implemented for arbitrary types");
return;
}
span_err!(
self.tcx.sess, item.span, E0117,
"the impl does not reference any \
types defined in this crate; \
only traits defined in the current crate can be \
implemented for arbitrary types");
return;
}
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,
"type parameter `{}` must be used as the type parameter for \
some local type (e.g. `MyStruct<T>`); only traits defined in \
the current crate can be implemented for a type parameter",
param_ty.user_string(self.tcx));
return;
}
span_err!(self.tcx.sess, item.span, E0210,
"type parameter `{}` must be used as the type parameter for \
some local type (e.g. `MyStruct<T>`); only traits defined in \
the current crate can be implemented for a type parameter",
param_ty.user_string(self.tcx));
return;
}
}

View File

@ -51,8 +51,6 @@ register_diagnostics! {
E0075,
E0076,
E0077,
E0079,
E0080,
E0081,
E0082,
E0083,

View File

@ -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>) {
debug!("write_ty_to_tcx({}, {})", node_id, ppaux::ty_to_string(tcx, 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>,

View File

@ -20,7 +20,7 @@ pub use self::imp::Lock;
#[cfg(unix)]
mod imp {
use std::ffi::{AsOsStr, CString};
use std::ffi::{CString, OsStr};
use std::os::unix::prelude::*;
use std::path::Path;
use std::io;
@ -116,7 +116,8 @@ mod imp {
impl 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 {
libc::open(buf.as_ptr(), libc::O_RDWR | libc::O_CREAT,
libc::S_IRWXU)
@ -164,9 +165,9 @@ mod imp {
#[cfg(windows)]
mod imp {
use libc;
use std::ffi::AsOsStr;
use std::io;
use std::mem;
use std::ffi::OsStr;
use std::os::windows::prelude::*;
use std::path::Path;
use std::ptr;
@ -194,7 +195,8 @@ mod imp {
impl 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);
let handle = unsafe {
libc::CreateFileW(p_16.as_ptr(),

View File

@ -23,7 +23,6 @@
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(collections)]
#![feature(core)]
#![feature(exit_status)]
#![feature(set_stdio)]
#![feature(libc)]
@ -36,7 +35,6 @@
#![feature(file_path)]
#![feature(path_ext)]
#![feature(path_relative_from)]
#![feature(convert)]
#![feature(slice_patterns)]
extern crate arena;

View File

@ -100,7 +100,7 @@
//! let encoded = json::encode(&object).unwrap();
//!
//! // 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" }
}
impl std::error::FromError<fmt::Error> for EncoderError {
fn from_error(err: fmt::Error) -> EncoderError { EncoderError::FmtError(err) }
impl From<fmt::Error> for EncoderError {
fn from(err: fmt::Error) -> EncoderError { EncoderError::FmtError(err) }
}
pub type EncodeResult = Result<(), EncoderError>;

View File

@ -36,7 +36,6 @@ Core encoding and decoding interfaces.
#![feature(std_misc)]
#![feature(unicode)]
#![feature(str_char)]
#![feature(convert)]
#![cfg_attr(test, feature(test, old_io))]
// test harness access

View File

@ -1482,8 +1482,7 @@ impl<'a, K, V> Entry<'a, K, V> {
}
}
#[unstable(feature = "collections",
reason = "matches entry v3 specification, waiting for dust to settle")]
#[stable(feature = "rust1", since = "1.0.0")]
/// Ensures a value is in the entry by inserting the default if empty, and returns
/// a mutable reference to the value in the entry.
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",
reason = "matches entry v3 specification, waiting for dust to settle")]
#[stable(feature = "rust1", since = "1.0.0")]
/// 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.
pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {

View File

@ -1192,7 +1192,7 @@ mod test_set {
};
let v = hs.into_iter().collect::<Vec<char>>();
assert!(['a', 'b'] == v || ['b', 'a'] == v);
assert!(v == ['a', 'b'] || v == ['b', 'a']);
}
#[test]

View File

@ -15,7 +15,7 @@ use self::BucketState::*;
use clone::Clone;
use cmp;
use hash::{Hash, Hasher};
use iter::{Iterator, ExactSizeIterator, count};
use iter::{Iterator, ExactSizeIterator};
use marker::{Copy, Send, Sync, Sized, self};
use mem::{min_align_of, size_of};
use mem;

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