diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index f0aacc1460b..7fd09f9e1f5 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -18,7 +18,6 @@ #![feature(std_misc)] #![feature(test)] #![feature(path_ext)] -#![feature(convert)] #![feature(str_char)] #![deny(warnings)] diff --git a/src/doc/reference.md b/src/doc/reference.md index 0bc4414999d..b3d5ad3b55d 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -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){} fn bar(map1: HashMap, map2: hash_map::HashMap){} 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]); diff --git a/src/doc/trpl/SUMMARY.md b/src/doc/trpl/SUMMARY.md index d31348d667b..136e155b1af 100644 --- a/src/doc/trpl/SUMMARY.md +++ b/src/doc/trpl/SUMMARY.md @@ -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) diff --git a/src/doc/trpl/benchmark-tests.md b/src/doc/trpl/benchmark-tests.md new file mode 100644 index 00000000000..88796537593 --- /dev/null +++ b/src/doc/trpl/benchmark-tests.md @@ -0,0 +1,152 @@ +% Benchmark tests + +Rust supports benchmark tests, which can test the performance of your +code. Let's make our `src/lib.rs` look like this (comments elided): + +```{rust,ignore} +#![feature(test)] + +extern crate test; + +pub fn add_two(a: i32) -> i32 { + a + 2 +} + +#[cfg(test)] +mod tests { + use super::*; + use test::Bencher; + + #[test] + fn it_works() { + assert_eq!(4, add_two(2)); + } + + #[bench] + fn bench_add_two(b: &mut Bencher) { + b.iter(|| add_two(2)); + } +} +``` + +Note the `test` feature gate, which enables this unstable feature. + +We've imported the `test` crate, which contains our benchmarking support. +We have a new function as well, with the `bench` attribute. Unlike regular +tests, which take no arguments, benchmark tests take a `&mut Bencher`. This +`Bencher` provides an `iter` method, which takes a closure. This closure +contains the code we'd like to benchmark. + +We can run benchmark tests with `cargo bench`: + +```bash +$ cargo bench + Compiling adder v0.0.1 (file:///home/steve/tmp/adder) + Running target/release/adder-91b3e234d4ed382a + +running 2 tests +test tests::it_works ... ignored +test tests::bench_add_two ... bench: 1 ns/iter (+/- 0) + +test result: ok. 0 passed; 0 failed; 1 ignored; 1 measured +``` + +Our non-benchmark test was ignored. You may have noticed that `cargo bench` +takes a bit longer than `cargo test`. This is because Rust runs our benchmark +a number of times, and then takes the average. Because we're doing so little +work in this example, we have a `1 ns/iter (+/- 0)`, but this would show +the variance if there was one. + +Advice on writing benchmarks: + + +* Move setup code outside the `iter` loop; only put the part you want to measure inside +* Make the code do "the same thing" on each iteration; do not accumulate or change state +* Make the outer function idempotent too; the benchmark runner is likely to run + it many times +* Make the inner `iter` loop short and fast so benchmark runs are fast and the + calibrator can adjust the run-length at fine resolution +* Make the code in the `iter` loop do something simple, to assist in pinpointing + performance improvements (or regressions) + +## Gotcha: optimizations + +There's another tricky part to writing benchmarks: benchmarks compiled with +optimizations activated can be dramatically changed by the optimizer so that +the benchmark is no longer benchmarking what one expects. For example, the +compiler might recognize that some calculation has no external effects and +remove it entirely. + +```{rust,ignore} +#![feature(test)] + +extern crate test; +use test::Bencher; + +#[bench] +fn bench_xor_1000_ints(b: &mut Bencher) { + b.iter(|| { + (0..1000).fold(0, |old, new| old ^ new); + }); +} +``` + +gives the following results + +```text +running 1 test +test bench_xor_1000_ints ... bench: 0 ns/iter (+/- 0) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured +``` + +The benchmarking runner offers two ways to avoid this. Either, the closure that +the `iter` method receives can return an arbitrary value which forces the +optimizer to consider the result used and ensures it cannot remove the +computation entirely. This could be done for the example above by adjusting the +`b.iter` call to + +```rust +# struct X; +# impl X { fn iter(&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(&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. diff --git a/src/doc/trpl/concurrency.md b/src/doc/trpl/concurrency.md index 79cb3117c0e..6b814a68542 100644 --- a/src/doc/trpl/concurrency.md +++ b/src/doc/trpl/concurrency.md @@ -280,13 +280,15 @@ it returns an `Result`, 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 diff --git a/src/doc/trpl/iterators.md b/src/doc/trpl/iterators.md index 8d7b1c3bd83..55776bee3b5 100644 --- a/src/doc/trpl/iterators.md +++ b/src/doc/trpl/iterators.md @@ -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); } ``` diff --git a/src/doc/trpl/macros.md b/src/doc/trpl/macros.md index 7da36043f6c..7e19ec94ee7 100644 --- a/src/doc/trpl/macros.md +++ b/src/doc/trpl/macros.md @@ -37,7 +37,7 @@ number of elements. ```rust let x: Vec = 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 = { 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]); # } ``` diff --git a/src/doc/trpl/ownership.md b/src/doc/trpl/ownership.md index f4b5495ba63..223085cc40b 100644 --- a/src/doc/trpl/ownership.md +++ b/src/doc/trpl/ownership.md @@ -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. diff --git a/src/doc/trpl/testing.md b/src/doc/trpl/testing.md index 8b2c14526cb..fddb4c19031 100644 --- a/src/doc/trpl/testing.md +++ b/src/doc/trpl/testing.md @@ -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(&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(&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. diff --git a/src/doc/trpl/traits.md b/src/doc/trpl/traits.md index 1e44076a430..341c90a7087 100644 --- a/src/doc/trpl/traits.md +++ b/src/doc/trpl/traits.md @@ -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 + +You’ve seen that you can bound a generic type parameter with a trait: + +```rust +fn foo(x: T) { + x.clone(); +} +``` + +If you need more than one bound, you can use `+`: + +```rust +use std::fmt::Debug; + +fn foo(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 diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 9b37ddc7ab5..855c86f08e7 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -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 /// }); diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index f9bd0ab2f1e..550b25ac3a7 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -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 Hash for Box { } } -/// 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` have been fixed ")] -// FIXME(#18737): this should be a direct impl on `Box`. If you're -// removing this please make sure that you can downcase on -// `Box` as well as `Box` -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(self) -> Result, Box>; -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl BoxAny for Box { +impl Box { #[inline] - fn downcast(self) -> Result, Box> { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn downcast(self) -> Result, Box> { if self.is::() { unsafe { // Get the raw representation of the trait object @@ -267,10 +255,10 @@ impl BoxAny for Box { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl BoxAny for Box { +impl Box { #[inline] - fn downcast(self) -> Result, Box> { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn downcast(self) -> Result, Box> { >::downcast(self) } } @@ -322,8 +310,48 @@ impl DoubleEndedIterator for Box { impl ExactSizeIterator for Box {} #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, E: Error + 'a> FromError for Box { - fn from_error(err: E) -> Box { +impl<'a, E: Error + 'a> From for Box { + fn from(err: E) -> Box { Box::new(err) } } + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, E: Error + Send + 'a> From for Box { + fn from(err: E) -> Box { + Box::new(err) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b> From<&'b str> for Box { + fn from(err: &'b str) -> Box { + #[derive(Debug)] + struct StringError(Box); + 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` 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(), + }))) + } + } +} diff --git a/src/liballoc/boxed_test.rs b/src/liballoc/boxed_test.rs index bb1ff9428a7..682d5f407c4 100644 --- a/src/liballoc/boxed_test.rs +++ b/src/liballoc/boxed_test.rs @@ -17,7 +17,6 @@ use core::clone::Clone; use std::boxed; use std::boxed::Box; -use std::boxed::BoxAny; #[test] fn test_owned_clone() { diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index 3ed8ca2bea9..8874ac6eb87 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -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. /// diff --git a/src/libcollections/borrow.rs b/src/libcollections/borrow.rs index 88d59f699d1..2fe769b73f5 100644 --- a/src/libcollections/borrow.rs +++ b/src/libcollections/borrow.rs @@ -40,6 +40,24 @@ use self::Cow::*; #[stable(feature = "rust1", since = "1.0.0")] pub trait Borrow { /// Immutably borrow from an owned value. + /// + /// # Examples + /// + /// ``` + /// use std::borrow::Borrow; + /// + /// fn check>(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 { #[stable(feature = "rust1", since = "1.0.0")] pub trait BorrowMut : Borrow { /// Mutably borrow from an owned value. + /// + /// # Examples + /// + /// ``` + /// use std::borrow::BorrowMut; + /// + /// fn check>(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 ::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) -> ::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")] diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index e1d007f0ac4..adfb284dabe 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -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 V>(self, default: F) -> &'a mut V { diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index c769b3df37f..7658611d809 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -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")] diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs index 52da4902b75..dbdb7956573 100644 --- a/src/libcollections/linked_list.rs +++ b/src/libcollections/linked_list.rs @@ -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 { @@ -252,6 +248,7 @@ impl LinkedList { /// } /// println!("{}", b.len()); // prints 0 /// ``` + #[stable(feature = "rust1", since = "1.0.0")] pub fn append(&mut self, other: &mut LinkedList) { match self.list_tail.resolve() { None => { @@ -844,7 +841,7 @@ impl ExactSizeIterator for IntoIter {} #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for LinkedList { fn from_iter>(iter: T) -> LinkedList { - 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::>()); + assert_eq!(a, &n.iter().collect::>()[..]); }).join().ok().unwrap(); } diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 050997f2dd3..4599aff000d 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -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] { 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] { /// ```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] { 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] { /// ```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] { 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 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 diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 9ddf8988f1e..f8f2909291f 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -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 { - 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::>(); /// 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::>(); /// 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::>(); /// 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")] diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index dbf214a712b..d8d7ad9887a 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -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> 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] diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 3595288a6c9..087b065031f 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -389,7 +389,7 @@ impl Vec { /// 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 Vec { } } + /// 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 Vec { /// # #![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 Extend for Vec { } __impl_slice_eq1! { Vec, Vec } -__impl_slice_eq2! { Vec, &'b [B] } -__impl_slice_eq2! { Vec, &'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, Clone } +__impl_slice_eq1! { Vec, &'b [B] } +__impl_slice_eq1! { Vec, &'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, Clone } macro_rules! array_impls { ($($N: expr)+) => { $( // NOTE: some less important impls are omitted to reduce code bloat - __impl_slice_eq2! { Vec, [B; $N] } - __impl_slice_eq2! { Vec, &'b [B; $N] } - // __impl_slice_eq2! { Vec, &'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, [B; $N] } + __impl_slice_eq1! { Vec, &'b [B; $N] } + // __impl_slice_eq1! { Vec, &'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 AsRef> for Vec { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Into> for Vec { - fn into(self) -> Vec { - self - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl AsRef<[T]> for Vec { fn as_ref(&self) -> &[T] { @@ -1679,11 +1679,6 @@ impl<'a> From<&'a str> for Vec { // 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 for Cow<'a, [T]> where T: Clone { fn from_iter>(it: I) -> Cow<'a, [T]> { diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 392e5092e3b..49b0c229215 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -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 VecDeque { /// buf.push_back(3); /// buf.push_back(4); /// let b: &[_] = &[&5, &3, &4]; - /// assert_eq!(buf.iter().collect::>().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 { @@ -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; diff --git a/src/libcollectionstest/bit/set.rs b/src/libcollectionstest/bit/set.rs index 4b4995d5fa7..19ea25ee345 100644 --- a/src/libcollectionstest/bit/set.rs +++ b/src/libcollectionstest/bit/set.rs @@ -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); diff --git a/src/libcollectionstest/enum_set.rs b/src/libcollectionstest/enum_set.rs index f04367147cb..a748541fca5 100644 --- a/src/libcollectionstest/enum_set.rs +++ b/src/libcollectionstest/enum_set.rs @@ -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] diff --git a/src/libcollectionstest/fmt.rs b/src/libcollectionstest/fmt.rs index 9a9aa71b58b..70e21c65a18 100644 --- a/src/libcollectionstest/fmt.rs +++ b/src/libcollectionstest/fmt.rs @@ -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!"); } diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs index f03a073e274..456c658a9c6 100644 --- a/src/libcollectionstest/lib.rs +++ b/src/libcollectionstest/lib.rs @@ -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; diff --git a/src/libcollectionstest/slice.rs b/src/libcollectionstest/slice.rs index 4168fe88a4b..041d9fba57c 100644 --- a/src/libcollectionstest/slice.rs +++ b/src/libcollectionstest/slice.rs @@ -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); diff --git a/src/libcollectionstest/str.rs b/src/libcollectionstest/str.rs index 5cfa8009054..ed9ee0206b7 100644 --- a/src/libcollectionstest/str.rs +++ b/src/libcollectionstest/str.rs @@ -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() { + fn t>() { let s: S = Default::default(); - assert_eq!(s.as_slice(), ""); + assert_eq!(s.as_ref(), ""); } t::<&str>(); diff --git a/src/libcollectionstest/string.rs b/src/libcollectionstest/string.rs index 4768d5e92ac..5d6aa8ac0dc 100644 --- a/src/libcollectionstest/string.rs +++ b/src/libcollectionstest/string.rs @@ -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 = "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 = "ศไทย中华Việt Nam".into_cow(); assert_eq!(String::from_utf8_lossy(xs), ys); let xs = b"Hello\xC2 There\xFF Goodbye"; diff --git a/src/libcollectionstest/vec_deque.rs b/src/libcollectionstest/vec_deque.rs index fe752d5a7e1..12323286f6b 100644 --- a/src/libcollectionstest/vec_deque.rs +++ b/src/libcollectionstest/vec_deque.rs @@ -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); diff --git a/src/libcore/any.rs b/src/libcore/any.rs index d3bc07b173a..0ffc4a229b5 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -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() -> TypeId { TypeId { t: unsafe { intrinsics::type_id::() }, diff --git a/src/libcore/atomic.rs b/src/libcore/atomic.rs index 91b4b46ac39..8c396a4e7fb 100644 --- a/src/libcore/atomic.rs +++ b/src/libcore/atomic.rs @@ -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, -} - -#[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, -} - -#[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) } - } -} diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 9e6dbce0325..906c87f3ffd 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -343,23 +343,6 @@ impl RefCell { } } - /// 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> { - 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 RefCell { } } - /// 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> { - 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 diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 9b8b59ec8ce..efe1179621d 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -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 { /// 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: PartialEq { /// 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: PartialEq { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn min(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(v1: T, v2: T) -> T { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn max(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(v1: T, v2: T) -> Option { /// 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(v1: T, v2: T) -> Option { #[unstable(feature = "core")] pub fn partial_max(v1: T, v2: T) -> Option { 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 } } diff --git a/src/libcore/cmp_macros.rs b/src/libcore/cmp_macros.rs index 18357bac9e6..95dab3d165a 100644 --- a/src/libcore/cmp_macros.rs +++ b/src/libcore/cmp_macros.rs @@ -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 { + impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq { #[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 { - #[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 { diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 21f9b1f5513..4a99f1a756a 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -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 { /// 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 { /// 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: 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 { /// Perform the conversion. + #[stable(feature = "rust1", since = "1.0.0")] fn from(T) -> Self; } @@ -48,14 +55,8 @@ pub trait From { // GENERIC IMPLS //////////////////////////////////////////////////////////////////////////////// -// As implies Into -impl<'a, T: ?Sized, U: ?Sized> Into<&'a U> for &'a T where T: AsRef { - 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 for &'a T where T: AsRef { fn as_ref(&self) -> &U { >::as_ref(*self) @@ -63,6 +64,7 @@ impl<'a, T: ?Sized, U: ?Sized> AsRef for &'a T where T: AsRef { } // As lifts over &mut +#[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: ?Sized, U: ?Sized> AsRef for &'a mut T where T: AsRef { fn as_ref(&self) -> &U { >::as_ref(*self) @@ -77,14 +79,8 @@ impl<'a, T: ?Sized, U: ?Sized> AsRef for &'a mut T where T: AsRef { // } // } -// AsMut implies Into -impl<'a, T: ?Sized, U: ?Sized> Into<&'a mut U> for &'a mut T where T: AsMut { - 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 for &'a mut T where T: AsMut { fn as_mut(&mut self) -> &mut U { (*self).as_mut() @@ -100,28 +96,38 @@ impl<'a, T: ?Sized, U: ?Sized> AsMut for &'a mut T where T: AsMut { // } // From implies Into +#[stable(feature = "rust1", since = "1.0.0")] impl Into for T where U: From { fn into(self) -> U { U::from(self) } } +// From (and thus Into) is reflexive +#[stable(feature = "rust1", since = "1.0.0")] +impl From for T { + fn from(t: T) -> T { t } +} + //////////////////////////////////////////////////////////////////////////////// // CONCRETE IMPLS //////////////////////////////////////////////////////////////////////////////// +#[stable(feature = "rust1", since = "1.0.0")] impl AsRef<[T]> for [T] { fn as_ref(&self) -> &[T] { self } } +#[stable(feature = "rust1", since = "1.0.0")] impl AsMut<[T]> for [T] { fn as_mut(&mut self) -> &mut [T] { self } } +#[stable(feature = "rust1", since = "1.0.0")] impl AsRef for str { fn as_ref(&self) -> &str { self diff --git a/src/libcore/error.rs b/src/libcore/error.rs index 9430aa00668..24035b7d9a8 100644 --- a/src/libcore/error.rs +++ b/src/libcore/error.rs @@ -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 for MyError { -//! fn from_error(err: io::Error) -> MyError { MyError::Io(err) } -//! } -//! -//! impl FromError 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 { - /// 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 FromError for E { - fn from_error(err: E) -> E { - err - } -} diff --git a/src/libcore/finally.rs b/src/libcore/finally.rs deleted file mode 100644 index 93a7d2bb17b..00000000000 --- a/src/libcore/finally.rs +++ /dev/null @@ -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 or the MIT license -// , 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 { - /// Executes this object, unconditionally running `dtor` after this block of - /// code has run. - fn finally(&mut self, dtor: F) -> T where F: FnMut(); -} - -impl Finally for F where F: FnMut() -> T { - fn finally(&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(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); - } -} diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index e65fbac926b..6820a7025fc 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -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; diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 43cf64bf3ad..0e91eafce18 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -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; /// Create a value initialized to zero. diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 44d48f9f4bf..2d69eeb9fa9 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -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; /// 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) { (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(self, mut f: F) -> (B, B) where Self: Sized, B: Default + Extend, @@ -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

(&mut self, mut predicate: P) -> Option 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

(&mut self, mut predicate: P) -> Option 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

(&mut self, mut predicate: P) -> Option 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 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 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(self) -> (FromA, FromB) where FromA: Default + Extend, FromB: Default + Extend, @@ -1027,7 +1043,8 @@ pub trait FromIterator { /// 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 { } /// 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 ExactSizeIterator for Inspect where F: FnMut(&I::Item), {} #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Rev where I: ExactSizeIterator + DoubleEndedIterator {} +impl ExactSizeIterator for Rev + where I: ExactSizeIterator + DoubleEndedIterator {} #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Map where F: FnMut(I::Item) -> B, {} #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Zip where A: ExactSizeIterator, B: ExactSizeIterator {} +impl ExactSizeIterator for Zip + where A: ExactSizeIterator, B: ExactSizeIterator {} /// An double-ended iterator with the direction inverted #[derive(Clone)] @@ -1177,7 +1200,9 @@ impl DoubleEndedIterator for Rev where I: DoubleEndedIterator { } #[unstable(feature = "core", reason = "trait is experimental")] -impl RandomAccessIterator for Rev where I: DoubleEndedIterator + RandomAccessIterator { +impl RandomAccessIterator for Rev + where I: DoubleEndedIterator + RandomAccessIterator +{ #[inline] fn indexable(&self) -> usize { self.iter.indexable() } #[inline] @@ -1244,10 +1269,10 @@ pub trait MultiplicativeIterator { /// /// ``` /// # #![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 { /// 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 MinMaxResult { - /// `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 RangeFrom { } #[allow(deprecated)] -impl ::ops::Range { +impl ops::Range { /// Creates an iterator with the same range, but stepping by the /// given amount at each iteration. /// @@ -2544,26 +2572,6 @@ impl ::ops::Range { } } -/// 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 = StepBy>; - -/// 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(start: A, step: A) -> Counter { - StepBy { - range: RangeFrom { start: start }, - step_by: step, - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for StepBy> where A: Clone, @@ -2584,108 +2592,12 @@ impl Iterator for StepBy> 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 { - 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(start: A, stop: A) -> Range { - 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 Iterator for Range { - type Item = A; - - #[inline] - fn next(&mut self) -> Option { - 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) { - // 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 DoubleEndedIterator for Range { - #[inline] - fn next_back(&mut self) -> Option { - 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 { - range: Range, + range: ops::Range, done: bool, } @@ -2693,18 +2605,18 @@ pub struct RangeInclusive { #[inline] #[unstable(feature = "core", reason = "likely to be replaced by range notation and adapters")] -#[allow(deprecated)] -pub fn range_inclusive(start: A, stop: A) -> RangeInclusive { +pub fn range_inclusive(start: A, stop: A) -> RangeInclusive + 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 Iterator for RangeInclusive { +impl Iterator for RangeInclusive { type Item = A; #[inline] @@ -2712,9 +2624,9 @@ impl Iterator for RangeInclusive { 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 Iterator for RangeInclusive { #[unstable(feature = "core", reason = "likely to be replaced by range notation and adapters")] -#[allow(deprecated)] -impl DoubleEndedIterator for RangeInclusive { +impl DoubleEndedIterator for RangeInclusive + where A: Step + One + Clone, + for<'a> &'a A: Sub +{ #[inline] fn next_back(&mut self) -> Option { - 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 = StepBy>; - -/// 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(start: A, stop: A, step: A) -> RangeStep { - StepBy { - step_by: step, - range: ::ops::Range { start: start, end: stop }, - } -} - #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] -impl Iterator for StepBy> { +impl Iterator for StepBy> { type Item = A; #[inline] @@ -2882,13 +2776,13 @@ impl Iterator for RangeStepInclusive { 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 Iterator for ::ops::Range { +impl Iterator for ops::Range { 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 DoubleEndedIterator for ::ops::Range where +impl DoubleEndedIterator for ops::Range where for<'a> &'a A: Sub<&'a A, Output = A> { #[inline] @@ -2943,7 +2837,7 @@ impl DoubleEndedIterator for ::ops::Range where #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] -impl Iterator for ::ops::RangeFrom { +impl Iterator for ops::RangeFrom { type Item = A; #[inline] diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index cf5cb0c2f5e..5e8b7fba1f1 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -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; diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index d5a7c1d6b26..751bd7353e4 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -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`. #[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; } /// } diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 3f4b39da4b3..f755c912fcd 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -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`")] -#[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>`")] -#[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`")] -#[lang="contravariant_type"] -pub struct ContravariantType; - -/// Old-style marker trait. Deprecated. -#[unstable(feature = "core", reason = "deprecated")] -#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData`")] -#[lang="covariant_type"] -pub struct CovariantType; - -/// Old-style marker trait. Deprecated. -#[unstable(feature = "core", reason = "deprecated")] -#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData>`")] -#[lang="invariant_type"] -pub struct InvariantType; - /// 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; pub trait Reflect : MarkerTrait { } -#[cfg(stage0)] -impl Reflect for T { } - -#[cfg(not(stage0))] impl Reflect for .. { } diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 98e8668239b..249beb6295c 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -173,11 +173,6 @@ pub unsafe fn zeroed() -> T { #[inline] #[unstable(feature = "filling_drop")] pub unsafe fn dropped() -> T { - #[cfg(stage0)] - #[inline(always)] - unsafe fn dropped_impl() -> T { zeroed() } - - #[cfg(not(stage0))] #[inline(always)] unsafe fn dropped_impl() -> 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 /// diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 64f8e7055a5..a4829ed96b3 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -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(pub T); +pub struct Wrapping(#[stable(feature = "rust1", since = "1.0.0")] pub T); #[unstable(feature = "core", reason = "may be removed or relocated")] pub mod wrapping; diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs index bda05a3d9e8..a78eed8ae5f 100644 --- a/src/libcore/num/wrapping.rs +++ b/src/libcore/num/wrapping.rs @@ -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) + } } diff --git a/src/libcore/option.rs b/src/libcore/option.rs index c5102ede29f..6db7c9bd99d 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -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 Option { // 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 AsSlice for Option { - /// Convert from `Option` 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 Default for Option { #[inline] diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index 448b90c0dbd..e60bc494081 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -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; diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 41a70ef708f..ff51e25fcbf 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -157,21 +157,6 @@ pub fn null() -> *const T { 0 as *const T } #[stable(feature = "rust1", since = "1.0.0")] pub fn null_mut() -> *mut T { 0 as *mut T } -/// Zeroes out `count * size_of::` 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(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. diff --git a/src/libcore/raw.rs b/src/libcore/raw.rs index 8502a9c53c4..47d1f3a1a3c 100644 --- a/src/libcore/raw.rs +++ b/src/libcore/raw.rs @@ -64,19 +64,6 @@ pub struct Slice { impl Copy for Slice {} -/// 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 diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 223a0bdae36..d8856130fab 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -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 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 // diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index f9e2b47d9b6..934c4515614 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -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 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 } diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs index 98b6533980d..922ab2c14a6 100644 --- a/src/libcore/str/pattern.rs +++ b/src/libcore/str/pattern.rs @@ -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 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); struct CharEqSearcher<'a, C: CharEq> { @@ -425,65 +456,116 @@ fn str_search_step(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 = as Pattern<'a>>::Searcher; - associated_items!( 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 = as Pattern<'a>>::Searcher; - associated_items!( 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 = as Pattern<'a>>::Searcher; - associated_items!( 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) + } } diff --git a/src/libcoretest/cell.rs b/src/libcoretest/cell.rs index fff3cc14ead..85dd1039003 100644 --- a/src/libcoretest/cell.rs +++ b/src/libcoretest/cell.rs @@ -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] diff --git a/src/libcoretest/finally.rs b/src/libcoretest/finally.rs deleted file mode 100644 index 2a48395271d..00000000000 --- a/src/libcoretest/finally.rs +++ /dev/null @@ -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 or the MIT license -// , 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); -} diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index 15938a5dcb4..af80d347f02 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -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 = 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::>(), [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(); diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs index 9cc3063dee6..7ae0dcbb5f9 100644 --- a/src/libcoretest/lib.rs +++ b/src/libcoretest/lib.rs @@ -39,7 +39,6 @@ mod atomic; mod cell; mod char; mod cmp; -mod finally; mod fmt; mod hash; mod iter; diff --git a/src/libcoretest/mem.rs b/src/libcoretest/mem.rs index fae36787c3d..5bc08376d25 100644 --- a/src/libcoretest/mem.rs +++ b/src/libcoretest/mem.rs @@ -103,7 +103,7 @@ fn test_transmute() { } unsafe { - assert_eq!([76], transmute::<_, Vec>("L".to_string())); + assert_eq!(transmute::<_, Vec>("L".to_string()), [76]); } } diff --git a/src/libcoretest/num/uint_macros.rs b/src/libcoretest/num/uint_macros.rs index 39e41a4fad3..e3eff6e7512 100644 --- a/src/libcoretest/num/uint_macros.rs +++ b/src/libcoretest/num/uint_macros.rs @@ -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] diff --git a/src/libcoretest/str.rs b/src/libcoretest/str.rs index 38cab4f0e09..c935b554574 100644 --- a/src/libcoretest/str.rs +++ b/src/libcoretest/str.rs @@ -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()); } diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 9b220409ef5..a7be6a7fcf0 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -446,7 +446,7 @@ mod tests { fn same(fmt: &'static str, p: &[Piece<'static>]) { let parser = Parser::new(fmt); - assert!(p == parser.collect::>>()); + assert!(parser.collect::>>() == p); } fn fmtdflt() -> FormatSpec<'static> { diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index b3a3f266a5e..74be96235d2 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -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 } diff --git a/src/librand/chacha.rs b/src/librand/chacha.rs index 91abb548d2e..44187a4fc99 100644 --- a/src/librand/chacha.rs +++ b/src/librand/chacha.rs @@ -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[..]) } } diff --git a/src/librand/lib.rs b/src/librand/lib.rs index 85f3c621c7e..15d3d981eb5 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -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(&mut self, values: &mut [T]) { let mut i = values.len(); diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs index 092cd780ec7..3e91b988770 100644 --- a/src/librbml/lib.rs +++ b/src/librbml/lib.rs @@ -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)[..])) } } diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 70303bb3410..0a29ed90ad4 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -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 } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index f31f8e8d4ce..b3ad96c4b5f 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -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))] diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 1ea632d9618..b6061f39233 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -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 { diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 0d9e0d14def..e3e5efc53c7 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -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 { 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; +pub type CastResult = Result; - ($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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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) -> 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) -> 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) -> 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) -> 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) -> 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) -> 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>) - -> Result { + ty_hint: Option>) -> 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 { - 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), } } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 161fae11ea6..6e81d14d73c 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -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>>, + node_types: RefCell>>, /// 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>, } +impl<'tcx> ctxt<'tcx> { + pub fn node_types(&self) -> Ref>> { 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; + fn u64_to_disr(&self, val: u64) -> Option; + fn disr_incr(&self, val: Disr) -> Option; + fn disr_string(&self, val: Disr) -> String; + fn disr_wrap_incr(&self, val: Option) -> 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 { + 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 { + 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 { + 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 { + 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], + opt_hint: Option<&attr::ReprAttr>) + -> Vec>> { + let mut variants: Vec> = Vec::new(); + let mut prev_disr_val: Option = 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>>> { 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 = 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); } } diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 60ae053dbaf..d71a68e2050 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -228,8 +228,9 @@ pub fn memoized(cache: &RefCell>, 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 { diff --git a/src/librustc_back/fs.rs b/src/librustc_back/fs.rs index 6d8891dd4fe..231f6ee3be6 100644 --- a/src/librustc_back/fs.rs +++ b/src/librustc_back/fs.rs @@ -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 { 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 { 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) { diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index fe457841e91..7591ebf67f8 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -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; diff --git a/src/librustc_back/sha2.rs b/src/librustc_back/sha2.rs index 8f0387059e4..898f20e7451 100644 --- a/src/librustc_back/sha2.rs +++ b/src/librustc_back/sha2.rs @@ -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); diff --git a/src/librustc_back/target/apple_ios_base.rs b/src/librustc_back/target/apple_ios_base.rs index 2fbbe7d1f7c..42cbdd7577d 100644 --- a/src/librustc_back/target/apple_ios_base.rs +++ b/src/librustc_back/target/apple_ios_base.rs @@ -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[..])) } }); diff --git a/src/librustc_back/tempdir.rs b/src/librustc_back/tempdir.rs index d4503ae7fc9..b12732f8794 100644 --- a/src/librustc_back/tempdir.rs +++ b/src/librustc_back/tempdir.rs @@ -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(tmpdir: &P, prefix: &str) - -> io::Result { + pub fn new_in>(tmpdir: P, prefix: &str) + -> io::Result { 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 diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 456d5f7a60a..be416327dad 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -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; diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 9e693a64ef0..fe55ca3b73b 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -699,8 +699,8 @@ fn print_flowgraph(variants: Vec, 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)[..]) }) } } diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index fcb0b9bdd3c..b0fc5fbcb50 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -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]); }) } diff --git a/src/librustc_llvm/archive_ro.rs b/src/librustc_llvm/archive_ro.rs index cc6a85e86ce..647f4bc6a40 100644 --- a/src/librustc_llvm/archive_ro.rs +++ b/src/librustc_llvm/archive_ro.rs @@ -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 { diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index c7b5b2e7534..cdafa4a16d0 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -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(); diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index a3ac0473bfa..b0eacd1a55d 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -39,7 +39,6 @@ #![feature(unicode)] #![feature(path_ext)] #![feature(fs)] -#![feature(convert)] #![feature(path_relative_from)] #![allow(trivial_casts)] diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index a415875d852..26fcf947e4f 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -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 { "".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?). diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 61e332f87ad..20677ab93fc 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -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))); diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index 745098d6e87..995f3caf588 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -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 { + unsafe { + if is_const_integral(v) { + Some(llvm::LLVMConstIntGetSExtValue(v)) + } else { + None + } + } +} + +pub fn const_to_opt_uint(v: ValueRef) -> Option { + unsafe { + if is_const_integral(v) { + Some(llvm::LLVMConstIntGetZExtValue(v)) + } else { + None + } + } +} + pub fn is_undef(val: ValueRef) -> bool { unsafe { llvm::LLVMIsUndef(val) != False diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index 0a9df2b5dc1..c32cb28ec78 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -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 { diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index f2c24501c66..8e9ae2eba0b 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -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!"); } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 16501ec2807..fbff4e84788 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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], id: ast::NodeId, - hint: attr::ReprAttr) - -> Vec>> { + hint: attr::ReprAttr) { #![allow(trivial_numeric_casts)] let rty = ty::node_id_to_type(ccx.tcx, id); - let mut variants: Vec> = Vec::new(); let mut disr_vals: Vec = Vec::new(); - let mut prev_disr_val: Option = 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"); diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index 7b76f3681c1..b450e6b398a 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -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`); 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`); only traits defined in \ + the current crate can be implemented for a type parameter", + param_ty.user_string(self.tcx)); + return; } } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 7d01bece01c..a8d93c8bd11 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -51,8 +51,6 @@ register_diagnostics! { E0075, E0076, E0077, - E0079, - E0080, E0081, E0082, E0083, diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 91410fa808c..9d6c04b1ad4 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -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>, diff --git a/src/librustdoc/flock.rs b/src/librustdoc/flock.rs index 8c85eaff23c..760fa329fd9 100644 --- a/src/librustdoc/flock.rs +++ b/src/librustdoc/flock.rs @@ -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(), diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 431cb4a2898..1ff3411f8fc 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -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; diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index 2d5d8cd501a..cdfe212bf23 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -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 for EncoderError { - fn from_error(err: fmt::Error) -> EncoderError { EncoderError::FmtError(err) } +impl From for EncoderError { + fn from(err: fmt::Error) -> EncoderError { EncoderError::FmtError(err) } } pub type EncodeResult = Result<(), EncoderError>; diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index b79323b3f96..2e86712c9bc 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -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 diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index bc0f109de15..a636c1a812d 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -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 V>(self, default: F) -> &'a mut V { diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 87380471c80..5fbc21797ab 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -1192,7 +1192,7 @@ mod test_set { }; let v = hs.into_iter().collect::>(); - assert!(['a', 'b'] == v || ['b', 'a'] == v); + assert!(v == ['a', 'b'] || v == ['b', 'a']); } #[test] diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index aa3195cbf01..053ceceb496 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -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; diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs index d8a95133d94..e76d5460eb0 100644 --- a/src/libstd/dynamic_lib.rs +++ b/src/libstd/dynamic_lib.rs @@ -18,7 +18,7 @@ use prelude::v1::*; use env; -use ffi::{AsOsStr, CString, OsString}; +use ffi::{CString, OsString}; use mem; use path::{Path, PathBuf}; @@ -190,7 +190,6 @@ mod dl { use ffi::{CStr, OsStr}; use str; use libc; - use os::unix::prelude::*; use ptr; pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> { diff --git a/src/libstd/env.rs b/src/libstd/env.rs index 71f072302fb..931cf46a58f 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -20,7 +20,7 @@ use prelude::v1::*; use iter::IntoIterator; use error::Error; -use ffi::{OsString, AsOsStr}; +use ffi::{OsStr, OsString}; use fmt; use io; use path::{Path, PathBuf}; @@ -176,7 +176,7 @@ impl Iterator for VarsOs { /// } /// ``` #[stable(feature = "env", since = "1.0.0")] -pub fn var(key: &K) -> Result where K: AsOsStr { +pub fn var(key: &K) -> Result where K: AsRef { match var_os(key) { Some(s) => s.into_string().map_err(VarError::NotUnicode), None => Err(VarError::NotPresent) @@ -198,9 +198,9 @@ pub fn var(key: &K) -> Result where K: AsOsStr { /// } /// ``` #[stable(feature = "env", since = "1.0.0")] -pub fn var_os(key: &K) -> Option where K: AsOsStr { +pub fn var_os(key: &K) -> Option where K: AsRef { let _g = ENV_LOCK.lock(); - os_imp::getenv(key.as_os_str()) + os_imp::getenv(key.as_ref()) } /// Possible errors from the `env::var` method. @@ -255,17 +255,30 @@ impl Error for VarError { /// ``` #[stable(feature = "env", since = "1.0.0")] pub fn set_var(k: &K, v: &V) - where K: AsOsStr, V: AsOsStr + where K: AsRef, V: AsRef { let _g = ENV_LOCK.lock(); - os_imp::setenv(k.as_os_str(), v.as_os_str()) + os_imp::setenv(k.as_ref(), v.as_ref()) } -/// Remove a variable from the environment entirely. +/// Remove an environment variable from the environment of the currently running process. +/// +/// # Examples +/// +/// ``` +/// use std::env; +/// +/// let key = "KEY"; +/// env::set_var(key, "VALUE"); +/// assert_eq!(env::var(key), Ok("VALUE".to_string())); +/// +/// env::remove_var(key); +/// assert!(env::var(key).is_err()); +/// ``` #[stable(feature = "env", since = "1.0.0")] -pub fn remove_var(k: &K) where K: AsOsStr { +pub fn remove_var(k: &K) where K: AsRef { let _g = ENV_LOCK.lock(); - os_imp::unsetenv(k.as_os_str()) + os_imp::unsetenv(k.as_ref()) } /// An iterator over `Path` instances for parsing an environment variable @@ -296,8 +309,8 @@ pub struct SplitPaths<'a> { inner: os_imp::SplitPaths<'a> } /// } /// ``` #[stable(feature = "env", since = "1.0.0")] -pub fn split_paths(unparsed: &T) -> SplitPaths { - SplitPaths { inner: os_imp::split_paths(unparsed.as_os_str()) } +pub fn split_paths + ?Sized>(unparsed: &T) -> SplitPaths { + SplitPaths { inner: os_imp::split_paths(unparsed.as_ref()) } } #[stable(feature = "env", since = "1.0.0")] @@ -327,7 +340,6 @@ pub struct JoinPathsError { /// # Examples /// /// ``` -/// # #![feature(convert)] /// use std::env; /// use std::path::PathBuf; /// @@ -340,7 +352,7 @@ pub struct JoinPathsError { /// ``` #[stable(feature = "env", since = "1.0.0")] pub fn join_paths(paths: I) -> Result - where I: IntoIterator, T: AsOsStr + where I: IntoIterator, T: AsRef { os_imp::join_paths(paths.into_iter()).map_err(|e| { JoinPathsError { inner: e } @@ -398,6 +410,19 @@ pub fn home_dir() -> Option { /// On Windows, returns the value of, in order, the 'TMP', 'TEMP', /// 'USERPROFILE' environment variable if any are set and not the empty /// string. Otherwise, tmpdir returns the path to the Windows directory. +/// +/// ``` +/// use std::env; +/// use std::fs::File; +/// +/// # fn foo() -> std::io::Result<()> { +/// let mut dir = env::temp_dir(); +/// dir.push("foo.txt"); +/// +/// let f = try!(File::create(dir)); +/// # Ok(()) +/// # } +/// ``` #[stable(feature = "env", since = "1.0.0")] pub fn temp_dir() -> PathBuf { os_imp::temp_dir() @@ -557,6 +582,7 @@ pub mod consts { #[stable(feature = "env", since = "1.0.0")] pub const ARCH: &'static str = super::arch::ARCH; + /// The family of the operating system. In this case, `unix`. #[stable(feature = "env", since = "1.0.0")] pub const FAMILY: &'static str = super::os::FAMILY; @@ -740,7 +766,7 @@ mod tests { let mut rng = rand::thread_rng(); let n = format!("TEST{}", rng.gen_ascii_chars().take(10) .collect::()); - let n = OsString::from_string(n); + let n = OsString::from(n); assert!(var_os(&n).is_none()); n } diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index a00f7708025..de91e5f3268 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -10,9 +10,9 @@ #![unstable(feature = "std_misc")] -use convert::Into; +use convert::{Into, From}; use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering}; -use error::{Error, FromError}; +use error::Error; use fmt; use io; use iter::Iterator; @@ -132,15 +132,6 @@ pub struct CStr { #[stable(feature = "rust1", since = "1.0.0")] pub struct NulError(usize, Vec); -/// A conversion trait used by the constructor of `CString` for types that can -/// be converted to a vector of bytes. -#[deprecated(since = "1.0.0", reason = "use std::convert::Into> instead")] -#[unstable(feature = "std_misc")] -pub trait IntoBytes { - /// Consumes this container, returning a vector of bytes. - fn into_bytes(self) -> Vec; -} - impl CString { /// Create a new C-compatible string from a container of bytes. /// @@ -178,57 +169,6 @@ impl CString { } } - /// Create a new C-compatible string from a byte slice. - /// - /// This method will copy the data of the slice provided into a new - /// allocation, ensuring that there is a trailing 0 byte. - /// - /// # Examples - /// - /// ```no_run - /// # #![feature(libc)] - /// extern crate libc; - /// use std::ffi::CString; - /// - /// extern { fn puts(s: *const libc::c_char); } - /// - /// fn main() { - /// let to_print = CString::new("Hello!").unwrap(); - /// unsafe { - /// puts(to_print.as_ptr()); - /// } - /// } - /// ``` - /// - /// # Panics - /// - /// This function will panic if the provided slice contains any - /// interior nul bytes. - #[unstable(feature = "std_misc")] - #[deprecated(since = "1.0.0", reason = "use CString::new instead")] - #[allow(deprecated)] - pub fn from_slice(v: &[u8]) -> CString { - CString::from_vec(v.to_vec()) - } - - /// Create a C-compatible string from a byte vector. - /// - /// This method will consume ownership of the provided vector, appending a 0 - /// byte to the end after verifying that there are no interior 0 bytes. - /// - /// # Panics - /// - /// This function will panic if the provided slice contains any - /// interior nul bytes. - #[unstable(feature = "std_misc")] - #[deprecated(since = "1.0.0", reason = "use CString::new instead")] - pub fn from_vec(v: Vec) -> CString { - match v.iter().position(|x| *x == 0) { - Some(i) => panic!("null byte found in slice at: {}", i), - None => unsafe { CString::from_vec_unchecked(v) }, - } - } - /// Create a C-compatible string from a byte vector without checking for /// interior 0 bytes. /// @@ -298,17 +238,17 @@ impl fmt::Display for NulError { } #[stable(feature = "rust1", since = "1.0.0")] -impl FromError for io::Error { - fn from_error(_: NulError) -> io::Error { +impl From for io::Error { + fn from(_: NulError) -> io::Error { io::Error::new(io::ErrorKind::InvalidInput, - "data provided contains a nul byte", None) + "data provided contains a nul byte") } } #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] -impl FromError for old_io::IoError { - fn from_error(_: NulError) -> old_io::IoError { +impl From for old_io::IoError { + fn from(_: NulError) -> old_io::IoError { old_io::IoError { kind: old_io::IoErrorKind::InvalidInput, desc: "data provided contains a nul byte", @@ -424,41 +364,6 @@ impl Ord for CStr { } } -/// Deprecated in favor of `CStr` -#[unstable(feature = "std_misc")] -#[deprecated(since = "1.0.0", reason = "use CStr::from_ptr(p).to_bytes() instead")] -pub unsafe fn c_str_to_bytes<'a>(raw: &'a *const libc::c_char) -> &'a [u8] { - let len = libc::strlen(*raw); - slice::from_raw_parts(*(raw as *const _ as *const *const u8), len as usize) -} - -/// Deprecated in favor of `CStr` -#[unstable(feature = "std_misc")] -#[deprecated(since = "1.0.0", - reason = "use CStr::from_ptr(p).to_bytes_with_nul() instead")] -pub unsafe fn c_str_to_bytes_with_nul<'a>(raw: &'a *const libc::c_char) - -> &'a [u8] { - let len = libc::strlen(*raw) + 1; - slice::from_raw_parts(*(raw as *const _ as *const *const u8), len as usize) -} - -#[allow(deprecated)] -impl<'a> IntoBytes for &'a str { - fn into_bytes(self) -> Vec { self.as_bytes().to_vec() } -} -#[allow(deprecated)] -impl<'a> IntoBytes for &'a [u8] { - fn into_bytes(self) -> Vec { self.to_vec() } -} -#[allow(deprecated)] -impl IntoBytes for String { - fn into_bytes(self) -> Vec { self.into_bytes() } -} -#[allow(deprecated)] -impl IntoBytes for Vec { - fn into_bytes(self) -> Vec { self } -} - #[cfg(test)] mod tests { use prelude::v1::*; diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs index f17dc654249..1b7e913d46c 100644 --- a/src/libstd/ffi/mod.rs +++ b/src/libstd/ffi/mod.rs @@ -13,17 +13,10 @@ #![stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")] -pub use self::c_str::{CString, CStr}; -pub use self::c_str::{NulError, IntoBytes}; -#[allow(deprecated)] -pub use self::c_str::c_str_to_bytes; -#[allow(deprecated)] -pub use self::c_str::c_str_to_bytes_with_nul; +pub use self::c_str::{CString, CStr, NulError}; #[stable(feature = "rust1", since = "1.0.0")] -pub use self::os_str::OsString; -#[stable(feature = "rust1", since = "1.0.0")] -pub use self::os_str::OsStr; +pub use self::os_str::{OsString, OsStr}; mod c_str; mod os_str; diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 49dbac4585b..ab20efe25eb 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -29,12 +29,13 @@ //! for conversion to/from various other string types. Eventually these types //! will offer a full-fledged string API. -#![unstable(feature = "os", +#![unstable(feature = "os_str", reason = "recently added as part of path/io reform")] use core::prelude::*; use borrow::{Borrow, Cow, ToOwned}; +use ffi::CString; use fmt::{self, Debug}; use mem; use string::String; @@ -42,6 +43,7 @@ use ops; use cmp; use hash::{Hash, Hasher}; use old_path::{Path, GenericPath}; +use vec::Vec; use sys::os_str::{Buf, Slice}; use sys_common::{AsInner, IntoInner, FromInner}; @@ -61,28 +63,43 @@ pub struct OsStr { } impl OsString { - /// Constructs an `OsString` at no cost by consuming a `String`. - #[stable(feature = "rust1", since = "1.0.0")] - #[deprecated(since = "1.0.0", reason = "use `from` instead")] - pub fn from_string(s: String) -> OsString { - OsString::from(s) - } - - /// Constructs an `OsString` by copying from a `&str` slice. - /// - /// Equivalent to: `OsString::from_string(String::from_str(s))`. - #[stable(feature = "rust1", since = "1.0.0")] - #[deprecated(since = "1.0.0", reason = "use `from` instead")] - pub fn from_str(s: &str) -> OsString { - OsString::from(s) - } - /// Constructs a new empty `OsString`. #[stable(feature = "rust1", since = "1.0.0")] pub fn new() -> OsString { OsString { inner: Buf::from_string(String::new()) } } + /// Construct an `OsString` from a byte sequence. + /// + /// # Platform behavior + /// + /// On Unix systems, any byte sequence can be successfully + /// converted into an `OsString`. + /// + /// On Windows system, only UTF-8 byte sequences will successfully + /// convert; non UTF-8 data will produce `None`. + #[unstable(feature = "convert", reason = "recently added")] + pub fn from_bytes(bytes: B) -> Option where B: Into> { + #[cfg(unix)] + fn from_bytes_inner(vec: Vec) -> Option { + use os::unix::ffi::OsStringExt; + Some(OsString::from_vec(vec)) + } + + #[cfg(windows)] + fn from_bytes_inner(vec: Vec) -> Option { + String::from_utf8(vec).ok().map(OsString::from) + } + + from_bytes_inner(bytes.into()) + } + + /// Convert to an `OsStr` slice. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn as_os_str(&self) -> &OsStr { + self + } + /// Convert the `OsString` into a `String` if it contains valid Unicode data. /// /// On failure, ownership of the original `OsString` is returned. @@ -91,13 +108,6 @@ impl OsString { self.inner.into_string().map_err(|buf| OsString { inner: buf} ) } - /// Extend the string with the given `&OsStr` slice. - #[deprecated(since = "1.0.0", reason = "renamed to `push`")] - #[unstable(feature = "os")] - pub fn push_os_str(&mut self, s: &OsStr) { - self.inner.push_slice(&s.inner) - } - /// Extend the string with the given `&OsStr` slice. #[stable(feature = "rust1", since = "1.0.0")] pub fn push>(&mut self, s: T) { @@ -211,8 +221,16 @@ impl Hash for OsString { } impl OsStr { + /// Coerce into an `OsStr` slice. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new + ?Sized>(s: &S) -> &OsStr { + s.as_ref() + } + /// Coerce directly from a `&str` slice to a `&OsStr` slice. #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated(since = "1.0.0", + reason = "use `OsStr::new` instead")] pub fn from_str(s: &str) -> &OsStr { unsafe { mem::transmute(Slice::from_str(s)) } } @@ -239,6 +257,36 @@ impl OsStr { OsString { inner: self.inner.to_owned() } } + /// Yield this `OsStr` as a byte slice. + /// + /// # Platform behavior + /// + /// On Unix systems, this is a no-op. + /// + /// On Windows systems, this returns `None` unless the `OsStr` is + /// valid unicode, in which case it produces UTF-8-encoded + /// data. This may entail checking validity. + #[unstable(feature = "convert", reason = "recently added")] + pub fn to_bytes(&self) -> Option<&[u8]> { + if cfg!(windows) { + self.to_str().map(|s| s.as_bytes()) + } else { + Some(self.bytes()) + } + } + + /// Create a `CString` containing this `OsStr` data. + /// + /// Fails if the `OsStr` contains interior nulls. + /// + /// This is a convenience for creating a `CString` from + /// `self.to_bytes()`, and inherits the platform behavior of the + /// `to_bytes` method. + #[unstable(feature = "convert", reason = "recently added")] + pub fn to_cstring(&self) -> Option { + self.to_bytes().and_then(|b| CString::new(b).ok()) + } + /// Get the underlying byte representation. /// /// Note: it is *crucial* that this API is private, to avoid @@ -258,14 +306,14 @@ impl PartialEq for OsStr { #[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for OsStr { fn eq(&self, other: &str) -> bool { - *self == *OsStr::from_str(other) + *self == *OsStr::new(other) } } #[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for str { fn eq(&self, other: &OsStr) -> bool { - *other == *OsStr::from_str(self) + *other == *OsStr::new(self) } } @@ -292,7 +340,7 @@ impl PartialOrd for OsStr { impl PartialOrd for OsStr { #[inline] fn partial_cmp(&self, other: &str) -> Option { - self.partial_cmp(OsStr::from_str(other)) + self.partial_cmp(OsStr::new(other)) } } @@ -359,7 +407,7 @@ impl AsOsStr for OsString { #[deprecated(since = "1.0.0", reason = "trait is deprecated")] impl AsOsStr for str { fn as_os_str(&self) -> &OsStr { - OsStr::from_str(self) + unsafe { mem::transmute(Slice::from_str(self)) } } } @@ -367,7 +415,7 @@ impl AsOsStr for str { #[deprecated(since = "1.0.0", reason = "trait is deprecated")] impl AsOsStr for String { fn as_os_str(&self) -> &OsStr { - OsStr::from_str(&self[..]) + unsafe { mem::transmute(Slice::from_str(self)) } } } @@ -388,14 +436,14 @@ impl AsRef for OsString { #[stable(feature = "rust1", since = "1.0.0")] impl AsRef for str { fn as_ref(&self) -> &OsStr { - OsStr::from_str(self) + unsafe { mem::transmute(Slice::from_str(self)) } } } #[stable(feature = "rust1", since = "1.0.0")] impl AsRef for String { fn as_ref(&self) -> &OsStr { - OsStr::from_str(&self[..]) + unsafe { mem::transmute(Slice::from_str(self)) } } } diff --git a/src/libstd/fs/mod.rs b/src/libstd/fs.rs similarity index 99% rename from src/libstd/fs/mod.rs rename to src/libstd/fs.rs index a3128ef0f8d..4f97ae8f69b 100644 --- a/src/libstd/fs/mod.rs +++ b/src/libstd/fs.rs @@ -25,11 +25,6 @@ use sys::fs2 as fs_imp; use sys_common::{AsInnerMut, FromInner, AsInner}; use vec::Vec; -#[allow(deprecated)] -pub use self::tempdir::TempDir; - -mod tempdir; - /// A reference to an open file on the filesystem. /// /// An instance of a `File` can be read and/or written depending on what options @@ -56,7 +51,7 @@ mod tempdir; #[stable(feature = "rust1", since = "1.0.0")] pub struct File { inner: fs_imp::File, - path: PathBuf, + path: Option, } /// Metadata information about a file. @@ -171,7 +166,7 @@ impl File { reason = "this abstraction is imposed by this library instead \ of the underlying OS and may be removed")] pub fn path(&self) -> Option<&Path> { - Some(&self.path) + self.path.as_ref().map(|p| &**p) } /// Attempt to sync all OS-internal metadata to disk. @@ -273,6 +268,12 @@ impl File { impl AsInner for File { fn as_inner(&self) -> &fs_imp::File { &self.inner } } +impl FromInner for File { + fn from_inner(f: fs_imp::File) -> File { + File { inner: f, path: None } + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Read for File { fn read(&mut self, buf: &mut [u8]) -> io::Result { @@ -381,7 +382,7 @@ impl OpenOptions { pub fn open>(&self, path: P) -> io::Result { let path = path.as_ref(); let inner = try!(fs_imp::File::open(path, &self.0)); - Ok(File { path: path.to_path_buf(), inner: inner }) + Ok(File { path: Some(path.to_path_buf()), inner: inner }) } } @@ -575,8 +576,7 @@ pub fn copy, Q: AsRef>(from: P, to: Q) -> io::Result { let to = to.as_ref(); if !from.is_file() { return Err(Error::new(ErrorKind::InvalidInput, - "the source path is not an existing file", - None)) + "the source path is not an existing file")) } let mut reader = try!(File::open(from)); @@ -1327,7 +1327,7 @@ mod tests { check!(fs::copy(&input, &out)); let mut v = Vec::new(); check!(check!(File::open(&out)).read_to_end(&mut v)); - assert_eq!(v.as_slice(), b"hello"); + assert_eq!(v, b"hello"); assert_eq!(check!(input.metadata()).permissions(), check!(out.metadata()).permissions()); @@ -1622,7 +1622,7 @@ mod tests { check!(check!(File::create(&tmpdir.join("test"))).write(&bytes)); let mut v = Vec::new(); check!(check!(File::open(&tmpdir.join("test"))).read_to_end(&mut v)); - assert!(v == bytes.as_slice()); + assert!(v == &bytes[..]); } #[test] diff --git a/src/libstd/fs/tempdir.rs b/src/libstd/fs/tempdir.rs deleted file mode 100644 index 8cc1dde98a0..00000000000 --- a/src/libstd/fs/tempdir.rs +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![unstable(feature = "tempdir", reason = "needs an RFC before stabilization")] -#![deprecated(since = "1.0.0", - reason = "use the `tempdir` crate from crates.io instead")] -#![allow(deprecated)] - -use prelude::v1::*; - -use env; -use io::{self, Error, ErrorKind}; -use fs; -use path::{self, PathBuf}; -use rand::{thread_rng, Rng}; - -/// A wrapper for a path to temporary directory implementing automatic -/// scope-based deletion. -pub struct TempDir { - path: Option, -} - -// How many times should we (re)try finding an unused random name? It should be -// enough that an attacker will run out of luck before we run out of patience. -const NUM_RETRIES: u32 = 1 << 31; -// How many characters should we include in a random file name? It needs to -// be enough to dissuade an attacker from trying to preemptively create names -// of that length, but not so huge that we unnecessarily drain the random number -// generator of entropy. -const NUM_RAND_CHARS: usize = 12; - -impl TempDir { - /// Attempts to make a temporary directory inside of `tmpdir` whose name - /// will have the prefix `prefix`. The directory will be automatically - /// deleted once the returned wrapper is destroyed. - /// - /// If no directory can be created, `Err` is returned. - #[allow(deprecated)] // rand usage - pub fn new_in>(tmpdir: P, prefix: &str) -> io::Result { - let storage; - let mut tmpdir = tmpdir.as_ref(); - if !tmpdir.is_absolute() { - let cur_dir = try!(env::current_dir()); - storage = cur_dir.join(tmpdir); - tmpdir = &storage; - // return TempDir::new_in(&cur_dir.join(tmpdir), prefix); - } - - let mut rng = thread_rng(); - for _ in 0..NUM_RETRIES { - let suffix: String = rng.gen_ascii_chars().take(NUM_RAND_CHARS).collect(); - let leaf = if prefix.len() > 0 { - format!("{}.{}", prefix, suffix) - } else { - // If we're given an empty string for a prefix, then creating a - // directory starting with "." would lead to it being - // semi-invisible on some systems. - suffix - }; - let path = tmpdir.join(&leaf); - match fs::create_dir(&path) { - Ok(_) => return Ok(TempDir { path: Some(path) }), - Err(ref e) if e.kind() == ErrorKind::AlreadyExists => {} - Err(e) => return Err(e) - } - } - - Err(Error::new(ErrorKind::AlreadyExists, - "too many temporary directories already exist", - None)) - } - - /// Attempts to make a temporary directory inside of `env::temp_dir()` whose - /// name will have the prefix `prefix`. The directory will be automatically - /// deleted once the returned wrapper is destroyed. - /// - /// If no directory can be created, `Err` is returned. - #[allow(deprecated)] - pub fn new(prefix: &str) -> io::Result { - TempDir::new_in(&env::temp_dir(), prefix) - } - - /// Unwrap the wrapped `std::path::Path` from the `TempDir` wrapper. - /// This discards the wrapper so that the automatic deletion of the - /// temporary directory is prevented. - pub fn into_path(mut self) -> PathBuf { - self.path.take().unwrap() - } - - /// Access the wrapped `std::path::Path` to the temporary directory. - pub fn path(&self) -> &path::Path { - self.path.as_ref().unwrap() - } - - /// Close and remove the temporary directory - /// - /// Although `TempDir` removes the directory on drop, in the destructor - /// any errors are ignored. To detect errors cleaning up the temporary - /// directory, call `close` instead. - pub fn close(mut self) -> io::Result<()> { - self.cleanup_dir() - } - - fn cleanup_dir(&mut self) -> io::Result<()> { - match self.path { - Some(ref p) => fs::remove_dir_all(p), - None => Ok(()) - } - } -} - -impl Drop for TempDir { - fn drop(&mut self) { - let _ = self.cleanup_dir(); - } -} - -// the tests for this module need to change the path using change_dir, -// and this doesn't play nicely with other tests so these unit tests are located -// in src/test/run-pass/tempfile.rs diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 8eea06bf6b0..6fe35614a85 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -16,7 +16,7 @@ use prelude::v1::*; use io::prelude::*; use cmp; -use error::{self, FromError}; +use error; use fmt; use io::{self, DEFAULT_BUF_SIZE, Error, ErrorKind}; use ptr; @@ -165,7 +165,7 @@ impl BufWriter { match self.inner.as_mut().unwrap().write(&self.buf[written..]) { Ok(0) => { ret = Err(Error::new(ErrorKind::WriteZero, - "failed to write the buffered data", None)); + "failed to write the buffered data")); break; } Ok(n) => written += n, @@ -264,8 +264,8 @@ impl IntoInnerError { } #[stable(feature = "rust1", since = "1.0.0")] -impl FromError> for Error { - fn from_error(iie: IntoInnerError) -> Error { iie.1 } +impl From> for Error { + fn from(iie: IntoInnerError) -> Error { iie.1 } } #[stable(feature = "rust1", since = "1.0.0")] @@ -503,34 +503,34 @@ mod tests { let mut buf = [0, 0, 0]; let nread = reader.read(&mut buf); - assert_eq!(Ok(3), nread); + assert_eq!(nread.unwrap(), 3); let b: &[_] = &[5, 6, 7]; assert_eq!(buf, b); let mut buf = [0, 0]; let nread = reader.read(&mut buf); - assert_eq!(Ok(2), nread); + assert_eq!(nread.unwrap(), 2); let b: &[_] = &[0, 1]; assert_eq!(buf, b); let mut buf = [0]; let nread = reader.read(&mut buf); - assert_eq!(Ok(1), nread); + assert_eq!(nread.unwrap(), 1); let b: &[_] = &[2]; assert_eq!(buf, b); let mut buf = [0, 0, 0]; let nread = reader.read(&mut buf); - assert_eq!(Ok(1), nread); + assert_eq!(nread.unwrap(), 1); let b: &[_] = &[3, 0, 0]; assert_eq!(buf, b); let nread = reader.read(&mut buf); - assert_eq!(Ok(1), nread); + assert_eq!(nread.unwrap(), 1); let b: &[_] = &[4, 0, 0]; assert_eq!(buf, b); - assert_eq!(reader.read(&mut buf), Ok(0)); + assert_eq!(reader.read(&mut buf).unwrap(), 0); } #[test] @@ -592,7 +592,7 @@ mod tests { } let mut stream = BufStream::new(S); - assert_eq!(stream.read(&mut [0; 10]), Ok(0)); + assert_eq!(stream.read(&mut [0; 10]).unwrap(), 0); stream.write(&[0; 10]).unwrap(); stream.flush().unwrap(); } @@ -658,10 +658,10 @@ mod tests { let in_buf: &[u8] = b"a\nb\nc"; let reader = BufReader::with_capacity(2, in_buf); let mut it = reader.lines(); - assert_eq!(it.next(), Some(Ok("a".to_string()))); - assert_eq!(it.next(), Some(Ok("b".to_string()))); - assert_eq!(it.next(), Some(Ok("c".to_string()))); - assert_eq!(it.next(), None); + assert_eq!(it.next().unwrap().unwrap(), "a".to_string()); + assert_eq!(it.next().unwrap().unwrap(), "b".to_string()); + assert_eq!(it.next().unwrap().unwrap(), "c".to_string()); + assert!(it.next().is_none()); } #[test] @@ -669,20 +669,20 @@ mod tests { let inner = ShortReader{lengths: vec![0, 1, 2, 0, 1, 0]}; let mut reader = BufReader::new(inner); let mut buf = [0, 0]; - assert_eq!(reader.read(&mut buf), Ok(0)); - assert_eq!(reader.read(&mut buf), Ok(1)); - assert_eq!(reader.read(&mut buf), Ok(2)); - assert_eq!(reader.read(&mut buf), Ok(0)); - assert_eq!(reader.read(&mut buf), Ok(1)); - assert_eq!(reader.read(&mut buf), Ok(0)); - assert_eq!(reader.read(&mut buf), Ok(0)); + assert_eq!(reader.read(&mut buf).unwrap(), 0); + assert_eq!(reader.read(&mut buf).unwrap(), 1); + assert_eq!(reader.read(&mut buf).unwrap(), 2); + assert_eq!(reader.read(&mut buf).unwrap(), 0); + assert_eq!(reader.read(&mut buf).unwrap(), 1); + assert_eq!(reader.read(&mut buf).unwrap(), 0); + assert_eq!(reader.read(&mut buf).unwrap(), 0); } #[test] fn read_char_buffered() { let buf = [195, 159]; let reader = BufReader::with_capacity(1, &buf[..]); - assert_eq!(reader.chars().next(), Some(Ok('ß'))); + assert_eq!(reader.chars().next().unwrap().unwrap(), 'ß'); } #[test] @@ -690,9 +690,9 @@ mod tests { let buf = [195, 159, b'a']; let reader = BufReader::with_capacity(1, &buf[..]); let mut it = reader.chars(); - assert_eq!(it.next(), Some(Ok('ß'))); - assert_eq!(it.next(), Some(Ok('a'))); - assert_eq!(it.next(), None); + assert_eq!(it.next().unwrap().unwrap(), 'ß'); + assert_eq!(it.next().unwrap().unwrap(), 'a'); + assert!(it.next().is_none()); } #[test] diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index d8e403376bd..6433c29bb9d 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -75,8 +75,7 @@ macro_rules! seek { if pos < 0 { Err(Error::new(ErrorKind::InvalidInput, - "invalid seek to a negative position", - None)) + "invalid seek to a negative position")) } else { self.pos = pos as u64; Ok(self.pos) @@ -172,9 +171,9 @@ mod tests { #[test] fn test_vec_writer() { let mut writer = Vec::new(); - assert_eq!(writer.write(&[0]), Ok(1)); - assert_eq!(writer.write(&[1, 2, 3]), Ok(3)); - assert_eq!(writer.write(&[4, 5, 6, 7]), Ok(4)); + assert_eq!(writer.write(&[0]).unwrap(), 1); + assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3); + assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4); let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7]; assert_eq!(writer, b); } @@ -182,9 +181,9 @@ mod tests { #[test] fn test_mem_writer() { let mut writer = Cursor::new(Vec::new()); - assert_eq!(writer.write(&[0]), Ok(1)); - assert_eq!(writer.write(&[1, 2, 3]), Ok(3)); - assert_eq!(writer.write(&[4, 5, 6, 7]), Ok(4)); + assert_eq!(writer.write(&[0]).unwrap(), 1); + assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3); + assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4); let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7]; assert_eq!(&writer.get_ref()[..], b); } @@ -195,16 +194,16 @@ mod tests { { let mut writer = Cursor::new(&mut buf[..]); assert_eq!(writer.position(), 0); - assert_eq!(writer.write(&[0]), Ok(1)); + assert_eq!(writer.write(&[0]).unwrap(), 1); assert_eq!(writer.position(), 1); - assert_eq!(writer.write(&[1, 2, 3]), Ok(3)); - assert_eq!(writer.write(&[4, 5, 6, 7]), Ok(4)); + assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3); + assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4); assert_eq!(writer.position(), 8); - assert_eq!(writer.write(&[]), Ok(0)); + assert_eq!(writer.write(&[]).unwrap(), 0); assert_eq!(writer.position(), 8); - assert_eq!(writer.write(&[8, 9]), Ok(1)); - assert_eq!(writer.write(&[10]), Ok(0)); + assert_eq!(writer.write(&[8, 9]).unwrap(), 1); + assert_eq!(writer.write(&[10]).unwrap(), 0); } let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8]; assert_eq!(buf, b); @@ -216,22 +215,22 @@ mod tests { { let mut writer = Cursor::new(&mut buf[..]); assert_eq!(writer.position(), 0); - assert_eq!(writer.write(&[1]), Ok(1)); + assert_eq!(writer.write(&[1]).unwrap(), 1); assert_eq!(writer.position(), 1); - assert_eq!(writer.seek(SeekFrom::Start(2)), Ok(2)); + assert_eq!(writer.seek(SeekFrom::Start(2)).unwrap(), 2); assert_eq!(writer.position(), 2); - assert_eq!(writer.write(&[2]), Ok(1)); + assert_eq!(writer.write(&[2]).unwrap(), 1); assert_eq!(writer.position(), 3); - assert_eq!(writer.seek(SeekFrom::Current(-2)), Ok(1)); + assert_eq!(writer.seek(SeekFrom::Current(-2)).unwrap(), 1); assert_eq!(writer.position(), 1); - assert_eq!(writer.write(&[3]), Ok(1)); + assert_eq!(writer.write(&[3]).unwrap(), 1); assert_eq!(writer.position(), 2); - assert_eq!(writer.seek(SeekFrom::End(-1)), Ok(7)); + assert_eq!(writer.seek(SeekFrom::End(-1)).unwrap(), 7); assert_eq!(writer.position(), 7); - assert_eq!(writer.write(&[4]), Ok(1)); + assert_eq!(writer.write(&[4]).unwrap(), 1); assert_eq!(writer.position(), 8); } @@ -243,31 +242,31 @@ mod tests { fn test_buf_writer_error() { let mut buf = [0 as u8; 2]; let mut writer = Cursor::new(&mut buf[..]); - assert_eq!(writer.write(&[0]), Ok(1)); - assert_eq!(writer.write(&[0, 0]), Ok(1)); - assert_eq!(writer.write(&[0, 0]), Ok(0)); + assert_eq!(writer.write(&[0]).unwrap(), 1); + assert_eq!(writer.write(&[0, 0]).unwrap(), 1); + assert_eq!(writer.write(&[0, 0]).unwrap(), 0); } #[test] fn test_mem_reader() { let mut reader = Cursor::new(vec!(0, 1, 2, 3, 4, 5, 6, 7)); let mut buf = []; - assert_eq!(reader.read(&mut buf), Ok(0)); + assert_eq!(reader.read(&mut buf).unwrap(), 0); assert_eq!(reader.position(), 0); let mut buf = [0]; - assert_eq!(reader.read(&mut buf), Ok(1)); + assert_eq!(reader.read(&mut buf).unwrap(), 1); assert_eq!(reader.position(), 1); let b: &[_] = &[0]; assert_eq!(buf, b); let mut buf = [0; 4]; - assert_eq!(reader.read(&mut buf), Ok(4)); + assert_eq!(reader.read(&mut buf).unwrap(), 4); assert_eq!(reader.position(), 5); let b: &[_] = &[1, 2, 3, 4]; assert_eq!(buf, b); - assert_eq!(reader.read(&mut buf), Ok(3)); + assert_eq!(reader.read(&mut buf).unwrap(), 3); let b: &[_] = &[5, 6, 7]; assert_eq!(&buf[..3], b); - assert_eq!(reader.read(&mut buf), Ok(0)); + assert_eq!(reader.read(&mut buf).unwrap(), 0); } #[test] @@ -281,57 +280,57 @@ mod tests { #[test] fn test_slice_reader() { let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7]; - let mut reader = &mut in_buf.as_slice(); + let mut reader = &mut &in_buf[..]; let mut buf = []; - assert_eq!(reader.read(&mut buf), Ok(0)); + assert_eq!(reader.read(&mut buf).unwrap(), 0); let mut buf = [0]; - assert_eq!(reader.read(&mut buf), Ok(1)); + assert_eq!(reader.read(&mut buf).unwrap(), 1); assert_eq!(reader.len(), 7); let b: &[_] = &[0]; - assert_eq!(buf.as_slice(), b); + assert_eq!(&buf[..], b); let mut buf = [0; 4]; - assert_eq!(reader.read(&mut buf), Ok(4)); + assert_eq!(reader.read(&mut buf).unwrap(), 4); assert_eq!(reader.len(), 3); let b: &[_] = &[1, 2, 3, 4]; - assert_eq!(buf.as_slice(), b); - assert_eq!(reader.read(&mut buf), Ok(3)); + assert_eq!(&buf[..], b); + assert_eq!(reader.read(&mut buf).unwrap(), 3); let b: &[_] = &[5, 6, 7]; assert_eq!(&buf[..3], b); - assert_eq!(reader.read(&mut buf), Ok(0)); + assert_eq!(reader.read(&mut buf).unwrap(), 0); } #[test] fn test_buf_reader() { let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7]; - let mut reader = Cursor::new(in_buf.as_slice()); + let mut reader = Cursor::new(&in_buf[..]); let mut buf = []; - assert_eq!(reader.read(&mut buf), Ok(0)); + assert_eq!(reader.read(&mut buf).unwrap(), 0); assert_eq!(reader.position(), 0); let mut buf = [0]; - assert_eq!(reader.read(&mut buf), Ok(1)); + assert_eq!(reader.read(&mut buf).unwrap(), 1); assert_eq!(reader.position(), 1); let b: &[_] = &[0]; assert_eq!(buf, b); let mut buf = [0; 4]; - assert_eq!(reader.read(&mut buf), Ok(4)); + assert_eq!(reader.read(&mut buf).unwrap(), 4); assert_eq!(reader.position(), 5); let b: &[_] = &[1, 2, 3, 4]; assert_eq!(buf, b); - assert_eq!(reader.read(&mut buf), Ok(3)); + assert_eq!(reader.read(&mut buf).unwrap(), 3); let b: &[_] = &[5, 6, 7]; assert_eq!(&buf[..3], b); - assert_eq!(reader.read(&mut buf), Ok(0)); + assert_eq!(reader.read(&mut buf).unwrap(), 0); } #[test] fn test_read_char() { let b = &b"Vi\xE1\xBB\x87t"[..]; let mut c = Cursor::new(b).chars(); - assert_eq!(c.next(), Some(Ok('V'))); - assert_eq!(c.next(), Some(Ok('i'))); - assert_eq!(c.next(), Some(Ok('ệ'))); - assert_eq!(c.next(), Some(Ok('t'))); - assert_eq!(c.next(), None); + assert_eq!(c.next().unwrap().unwrap(), 'V'); + assert_eq!(c.next().unwrap().unwrap(), 'i'); + assert_eq!(c.next().unwrap().unwrap(), 'ệ'); + assert_eq!(c.next().unwrap().unwrap(), 't'); + assert!(c.next().is_none()); } #[test] @@ -345,17 +344,17 @@ mod tests { fn seek_past_end() { let buf = [0xff]; let mut r = Cursor::new(&buf[..]); - assert_eq!(r.seek(SeekFrom::Start(10)), Ok(10)); - assert_eq!(r.read(&mut [0]), Ok(0)); + assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10); + assert_eq!(r.read(&mut [0]).unwrap(), 0); let mut r = Cursor::new(vec!(10)); - assert_eq!(r.seek(SeekFrom::Start(10)), Ok(10)); - assert_eq!(r.read(&mut [0]), Ok(0)); + assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10); + assert_eq!(r.read(&mut [0]).unwrap(), 0); let mut buf = [0]; let mut r = Cursor::new(&mut buf[..]); - assert_eq!(r.seek(SeekFrom::Start(10)), Ok(10)); - assert_eq!(r.write(&[3]), Ok(0)); + assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10); + assert_eq!(r.write(&[3]).unwrap(), 0); } #[test] @@ -376,32 +375,32 @@ mod tests { fn test_seekable_mem_writer() { let mut writer = Cursor::new(Vec::::new()); assert_eq!(writer.position(), 0); - assert_eq!(writer.write(&[0]), Ok(1)); + assert_eq!(writer.write(&[0]).unwrap(), 1); assert_eq!(writer.position(), 1); - assert_eq!(writer.write(&[1, 2, 3]), Ok(3)); - assert_eq!(writer.write(&[4, 5, 6, 7]), Ok(4)); + assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3); + assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4); assert_eq!(writer.position(), 8); let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7]; assert_eq!(&writer.get_ref()[..], b); - assert_eq!(writer.seek(SeekFrom::Start(0)), Ok(0)); + assert_eq!(writer.seek(SeekFrom::Start(0)).unwrap(), 0); assert_eq!(writer.position(), 0); - assert_eq!(writer.write(&[3, 4]), Ok(2)); + assert_eq!(writer.write(&[3, 4]).unwrap(), 2); let b: &[_] = &[3, 4, 2, 3, 4, 5, 6, 7]; assert_eq!(&writer.get_ref()[..], b); - assert_eq!(writer.seek(SeekFrom::Current(1)), Ok(3)); - assert_eq!(writer.write(&[0, 1]), Ok(2)); + assert_eq!(writer.seek(SeekFrom::Current(1)).unwrap(), 3); + assert_eq!(writer.write(&[0, 1]).unwrap(), 2); let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 7]; assert_eq!(&writer.get_ref()[..], b); - assert_eq!(writer.seek(SeekFrom::End(-1)), Ok(7)); - assert_eq!(writer.write(&[1, 2]), Ok(2)); + assert_eq!(writer.seek(SeekFrom::End(-1)).unwrap(), 7); + assert_eq!(writer.write(&[1, 2]).unwrap(), 2); let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2]; assert_eq!(&writer.get_ref()[..], b); - assert_eq!(writer.seek(SeekFrom::End(1)), Ok(10)); - assert_eq!(writer.write(&[1]), Ok(1)); + assert_eq!(writer.seek(SeekFrom::End(1)).unwrap(), 10); + assert_eq!(writer.write(&[1]).unwrap(), 1); let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1]; assert_eq!(&writer.get_ref()[..], b); } @@ -409,8 +408,8 @@ mod tests { #[test] fn vec_seek_past_end() { let mut r = Cursor::new(Vec::new()); - assert_eq!(r.seek(SeekFrom::Start(10)), Ok(10)); - assert_eq!(r.write(&[3]), Ok(1)); + assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10); + assert_eq!(r.write(&[3]).unwrap(), 1); } #[test] diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs index f445ace081e..b84dcb8fb62 100644 --- a/src/libstd/io/error.rs +++ b/src/libstd/io/error.rs @@ -9,12 +9,12 @@ // except according to those terms. use boxed::Box; -use clone::Clone; +use convert::Into; use error; use fmt; +use marker::Send; use option::Option::{self, Some, None}; use result; -use string::String; use sys; /// A type for results generated by I/O related functions where the `Err` type @@ -31,23 +31,22 @@ pub type Result = result::Result; /// Errors mostly originate from the underlying OS, but custom instances of /// `Error` can be created with crafted error messages and a particular value of /// `ErrorKind`. -#[derive(PartialEq, Eq, Clone, Debug)] +#[derive(Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Error { repr: Repr, } -#[derive(PartialEq, Eq, Clone, Debug)] +#[derive(Debug)] enum Repr { Os(i32), Custom(Box), } -#[derive(PartialEq, Eq, Clone, Debug)] +#[derive(Debug)] struct Custom { kind: ErrorKind, - desc: &'static str, - detail: Option + error: Box, } /// A list specifying general categories of I/O error. @@ -125,18 +124,34 @@ pub enum ErrorKind { } impl Error { - /// Creates a new custom error from a specified kind/description/detail. - #[unstable(feature = "io", reason = "the exact makeup of an Error may - change to include `Box` for \ - example")] - pub fn new(kind: ErrorKind, - description: &'static str, - detail: Option) -> Error { + /// Creates a new I/O error from a known kind of error as well as an + /// arbitrary error payload. + /// + /// This function is used to generically create I/O errors which do not + /// originate from the OS itself. The `error` argument is an arbitrary + /// payload which will be contained in this `Error`. Accessors as well as + /// downcasting will soon be added to this type as well to access the custom + /// information. + /// + /// # Examples + /// + /// ``` + /// use std::io::{Error, ErrorKind}; + /// + /// // errors can be created from strings + /// let custom_error = Error::new(ErrorKind::Other, "oh no!"); + /// + /// // errors can also be created from other errors + /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new(kind: ErrorKind, error: E) -> Error + where E: Into> + { Error { repr: Repr::Custom(Box::new(Custom { kind: kind, - desc: description, - detail: detail, + error: error.into(), })) } } @@ -162,8 +177,7 @@ impl Error { /// /// If this `Error` was constructed via `last_os_error` then this function /// will return `Some`, otherwise it will return `None`. - #[unstable(feature = "io", reason = "function was just added and the return \ - type may become an abstract OS error")] + #[stable(feature = "rust1", since = "1.0.0")] pub fn raw_os_error(&self) -> Option { match self.repr { Repr::Os(i) => Some(i), @@ -179,27 +193,6 @@ impl Error { Repr::Custom(ref c) => c.kind, } } - - /// Returns a short description for this error message - #[unstable(feature = "io")] - #[deprecated(since = "1.0.0", reason = "use the Error trait's description \ - method instead")] - pub fn description(&self) -> &str { - match self.repr { - Repr::Os(..) => "os error", - Repr::Custom(ref c) => c.desc, - } - } - - /// Returns a detailed error message for this error (if one is available) - #[unstable(feature = "io")] - #[deprecated(since = "1.0.0", reason = "use the to_string() method instead")] - pub fn detail(&self) -> Option { - match self.repr { - Repr::Os(code) => Some(sys::os::error_string(code)), - Repr::Custom(ref s) => s.detail.clone(), - } - } } #[stable(feature = "rust1", since = "1.0.0")] @@ -210,21 +203,7 @@ impl fmt::Display for Error { let detail = sys::os::error_string(code); write!(fmt, "{} (os error {})", detail, code) } - Repr::Custom(ref c) => { - match **c { - Custom { - kind: ErrorKind::Other, - desc: "unknown error", - detail: Some(ref detail) - } => { - write!(fmt, "{}", detail) - } - Custom { detail: None, desc, .. } => - write!(fmt, "{}", desc), - Custom { detail: Some(ref detail), desc, .. } => - write!(fmt, "{} ({})", desc, detail) - } - } + Repr::Custom(ref c) => c.error.fmt(fmt), } } } @@ -234,7 +213,7 @@ impl error::Error for Error { fn description(&self) -> &str { match self.repr { Repr::Os(..) => "os error", - Repr::Custom(ref c) => c.desc, + Repr::Custom(ref c) => c.error.description(), } } } diff --git a/src/libstd/io/impls.rs b/src/libstd/io/impls.rs index 52daba36213..67bc45d3b62 100644 --- a/src/libstd/io/impls.rs +++ b/src/libstd/io/impls.rs @@ -180,7 +180,7 @@ impl<'a> Write for &'a mut [u8] { if try!(self.write(data)) == data.len() { Ok(()) } else { - Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer", None)) + Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer")) } } diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 830a88bb6c9..a014d6e68ff 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -83,7 +83,7 @@ fn append_to_string(buf: &mut String, f: F) -> Result if str::from_utf8(&g.s[g.len..]).is_err() { ret.and_then(|_| { Err(Error::new(ErrorKind::InvalidInput, - "stream did not contain valid UTF-8", None)) + "stream did not contain valid UTF-8")) }) } else { g.len = g.s.len(); @@ -359,8 +359,7 @@ pub trait Write { while buf.len() > 0 { match self.write(buf) { Ok(0) => return Err(Error::new(ErrorKind::WriteZero, - "failed to write whole buffer", - None)), + "failed to write whole buffer")), Ok(n) => buf = &buf[n..], Err(ref e) if e.kind() == ErrorKind::Interrupted => {} Err(e) => return Err(e), @@ -441,9 +440,7 @@ pub trait Write { /// /// The stream typically has a fixed size, allowing seeking relative to either /// end or the current offset. -#[unstable(feature = "io", reason = "the central `seek` method may be split \ - into multiple methods instead of taking \ - an enum as an argument")] +#[stable(feature = "rust1", since = "1.0.0")] pub trait Seek { /// Seek to an offset, in bytes, in a stream /// @@ -459,14 +456,16 @@ pub trait Seek { /// # Errors /// /// Seeking to a negative offset is considered an error + #[stable(feature = "rust1", since = "1.0.0")] fn seek(&mut self, pos: SeekFrom) -> Result; } /// Enumeration of possible methods to seek within an I/O object. #[derive(Copy, PartialEq, Eq, Clone, Debug)] -#[unstable(feature = "io", reason = "awaiting the stability of Seek")] +#[stable(feature = "rust1", since = "1.0.0")] pub enum SeekFrom { /// Set the offset to the provided number of bytes. + #[stable(feature = "rust1", since = "1.0.0")] Start(u64), /// Set the offset to the size of this object plus the specified number of @@ -474,6 +473,7 @@ pub enum SeekFrom { /// /// It is possible to seek beyond the end of an object, but is an error to /// seek before byte 0. + #[stable(feature = "rust1", since = "1.0.0")] End(i64), /// Set the offset to the current position plus the specified number of @@ -481,6 +481,7 @@ pub enum SeekFrom { /// /// It is possible to seek beyond the end of an object, but is an error to /// seek before byte 0. + #[stable(feature = "rust1", since = "1.0.0")] Current(i64), } @@ -780,7 +781,7 @@ pub struct Chars { /// An enumeration of possible errors that can be generated from the `Chars` /// adapter. -#[derive(PartialEq, Clone, Debug)] +#[derive(Debug)] #[unstable(feature = "io", reason = "awaiting stability of Read::chars")] pub enum CharsError { /// Variant representing that the underlying stream was read successfully @@ -919,18 +920,18 @@ mod tests { fn read_until() { let mut buf = Cursor::new(&b"12"[..]); let mut v = Vec::new(); - assert_eq!(buf.read_until(b'3', &mut v), Ok(2)); + assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 2); assert_eq!(v, b"12"); let mut buf = Cursor::new(&b"1233"[..]); let mut v = Vec::new(); - assert_eq!(buf.read_until(b'3', &mut v), Ok(3)); + assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 3); assert_eq!(v, b"123"); v.truncate(0); - assert_eq!(buf.read_until(b'3', &mut v), Ok(1)); + assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 1); assert_eq!(v, b"3"); v.truncate(0); - assert_eq!(buf.read_until(b'3', &mut v), Ok(0)); + assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 0); assert_eq!(v, []); } @@ -938,32 +939,32 @@ mod tests { fn split() { let buf = Cursor::new(&b"12"[..]); let mut s = buf.split(b'3'); - assert_eq!(s.next(), Some(Ok(vec![b'1', b'2']))); - assert_eq!(s.next(), None); + assert_eq!(s.next().unwrap().unwrap(), vec![b'1', b'2']); + assert!(s.next().is_none()); let buf = Cursor::new(&b"1233"[..]); let mut s = buf.split(b'3'); - assert_eq!(s.next(), Some(Ok(vec![b'1', b'2']))); - assert_eq!(s.next(), Some(Ok(vec![]))); - assert_eq!(s.next(), None); + assert_eq!(s.next().unwrap().unwrap(), vec![b'1', b'2']); + assert_eq!(s.next().unwrap().unwrap(), vec![]); + assert!(s.next().is_none()); } #[test] fn read_line() { let mut buf = Cursor::new(&b"12"[..]); let mut v = String::new(); - assert_eq!(buf.read_line(&mut v), Ok(2)); + assert_eq!(buf.read_line(&mut v).unwrap(), 2); assert_eq!(v, "12"); let mut buf = Cursor::new(&b"12\n\n"[..]); let mut v = String::new(); - assert_eq!(buf.read_line(&mut v), Ok(3)); + assert_eq!(buf.read_line(&mut v).unwrap(), 3); assert_eq!(v, "12\n"); v.truncate(0); - assert_eq!(buf.read_line(&mut v), Ok(1)); + assert_eq!(buf.read_line(&mut v).unwrap(), 1); assert_eq!(v, "\n"); v.truncate(0); - assert_eq!(buf.read_line(&mut v), Ok(0)); + assert_eq!(buf.read_line(&mut v).unwrap(), 0); assert_eq!(v, ""); } @@ -971,26 +972,26 @@ mod tests { fn lines() { let buf = Cursor::new(&b"12"[..]); let mut s = buf.lines(); - assert_eq!(s.next(), Some(Ok("12".to_string()))); - assert_eq!(s.next(), None); + assert_eq!(s.next().unwrap().unwrap(), "12".to_string()); + assert!(s.next().is_none()); let buf = Cursor::new(&b"12\n\n"[..]); let mut s = buf.lines(); - assert_eq!(s.next(), Some(Ok("12".to_string()))); - assert_eq!(s.next(), Some(Ok(String::new()))); - assert_eq!(s.next(), None); + assert_eq!(s.next().unwrap().unwrap(), "12".to_string()); + assert_eq!(s.next().unwrap().unwrap(), "".to_string()); + assert!(s.next().is_none()); } #[test] fn read_to_end() { let mut c = Cursor::new(&b""[..]); let mut v = Vec::new(); - assert_eq!(c.read_to_end(&mut v), Ok(0)); + assert_eq!(c.read_to_end(&mut v).unwrap(), 0); assert_eq!(v, []); let mut c = Cursor::new(&b"1"[..]); let mut v = Vec::new(); - assert_eq!(c.read_to_end(&mut v), Ok(1)); + assert_eq!(c.read_to_end(&mut v).unwrap(), 1); assert_eq!(v, b"1"); } @@ -998,12 +999,12 @@ mod tests { fn read_to_string() { let mut c = Cursor::new(&b""[..]); let mut v = String::new(); - assert_eq!(c.read_to_string(&mut v), Ok(0)); + assert_eq!(c.read_to_string(&mut v).unwrap(), 0); assert_eq!(v, ""); let mut c = Cursor::new(&b"1"[..]); let mut v = String::new(); - assert_eq!(c.read_to_string(&mut v), Ok(1)); + assert_eq!(c.read_to_string(&mut v).unwrap(), 1); assert_eq!(v, "1"); let mut c = Cursor::new(&b"\xff"[..]); @@ -1017,11 +1018,11 @@ mod tests { impl Read for R { fn read(&mut self, _: &mut [u8]) -> io::Result { - Err(io::Error::new(io::ErrorKind::Other, "", None)) + Err(io::Error::new(io::ErrorKind::Other, "")) } } let mut buf = [0; 1]; - assert_eq!(Ok(0), R.take(0).read(&mut buf)); + assert_eq!(0, R.take(0).read(&mut buf).unwrap()); } } diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index 20426025257..c82f9515e8d 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -111,33 +111,33 @@ mod test { #[test] fn sink_sinks() { let mut s = sink(); - assert_eq!(s.write(&[]), Ok(0)); - assert_eq!(s.write(&[0]), Ok(1)); - assert_eq!(s.write(&[0; 1024]), Ok(1024)); - assert_eq!(s.by_ref().write(&[0; 1024]), Ok(1024)); + assert_eq!(s.write(&[]).unwrap(), 0); + assert_eq!(s.write(&[0]).unwrap(), 1); + assert_eq!(s.write(&[0; 1024]).unwrap(), 1024); + assert_eq!(s.by_ref().write(&[0; 1024]).unwrap(), 1024); } #[test] fn empty_reads() { let mut e = empty(); - assert_eq!(e.read(&mut []), Ok(0)); - assert_eq!(e.read(&mut [0]), Ok(0)); - assert_eq!(e.read(&mut [0; 1024]), Ok(0)); - assert_eq!(e.by_ref().read(&mut [0; 1024]), Ok(0)); + assert_eq!(e.read(&mut []).unwrap(), 0); + assert_eq!(e.read(&mut [0]).unwrap(), 0); + assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0); + assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0); } #[test] fn repeat_repeats() { let mut r = repeat(4); let mut b = [0; 1024]; - assert_eq!(r.read(&mut b), Ok(1024)); + assert_eq!(r.read(&mut b).unwrap(), 1024); assert!(b.iter().all(|b| *b == 4)); } #[test] fn take_some_bytes() { assert_eq!(repeat(4).take(100).bytes().count(), 100); - assert_eq!(repeat(4).take(100).bytes().next(), Some(Ok(4))); + assert_eq!(repeat(4).take(100).bytes().next().unwrap().unwrap(), 4); assert_eq!(repeat(1).take(10).chain(repeat(2).take(10)).bytes().count(), 20); } @@ -146,7 +146,7 @@ mod test { let mut buf = [0; 10]; { let mut ptr: &mut [u8] = &mut buf; - assert_eq!(repeat(4).tee(&mut ptr).take(5).read(&mut [0; 10]), Ok(5)); + assert_eq!(repeat(4).tee(&mut ptr).take(5).read(&mut [0; 10]).unwrap(), 5); } assert_eq!(buf, [4, 4, 4, 4, 4, 0, 0, 0, 0, 0]); } @@ -160,7 +160,7 @@ mod test { let mut ptr2: &mut [u8] = &mut buf2; assert_eq!((&mut ptr1).broadcast(&mut ptr2) - .write(&[1, 2, 3]), Ok(3)); + .write(&[1, 2, 3]).unwrap(), 3); } assert_eq!(buf1, buf2); assert_eq!(buf1, [1, 2, 3, 0, 0, 0, 0, 0, 0, 0]); diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index b7cb8f9ed50..41ac3d60df5 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -44,7 +44,7 @@ //! lives in the [`vec`](vec/index.html) module. Contiguous, unsized regions //! of memory, `[T]`, commonly called "slices", and their borrowed versions, //! `&[T]`, commonly called "borrowed slices", are built-in types for which the -//! for which the [`slice`](slice/index.html) module defines many methods. +//! [`slice`](slice/index.html) module defines many methods. //! //! `&str`, a UTF-8 string, is a built-in type, and the standard library //! defines methods for it on a variety of traits in the @@ -122,12 +122,11 @@ #![feature(unsafe_no_drop_flag, filling_drop)] #![feature(macro_reexport)] #![feature(unique)] -#![feature(convert)] #![feature(allow_internal_unstable)] #![feature(str_char)] #![feature(into_cow)] -#![feature(slice_patterns)] #![feature(std_misc)] +#![feature(slice_patterns)] #![feature(debug_builders)] #![cfg_attr(test, feature(test, rustc_private, std_misc))] @@ -173,8 +172,6 @@ pub use core::clone; #[cfg(not(test))] pub use core::cmp; pub use core::convert; pub use core::default; -#[allow(deprecated)] -pub use core::finally; pub use core::hash; pub use core::intrinsics; pub use core::iter; diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 645bc5db753..b3d1adb4421 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -101,7 +101,7 @@ macro_rules! try { ($expr:expr) => (match $expr { $crate::result::Result::Ok(val) => val, $crate::result::Result::Err(err) => { - return $crate::result::Result::Err($crate::error::FromError::from_error(err)) + return $crate::result::Result::Err($crate::convert::From::from(err)) } }) } diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index a08b33b342b..c45230e91ba 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -435,7 +435,7 @@ impl ToSocketAddrs for str { match $e { Some(r) => r, None => return Err(io::Error::new(io::ErrorKind::InvalidInput, - $msg, None)), + $msg)), } ) } @@ -697,8 +697,11 @@ mod tests { false, false, false, true, false, false, false, Some(Global)); } - fn tsa(a: A) -> io::Result> { - Ok(try!(a.to_socket_addrs()).collect()) + fn tsa(a: A) -> Result, String> { + match a.to_socket_addrs() { + Ok(a) => Ok(a.collect()), + Err(e) => Err(e.to_string()), + } } #[test] diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs index ee57300765e..a152b98822a 100644 --- a/src/libstd/net/mod.rs +++ b/src/libstd/net/mod.rs @@ -72,7 +72,7 @@ fn each_addr(addr: A, mut f: F) -> io::Result } Err(last_err.unwrap_or_else(|| { Error::new(ErrorKind::InvalidInput, - "could not resolve to any addresses", None) + "could not resolve to any addresses") })) } diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index 869faa795f9..04d1013af1f 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -17,7 +17,7 @@ use io::prelude::*; use io; use net::{ToSocketAddrs, SocketAddr, Shutdown}; use sys_common::net2 as net_imp; -use sys_common::AsInner; +use sys_common::{AsInner, FromInner}; /// A structure which represents a TCP stream between a local socket and a /// remote socket. @@ -100,13 +100,6 @@ impl TcpStream { self.0.peer_addr() } - /// Returns the socket address of the local half of this TCP connection. - #[unstable(feature = "net")] - #[deprecated(since = "1.0.0", reason = "renamed to local_addr")] - pub fn socket_addr(&self) -> io::Result { - self.0.socket_addr() - } - /// Returns the socket address of the local half of this TCP connection. #[stable(feature = "rust1", since = "1.0.0")] pub fn local_addr(&self) -> io::Result { @@ -172,6 +165,10 @@ impl AsInner for TcpStream { fn as_inner(&self) -> &net_imp::TcpStream { &self.0 } } +impl FromInner for TcpStream { + fn from_inner(inner: net_imp::TcpStream) -> TcpStream { TcpStream(inner) } +} + impl TcpListener { /// Creates a new `TcpListener` which will be bound to the specified /// address. @@ -195,13 +192,6 @@ impl TcpListener { self.0.socket_addr() } - /// Deprecated, renamed to local_addr - #[unstable(feature = "net")] - #[deprecated(since = "1.0.0", reason = "renamed to local_addr")] - pub fn socket_addr(&self) -> io::Result { - self.0.socket_addr() - } - /// Create a new independently owned handle to the underlying socket. /// /// The returned `TcpListener` is a reference to the same socket that this @@ -245,6 +235,12 @@ impl AsInner for TcpListener { fn as_inner(&self) -> &net_imp::TcpListener { &self.0 } } +impl FromInner for TcpListener { + fn from_inner(inner: net_imp::TcpListener) -> TcpListener { + TcpListener(inner) + } +} + #[cfg(test)] mod tests { use prelude::v1::*; @@ -349,7 +345,7 @@ mod tests { let _t = thread::spawn(move|| { let mut stream = t!(TcpStream::connect(&addr)); t!(stream.write(&[99])); - tx.send(t!(stream.socket_addr())).unwrap(); + tx.send(t!(stream.local_addr())).unwrap(); }); let (mut stream, addr) = t!(acceptor.accept()); @@ -499,7 +495,7 @@ mod tests { fn socket_and_peer_name_ip4() { each_ip(&mut |addr| { let listener = t!(TcpListener::bind(&addr)); - let so_name = t!(listener.socket_addr()); + let so_name = t!(listener.local_addr()); assert_eq!(addr, so_name); let _t = thread::spawn(move|| { t!(listener.accept()); @@ -525,7 +521,7 @@ mod tests { let mut c = t!(TcpStream::connect(&addr)); let mut b = [0; 10]; - assert_eq!(c.read(&mut b), Ok(1)); + assert_eq!(c.read(&mut b).unwrap(), 1); t!(c.write(&[1])); rx.recv().unwrap(); }) @@ -570,7 +566,7 @@ mod tests { let _t = thread::spawn(move|| { let mut s = t!(TcpStream::connect(&addr)); let mut buf = [0, 0]; - assert_eq!(s.read(&mut buf), Ok(1)); + assert_eq!(s.read(&mut buf).unwrap(), 1); assert_eq!(buf[0], 1); t!(s.write(&[2])); }); @@ -588,7 +584,7 @@ mod tests { }); tx1.send(()).unwrap(); let mut buf = [0, 0]; - assert_eq!(s1.read(&mut buf), Ok(1)); + assert_eq!(s1.read(&mut buf).unwrap(), 1); rx2.recv().unwrap(); }) } @@ -661,7 +657,7 @@ mod tests { let _t = thread::spawn(move|| { let mut c = t!(a.accept()).0; let mut b = [0]; - assert_eq!(c.read(&mut b), Ok(0)); + assert_eq!(c.read(&mut b).unwrap(), 0); t!(c.write(&[1])); }); @@ -692,16 +688,16 @@ mod tests { t!(s.shutdown(Shutdown::Write)); assert!(s.write(&[0]).is_err()); t!(s.shutdown(Shutdown::Read)); - assert_eq!(s.read(&mut b), Ok(0)); + assert_eq!(s.read(&mut b).unwrap(), 0); // closing should affect previous handles assert!(s2.write(&[0]).is_err()); - assert_eq!(s2.read(&mut b), Ok(0)); + assert_eq!(s2.read(&mut b).unwrap(), 0); // closing should affect new handles let mut s3 = t!(s.try_clone()); assert!(s3.write(&[0]).is_err()); - assert_eq!(s3.read(&mut b), Ok(0)); + assert_eq!(s3.read(&mut b).unwrap(), 0); // make sure these don't die let _ = s2.shutdown(Shutdown::Read); diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index 81151114962..7b14e4dbea6 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -16,7 +16,7 @@ use prelude::v1::*; use io::{self, Error, ErrorKind}; use net::{ToSocketAddrs, SocketAddr, IpAddr}; use sys_common::net2 as net_imp; -use sys_common::AsInner; +use sys_common::{AsInner, FromInner}; /// A User Datagram Protocol socket. /// @@ -76,17 +76,10 @@ impl UdpSocket { match try!(addr.to_socket_addrs()).next() { Some(addr) => self.0.send_to(buf, &addr), None => Err(Error::new(ErrorKind::InvalidInput, - "no addresses to send data to", None)), + "no addresses to send data to")), } } - /// Returns the socket address that this socket was created from. - #[unstable(feature = "net")] - #[deprecated(since = "1.0.0", reason = "renamed to local_addr")] - pub fn socket_addr(&self) -> io::Result { - self.0.socket_addr() - } - /// Returns the socket address that this socket was created from. #[stable(feature = "rust1", since = "1.0.0")] pub fn local_addr(&self) -> io::Result { @@ -140,6 +133,10 @@ impl AsInner for UdpSocket { fn as_inner(&self) -> &net_imp::UdpSocket { &self.0 } } +impl FromInner for UdpSocket { + fn from_inner(inner: net_imp::UdpSocket) -> UdpSocket { UdpSocket(inner) } +} + #[cfg(test)] mod tests { use prelude::v1::*; @@ -203,7 +200,7 @@ mod tests { fn socket_name_ip4() { each_ip(&mut |addr, _| { let server = t!(UdpSocket::bind(&addr)); - assert_eq!(addr, t!(server.socket_addr())); + assert_eq!(addr, t!(server.local_addr())); }) } @@ -215,7 +212,7 @@ mod tests { let _t = thread::spawn(move|| { let mut buf = [0, 0]; - assert_eq!(sock2.recv_from(&mut buf), Ok((1, addr1))); + assert_eq!(sock2.recv_from(&mut buf).unwrap(), (1, addr1)); assert_eq!(buf[0], 1); t!(sock2.send_to(&[2], &addr1)); }); @@ -231,7 +228,7 @@ mod tests { }); tx1.send(()).unwrap(); let mut buf = [0, 0]; - assert_eq!(sock1.recv_from(&mut buf), Ok((1, addr2))); + assert_eq!(sock1.recv_from(&mut buf).unwrap(), (1, addr2)); rx2.recv().unwrap(); }) } diff --git a/src/libstd/old_io/buffered.rs b/src/libstd/old_io/buffered.rs index ad6cac62173..68aa7e4770f 100644 --- a/src/libstd/old_io/buffered.rs +++ b/src/libstd/old_io/buffered.rs @@ -548,7 +548,7 @@ mod test { let mut w = BufferedWriter::with_capacity(3, Vec::new()); w.write_all(&[0, 1]).unwrap(); let a: &[_] = &[]; - assert_eq!(a, &w.get_ref()[..]); + assert_eq!(&w.get_ref()[..], a); let w = w.into_inner(); let a: &[_] = &[0, 1]; assert_eq!(a, &w[..]); diff --git a/src/libstd/old_io/extensions.rs b/src/libstd/old_io/extensions.rs index 0e5dd3aa4aa..73973d0db28 100644 --- a/src/libstd/old_io/extensions.rs +++ b/src/libstd/old_io/extensions.rs @@ -519,7 +519,8 @@ mod bench { ({ use super::u64_from_be_bytes; - let data = (0..$stride*100+$start_index).collect::>(); + let len = ($stride as u8).wrapping_mul(100).wrapping_add($start_index); + let data = (0..len).collect::>(); let mut sum = 0; $b.iter(|| { let mut i = $start_index; diff --git a/src/libstd/old_io/fs.rs b/src/libstd/old_io/fs.rs index 6aa63c395c6..bef6ea53e50 100644 --- a/src/libstd/old_io/fs.rs +++ b/src/libstd/old_io/fs.rs @@ -951,7 +951,8 @@ mod test { pub fn tmpdir() -> TempDir { use os; use rand; - let ret = os::tmpdir().join(format!("rust-{}", rand::random::())); + let temp = Path::new(::env::temp_dir().to_str().unwrap()); + let ret = temp.join(format!("rust-{}", rand::random::())); check!(old_io::fs::mkdir(&ret, old_io::USER_RWX)); TempDir(ret) } @@ -1639,7 +1640,7 @@ mod test { check!(File::create(&tmpdir.join("test")).write(&bytes)); let actual = check!(File::open(&tmpdir.join("test")).read_to_end()); - assert!(actual == bytes.as_slice()); + assert!(actual == &bytes[..]); } #[test] diff --git a/src/libstd/old_io/mem.rs b/src/libstd/old_io/mem.rs index 64803191d4f..c92e74fbc56 100644 --- a/src/libstd/old_io/mem.rs +++ b/src/libstd/old_io/mem.rs @@ -399,7 +399,7 @@ impl<'a> Buffer for BufReader<'a> { mod test { extern crate test as test_crate; use old_io::{SeekSet, SeekCur, SeekEnd, Reader, Writer, Seek, Buffer}; - use prelude::v1::{Ok, Err, Vec, AsSlice}; + use prelude::v1::{Ok, Err, Vec}; use prelude::v1::Iterator; use old_io; use iter::repeat; @@ -744,7 +744,7 @@ mod test { wr.write(&[5; 10]).unwrap(); } } - assert_eq!(buf.as_slice(), [5; 100].as_slice()); + assert_eq!(&buf[..], &[5; 100][..]); }); } diff --git a/src/libstd/old_io/mod.rs b/src/libstd/old_io/mod.rs index df8ac78f7e5..9d7e1082d33 100644 --- a/src/libstd/old_io/mod.rs +++ b/src/libstd/old_io/mod.rs @@ -274,7 +274,7 @@ use mem::transmute; use ops::FnOnce; use option::Option; use option::Option::{Some, None}; -use os; +use sys::os; use boxed::Box; use result::Result; use result::Result::{Ok, Err}; diff --git a/src/libstd/old_io/net/ip.rs b/src/libstd/old_io/net/ip.rs index 26e1bb6550b..099fe657f26 100644 --- a/src/libstd/old_io/net/ip.rs +++ b/src/libstd/old_io/net/ip.rs @@ -414,7 +414,7 @@ pub struct ParseError; /// Some examples: /// /// ```rust,no_run -/// # #![feature(old_io, core)] +/// # #![feature(old_io, core, convert)] /// # #![allow(unused_must_use)] /// /// use std::old_io::{TcpStream, TcpListener}; @@ -435,7 +435,7 @@ pub struct ParseError; /// let tcp_l = TcpListener::bind("localhost:12345"); /// /// let mut udp_s = UdpSocket::bind(("127.0.0.1", 23451)).unwrap(); -/// udp_s.send_to([7, 7, 7].as_slice(), (Ipv4Addr(127, 0, 0, 1), 23451)); +/// udp_s.send_to([7, 7, 7].as_ref(), (Ipv4Addr(127, 0, 0, 1), 23451)); /// } /// ``` pub trait ToSocketAddr { diff --git a/src/libstd/old_io/pipe.rs b/src/libstd/old_io/pipe.rs index 26f24600479..fd1df49473e 100644 --- a/src/libstd/old_io/pipe.rs +++ b/src/libstd/old_io/pipe.rs @@ -124,9 +124,9 @@ mod test { use os; use old_io::pipe::PipeStream; - let os::Pipe { reader, writer } = unsafe { os::pipe().unwrap() }; - let out = PipeStream::open(writer); - let mut input = PipeStream::open(reader); + let (reader, writer) = unsafe { ::sys::os::pipe().unwrap() }; + let out = PipeStream::open(writer.unwrap()); + let mut input = PipeStream::open(reader.unwrap()); let (tx, rx) = channel(); let _t = thread::spawn(move|| { let mut out = out; diff --git a/src/libstd/old_io/process.rs b/src/libstd/old_io/process.rs index 06940bf6860..ad2d5b46819 100644 --- a/src/libstd/old_io/process.rs +++ b/src/libstd/old_io/process.rs @@ -246,7 +246,7 @@ impl Command { None => { // if the env is currently just inheriting from the parent's, // materialize the parent's env into a hashtable. - self.env = Some(os::env_as_bytes().into_iter().map(|(k, v)| { + self.env = Some(::env::vars().map(|(k, v)| { (EnvKey(CString::new(k).unwrap()), CString::new(v).unwrap()) }).collect()); @@ -367,7 +367,7 @@ impl Command { /// # Examples /// /// ``` - /// # #![feature(old_io, core)] + /// # #![feature(old_io, core, convert)] /// use std::old_io::Command; /// /// let output = match Command::new("cat").arg("foot.txt").output() { @@ -376,8 +376,8 @@ impl Command { /// }; /// /// println!("status: {}", output.status); - /// println!("stdout: {}", String::from_utf8_lossy(output.output.as_slice())); - /// println!("stderr: {}", String::from_utf8_lossy(output.error.as_slice())); + /// println!("stdout: {}", String::from_utf8_lossy(output.output.as_ref())); + /// println!("stderr: {}", String::from_utf8_lossy(output.error.as_ref())); /// ``` pub fn output(&self) -> IoResult { self.spawn().and_then(|p| p.wait_with_output()) @@ -764,11 +764,9 @@ impl Drop for Process { #[cfg(test)] mod tests { + use prelude::v1::*; use old_io::{Truncate, Write, TimedOut, timer, process, FileNotFound}; use old_io::{Reader, Writer}; - use prelude::v1::{Ok, Err, drop, Some, None, Vec}; - use prelude::v1::{String, Clone}; - use prelude::v1::{Str, AsSlice, ToString}; use old_path::{GenericPath, Path}; use old_io::fs::PathExtensions; use old_io::timer::*; @@ -1003,7 +1001,7 @@ mod tests { let prog = pwd_cmd().spawn().unwrap(); let output = String::from_utf8(prog.wait_with_output().unwrap().output).unwrap(); - let parent_dir = os::getcwd().unwrap(); + let parent_dir = Path::new(::env::current_dir().unwrap().to_str().unwrap()); let child_dir = Path::new(output.trim()); let parent_stat = parent_dir.stat().unwrap(); @@ -1018,7 +1016,7 @@ mod tests { use os; // test changing to the parent of os::getcwd() because we know // the path exists (and os::getcwd() is not expected to be root) - let parent_dir = os::getcwd().unwrap().dir_path(); + let parent_dir = Path::new(::env::current_dir().unwrap().to_str().unwrap()); let prog = pwd_cmd().cwd(&parent_dir).spawn().unwrap(); let output = String::from_utf8(prog.wait_with_output().unwrap().output).unwrap(); @@ -1058,11 +1056,11 @@ mod tests { let prog = env_cmd().spawn().unwrap(); let output = String::from_utf8(prog.wait_with_output().unwrap().output).unwrap(); - let r = os::env(); - for &(ref k, ref v) in &r { + let r = ::env::vars(); + for (k, v) in r { // don't check windows magical empty-named variables assert!(k.is_empty() || - output.contains(&format!("{}={}", *k, *v)), + output.contains(&format!("{}={}", k, v)), "output doesn't contain `{}={}`\n{}", k, v, output); } @@ -1076,16 +1074,12 @@ mod tests { let mut prog = env_cmd().spawn().unwrap(); let output = String::from_utf8(prog.wait_with_output().unwrap().output).unwrap(); - let r = os::env(); - for &(ref k, ref v) in &r { + let r = ::env::vars(); + for (k, v) in r { // don't check android RANDOM variables - if *k != "RANDOM".to_string() { - assert!(output.contains(&format!("{}={}", - *k, - *v)) || - output.contains(&format!("{}=\'{}\'", - *k, - *v))); + if k != "RANDOM".to_string() { + assert!(output.contains(&format!("{}={}", k, v)) || + output.contains(&format!("{}=\'{}\'", k, v))); } } } @@ -1100,9 +1094,9 @@ mod tests { // PATH to our sub-process. let path_val: String; let mut new_env = vec![("RUN_TEST_NEW_ENV", "123")]; - match os::getenv("PATH") { - None => {} - Some(val) => { + match ::env::var("PATH") { + Err(..) => {} + Ok(val) => { path_val = val; new_env.push(("PATH", &path_val)) } diff --git a/src/libstd/old_io/tempfile.rs b/src/libstd/old_io/tempfile.rs index 0a2cc517a06..94faa5540bb 100644 --- a/src/libstd/old_io/tempfile.rs +++ b/src/libstd/old_io/tempfile.rs @@ -100,7 +100,8 @@ impl TempDir { #[allow(deprecated)] pub fn new_in(tmpdir: &Path, prefix: &str) -> IoResult { if !tmpdir.is_absolute() { - let cur_dir = try!(::os::getcwd()); + let cur_dir = ::env::current_dir().unwrap(); + let cur_dir = Path::new(cur_dir.to_str().unwrap()); return TempDir::new_in(&cur_dir.join(tmpdir), prefix); } @@ -136,7 +137,8 @@ impl TempDir { /// If no directory can be created, `Err` is returned. #[allow(deprecated)] pub fn new(prefix: &str) -> IoResult { - TempDir::new_in(&::os::tmpdir(), prefix) + let tmp = Path::new(::env::temp_dir().to_str().unwrap()); + TempDir::new_in(&tmp, prefix) } /// Unwrap the wrapped `std::path::Path` from the `TempDir` wrapper. diff --git a/src/libstd/old_io/test.rs b/src/libstd/old_io/test.rs index db409ecde45..312e1c814dc 100644 --- a/src/libstd/old_io/test.rs +++ b/src/libstd/old_io/test.rs @@ -43,7 +43,7 @@ fn next_test_unix_socket() -> String { pub fn next_test_unix() -> Path { let string = next_test_unix_socket(); if cfg!(unix) { - ::os::tmpdir().join(string) + Path::new(::env::temp_dir().to_str().unwrap()).join(string) } else { Path::new(format!("{}{}", r"\\.\pipe\", string)) } @@ -141,7 +141,7 @@ mod darwin_fd_limit { // sysctl value, and bump the soft resource limit for maxfiles up to the sysctl value. use ptr::null_mut; use mem::size_of_val; - use os::last_os_error; + use io; // Fetch the kern.maxfilesperproc value let mut mib: [libc::c_int; 2] = [CTL_KERN, KERN_MAXFILESPERPROC]; @@ -149,14 +149,14 @@ mod darwin_fd_limit { let mut size: libc::size_t = size_of_val(&maxfiles) as libc::size_t; if sysctl(&mut mib[0], 2, &mut maxfiles as *mut libc::c_int as *mut libc::c_void, &mut size, null_mut(), 0) != 0 { - let err = last_os_error(); + let err = io::Error::last_os_error(); panic!("raise_fd_limit: error calling sysctl: {}", err); } // Fetch the current resource limits let mut rlim = rlimit{rlim_cur: 0, rlim_max: 0}; if getrlimit(RLIMIT_NOFILE, &mut rlim) != 0 { - let err = last_os_error(); + let err = io::Error::last_os_error(); panic!("raise_fd_limit: error calling getrlimit: {}", err); } @@ -165,7 +165,7 @@ mod darwin_fd_limit { // Set our newly-increased resource limit if setrlimit(RLIMIT_NOFILE, &rlim) != 0 { - let err = last_os_error(); + let err = io::Error::last_os_error(); panic!("raise_fd_limit: error calling setrlimit: {}", err); } } diff --git a/src/libstd/old_io/util.rs b/src/libstd/old_io/util.rs index 604099f1178..a5ecb98334a 100644 --- a/src/libstd/old_io/util.rs +++ b/src/libstd/old_io/util.rs @@ -334,7 +334,7 @@ mod test { let mut r = MemReader::new(vec!(0, 1, 2)); { let mut r = LimitReader::new(r.by_ref(), 4); - assert_eq!([0, 1, 2], r.read_to_end().unwrap()); + assert_eq!(r.read_to_end().unwrap(), [0, 1, 2]); } } @@ -343,9 +343,9 @@ mod test { let mut r = MemReader::new(vec!(0, 1, 2)); { let mut r = LimitReader::new(r.by_ref(), 2); - assert_eq!([0, 1], r.read_to_end().unwrap()); + assert_eq!(r.read_to_end().unwrap(), [0, 1]); } - assert_eq!([2], r.read_to_end().unwrap()); + assert_eq!(r.read_to_end().unwrap(), [2]); } #[test] @@ -355,7 +355,7 @@ mod test { assert_eq!(3, r.limit()); assert_eq!(0, r.read_byte().unwrap()); assert_eq!(2, r.limit()); - assert_eq!([1, 2], r.read_to_end().unwrap()); + assert_eq!(r.read_to_end().unwrap(), [1, 2]); assert_eq!(0, r.limit()); } @@ -364,7 +364,7 @@ mod test { let mut r = MemReader::new(vec![0, 1, 2, 3, 4, 5]); let mut r = LimitReader::new(r.by_ref(), 1); r.consume(2); - assert_eq!([], r.read_to_end().unwrap()); + assert_eq!(r.read_to_end().unwrap(), []); } #[test] @@ -380,7 +380,7 @@ mod test { let mut s = ZeroReader; let mut buf = vec![1, 2, 3]; assert_eq!(s.read(&mut buf), Ok(3)); - assert_eq!([0, 0, 0], buf); + assert_eq!(buf, [0, 0, 0]); } #[test] @@ -423,16 +423,16 @@ mod test { let rs = vec!(MemReader::new(vec!(0, 1)), MemReader::new(vec!()), MemReader::new(vec!(2, 3))); let mut r = ChainedReader::new(rs.into_iter()); - assert_eq!([0, 1, 2, 3], r.read_to_end().unwrap()); + assert_eq!(r.read_to_end().unwrap(), [0, 1, 2, 3]); } #[test] fn test_tee_reader() { let mut r = TeeReader::new(MemReader::new(vec!(0, 1, 2)), Vec::new()); - assert_eq!([0, 1, 2], r.read_to_end().unwrap()); + assert_eq!(r.read_to_end().unwrap(), [0, 1, 2]); let (_, w) = r.into_inner(); - assert_eq!([0, 1, 2], w); + assert_eq!(w, [0, 1, 2]); } #[test] @@ -440,7 +440,7 @@ mod test { let mut r = MemReader::new(vec!(0, 1, 2, 3, 4)); let mut w = Vec::new(); copy(&mut r, &mut w).unwrap(); - assert_eq!([0, 1, 2, 3, 4], w); + assert_eq!(w, [0, 1, 2, 3, 4]); } #[test] diff --git a/src/libstd/old_path/mod.rs b/src/libstd/old_path/mod.rs index c405df2824e..9c88533d3ba 100644 --- a/src/libstd/old_path/mod.rs +++ b/src/libstd/old_path/mod.rs @@ -69,12 +69,13 @@ use core::marker::Sized; use ffi::CString; use clone::Clone; +use borrow::Cow; use fmt; use iter::Iterator; use option::Option; use option::Option::{None, Some}; use str; -use string::{String, CowString}; +use string::String; use vec::Vec; /// Typedef for POSIX file paths. @@ -907,7 +908,7 @@ impl<'a, P: GenericPath> Display<'a, P> { /// If the path is not UTF-8, invalid sequences will be replaced with the /// Unicode replacement char. This involves allocation. #[inline] - pub fn as_cow(&self) -> CowString<'a> { + pub fn as_cow(&self) -> Cow<'a, str> { String::from_utf8_lossy(if self.filename { match self.path.filename() { None => { diff --git a/src/libstd/old_path/posix.rs b/src/libstd/old_path/posix.rs index bbc1756bee6..c517fab257f 100644 --- a/src/libstd/old_path/posix.rs +++ b/src/libstd/old_path/posix.rs @@ -20,7 +20,7 @@ use iter::{Iterator, Map}; use marker::Sized; use option::Option::{self, Some, None}; use result::Result::{self, Ok, Err}; -use slice::{AsSlice, Split, SliceConcatExt}; +use slice::{Split, SliceConcatExt}; use str::{self, FromStr}; use vec::Vec; @@ -126,7 +126,7 @@ impl GenericPathUnsafe for Path { unsafe fn set_filename_unchecked(&mut self, filename: T) { let filename = filename.container_as_bytes(); match self.sepidx { - None if b".." == self.repr => { + None if self.repr == b".." => { let mut v = Vec::with_capacity(3 + filename.len()); v.push_all(dot_dot_static); v.push(SEP_BYTE); @@ -186,7 +186,7 @@ impl GenericPath for Path { fn dirname<'a>(&'a self) -> &'a [u8] { match self.sepidx { - None if b".." == self.repr => &self.repr, + None if self.repr == b".." => &self.repr, None => dot_static, Some(0) => &self.repr[..1], Some(idx) if &self.repr[idx+1..] == b".." => &self.repr, @@ -196,8 +196,7 @@ impl GenericPath for Path { fn filename<'a>(&'a self) -> Option<&'a [u8]> { match self.sepidx { - None if b"." == self.repr || - b".." == self.repr => None, + None if self.repr == b"." || self.repr == b".." => None, None => Some(&self.repr), Some(idx) if &self.repr[idx+1..] == b".." => None, Some(0) if self.repr[1..].is_empty() => None, @@ -207,13 +206,13 @@ impl GenericPath for Path { fn pop(&mut self) -> bool { match self.sepidx { - None if b"." == self.repr => false, + None if self.repr == b"." => false, None => { self.repr = vec![b'.']; self.sepidx = None; true } - Some(0) if b"/" == self.repr => false, + Some(0) if self.repr == b"/" => false, Some(idx) => { if idx == 0 { self.repr.truncate(idx+1); @@ -245,7 +244,7 @@ impl GenericPath for Path { } else { let mut ita = self.components(); let mut itb = other.components(); - if b"." == self.repr { + if self.repr == b"." { return match itb.next() { None => true, Some(b) => b != b".." @@ -339,11 +338,11 @@ impl Path { /// Returns a normalized byte vector representation of a path, by removing all empty /// components, and unnecessary . and .. components. - fn normalize>(v: &V) -> Vec { + fn normalize(v: &[u8]) -> Vec { // borrowck is being very picky let val = { - let is_abs = !v.as_slice().is_empty() && v.as_slice()[0] == SEP_BYTE; - let v_ = if is_abs { &v.as_slice()[1..] } else { v.as_slice() }; + let is_abs = !v.is_empty() && v[0] == SEP_BYTE; + let v_ = if is_abs { &v[1..] } else { v }; let comps = normalize_helper(v_, is_abs); match comps { None => None, @@ -371,7 +370,7 @@ impl Path { } }; match val { - None => v.as_slice().to_vec(), + None => v.to_vec(), Some(val) => val } } @@ -446,8 +445,7 @@ mod tests { use clone::Clone; use option::Option::{self, Some, None}; use old_path::GenericPath; - use slice::AsSlice; - use str::{self, Str}; + use str; use string::ToString; use vec::Vec; use iter::Iterator; diff --git a/src/libstd/old_path/windows.rs b/src/libstd/old_path/windows.rs index bd67855bf1b..0b88f368b39 100644 --- a/src/libstd/old_path/windows.rs +++ b/src/libstd/old_path/windows.rs @@ -1129,8 +1129,6 @@ mod tests { use iter::Iterator; use option::Option::{self, Some, None}; use old_path::GenericPath; - use slice::AsSlice; - use str::Str; use string::ToString; use vec::Vec; diff --git a/src/libstd/os.rs b/src/libstd/os.rs index e19c734b8a3..ee0f04cb991 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -8,1826 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Higher-level interfaces to libc::* functions and operating system services. -//! -//! In general these take and return rust types, use rust idioms (enums, -//! closures, vectors) rather than C idioms, and do more extensive safety -//! checks. -//! -//! This module is not meant to only contain 1:1 mappings to libc entries; any -//! os-interface code that is reasonably useful and broadly applicable can go -//! here. Including utility routines that merely build on other os code. -//! -//! We assume the general case is that users do not care, and do not want to be -//! made to care, which operating system they are on. While they may want to -//! special case various special cases -- and so we will not _hide_ the facts of -//! which OS the user is on -- they should be given the opportunity to write -//! OS-ignorant code by default. +//! OS-specific functionality -#![unstable(feature = "os")] -#![deprecated(since = "1.0.0", reason = "replaced with std::env APIs")] - -#![allow(missing_docs)] -#![allow(non_snake_case)] -#![allow(unused_imports)] -#![allow(deprecated)] - -use self::MemoryMapKind::*; -use self::MapOption::*; -use self::MapError::*; - -use boxed::Box; -use clone::Clone; -use convert::From; -use env; -use error::{FromError, Error}; -use ffi::{OsString, OsStr}; -use fmt; -use iter::Iterator; -use libc::{c_void, c_int, c_char}; -use libc; -use marker::{Copy, Send}; -use old_io::{IoResult, IoError}; -use ops::{Drop, FnOnce}; -use option::Option::{Some, None}; -use option::Option; -use old_path::{Path, GenericPath, BytesContainer}; -use path::{self, PathBuf}; -use ptr; -use result::Result::{Err, Ok}; -use result::Result; -use slice::AsSlice; -use str::Str; -use str; -use string::{String, ToString}; -use sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering}; -use sys::os as os_imp; -use sys; -use vec::Vec; - -#[cfg(unix)] use ffi::{self, CString}; +#![stable(feature = "os", since = "1.0.0")] #[cfg(unix)] pub use sys::ext as unix; #[cfg(windows)] pub use sys::ext as windows; - -fn err2old(new: ::io::Error) -> IoError { - IoError { - kind: ::old_io::OtherIoError, - desc: "os error", - detail: Some(new.to_string()), - } -} - -#[cfg(windows)] -fn path2new(path: &Path) -> PathBuf { - PathBuf::from(path.as_str().unwrap()) -} -#[cfg(unix)] -fn path2new(path: &Path) -> PathBuf { - use os::unix::prelude::*; - PathBuf::from(::from_bytes(path.as_vec())) -} - -#[cfg(unix)] -fn path2old(path: &path::Path) -> Path { - use os::unix::prelude::*; - use ffi::AsOsStr; - Path::new(path.as_os_str().as_bytes()) -} -#[cfg(windows)] -fn path2old(path: &path::Path) -> Path { - Path::new(path.to_str().unwrap()) -} - -/// Get the number of cores available -pub fn num_cpus() -> usize { - unsafe { - return rust_get_num_cpus() as usize; - } - - extern { - fn rust_get_num_cpus() -> libc::uintptr_t; - } -} - -pub const TMPBUF_SZ : usize = 1000; - -/// Returns the current working directory as a `Path`. -/// -/// # Errors -/// -/// Returns an `Err` if the current working directory value is invalid. -/// Possible cases: -/// -/// * Current directory does not exist. -/// * There are insufficient permissions to access the current directory. -/// * The internal buffer is not large enough to hold the path. -/// -/// # Examples -/// -/// ``` -/// # #![feature(os, old_path)] -/// use std::os; -/// use std::old_path::{Path, GenericPath}; -/// -/// // We assume that we are in a valid directory. -/// let current_working_directory = os::getcwd().unwrap(); -/// println!("The current directory is {:?}", current_working_directory.display()); -/// ``` -#[unstable(feature = "os")] -pub fn getcwd() -> IoResult { - env::current_dir().map_err(err2old).map(|s| path2old(&s)) -} - -/// Returns a vector of (variable, value) pairs, for all the environment -/// variables of the current process. -/// -/// Invalid UTF-8 bytes are replaced with \uFFFD. See `String::from_utf8_lossy()` -/// for details. -/// -/// # Examples -/// -/// ``` -/// # #![feature(os)] -/// use std::os; -/// -/// // We will iterate through the references to the element returned by os::env(); -/// for &(ref key, ref value) in os::env().iter() { -/// println!("'{}': '{}'", key, value ); -/// } -/// ``` -#[deprecated(since = "1.0.0", reason = "use env::vars instead")] -#[unstable(feature = "os")] -pub fn env() -> Vec<(String,String)> { - env::vars_os().map(|(k, v)| { - (k.to_string_lossy().into_owned(), v.to_string_lossy().into_owned()) - }).collect() -} - -/// Returns a vector of (variable, value) byte-vector pairs for all the -/// environment variables of the current process. -#[deprecated(since = "1.0.0", reason = "use env::vars_os instead")] -#[unstable(feature = "os")] -pub fn env_as_bytes() -> Vec<(Vec, Vec)> { - env::vars_os().map(|(k, v)| (byteify(k), byteify(v))).collect() -} - -/// Fetches the environment variable `n` from the current process, returning -/// None if the variable isn't set. -/// -/// Any invalid UTF-8 bytes in the value are replaced by \uFFFD. See -/// `String::from_utf8_lossy()` for details. -/// -/// # Panics -/// -/// Panics if `n` has any interior NULs. -/// -/// # Examples -/// -/// ``` -/// # #![feature(os)] -/// use std::os; -/// -/// let key = "HOME"; -/// match os::getenv(key) { -/// Some(val) => println!("{}: {}", key, val), -/// None => println!("{} is not defined in the environment.", key) -/// } -/// ``` -#[deprecated(since = "1.0.0", reason = "use env::var instead")] -#[unstable(feature = "os")] -pub fn getenv(n: &str) -> Option { - env::var(n).ok() -} - -/// Fetches the environment variable `n` byte vector from the current process, -/// returning None if the variable isn't set. -/// -/// # Panics -/// -/// Panics if `n` has any interior NULs. -#[deprecated(since = "1.0.0", reason = "use env::var_os instead")] -#[unstable(feature = "os")] -pub fn getenv_as_bytes(n: &str) -> Option> { - env::var_os(n).map(byteify) -} - -#[cfg(unix)] -fn byteify(s: OsString) -> Vec { - use os::unix::prelude::*; - s.into_vec() -} -#[cfg(windows)] -fn byteify(s: OsString) -> Vec { - s.to_string_lossy().as_bytes().to_vec() -} - -/// Sets the environment variable `n` to the value `v` for the currently running -/// process. -/// -/// # Examples -/// -/// ``` -/// # #![feature(os)] -/// use std::os; -/// -/// let key = "KEY"; -/// os::setenv(key, "VALUE"); -/// match os::getenv(key) { -/// Some(ref val) => println!("{}: {}", key, val), -/// None => println!("{} is not defined in the environment.", key) -/// } -/// ``` -#[deprecated(since = "1.0.0", reason = "renamed to env::set_var")] -#[unstable(feature = "os")] -pub fn setenv(n: &str, v: T) { - #[cfg(unix)] - fn _setenv(n: &str, v: &[u8]) { - use os::unix::prelude::*; - let v: OsString = OsStringExt::from_vec(v.to_vec()); - env::set_var(n, &v) - } - - #[cfg(windows)] - fn _setenv(n: &str, v: &[u8]) { - let v = str::from_utf8(v).unwrap(); - env::set_var(n, v) - } - - _setenv(n, v.container_as_bytes()) -} - -/// Remove a variable from the environment entirely. -#[deprecated(since = "1.0.0", reason = "renamed to env::remove_var")] -#[unstable(feature = "os")] -pub fn unsetenv(n: &str) { - env::remove_var(n) -} - -/// Parses input according to platform conventions for the `PATH` -/// environment variable. -/// -/// # Examples -/// -/// ``` -/// # #![feature(old_path, os)] -/// use std::os; -/// use std::old_path::{Path, GenericPath}; -/// -/// let key = "PATH"; -/// match os::getenv_as_bytes(key) { -/// Some(paths) => { -/// for path in os::split_paths(paths).iter() { -/// println!("'{}'", path.display()); -/// } -/// } -/// None => println!("{} is not defined in the environment.", key) -/// } -/// ``` -#[unstable(feature = "os")] -pub fn split_paths(unparsed: T) -> Vec { - let b = unparsed.container_as_bytes(); - let s = str::from_utf8(b).unwrap(); - env::split_paths(s).map(|s| path2old(&s)).collect() -} - -/// Joins a collection of `Path`s appropriately for the `PATH` -/// environment variable. -/// -/// Returns a `Vec` on success, since `Path`s are not utf-8 -/// encoded on all platforms. -/// -/// Returns an `Err` (containing an error message) if one of the input -/// `Path`s contains an invalid character for constructing the `PATH` -/// variable (a double quote on Windows or a colon on Unix). -/// -/// # Examples -/// -/// ``` -/// # #![feature(os, old_path, core)] -/// use std::os; -/// use std::old_path::Path; -/// -/// let key = "PATH"; -/// let mut paths = os::getenv_as_bytes(key).map_or(Vec::new(), os::split_paths); -/// paths.push(Path::new("/home/xyz/bin")); -/// os::setenv(key, os::join_paths(paths.as_slice()).unwrap()); -/// ``` -#[unstable(feature = "os")] -pub fn join_paths(paths: &[T]) -> Result, &'static str> { - env::join_paths(paths.iter().map(|s| { - str::from_utf8(s.container_as_bytes()).unwrap() - })).map(|s| { - s.to_string_lossy().into_owned().into_bytes() - }).map_err(|_| "failed to join paths") -} - -/// A low-level OS in-memory pipe. -#[derive(Copy)] -pub struct Pipe { - /// A file descriptor representing the reading end of the pipe. Data written - /// on the `out` file descriptor can be read from this file descriptor. - pub reader: c_int, - /// A file descriptor representing the write end of the pipe. Data written - /// to this file descriptor can be read from the `input` file descriptor. - pub writer: c_int, -} - -/// Creates a new low-level OS in-memory pipe. -/// -/// This function can fail to succeed if there are no more resources available -/// to allocate a pipe. -/// -/// This function is also unsafe as there is no destructor associated with the -/// `Pipe` structure will return. If it is not arranged for the returned file -/// descriptors to be closed, the file descriptors will leak. For safe handling -/// of this scenario, use `std::old_io::PipeStream` instead. -pub unsafe fn pipe() -> IoResult { - let (reader, writer) = try!(sys::os::pipe()); - Ok(Pipe { - reader: reader.unwrap(), - writer: writer.unwrap(), - }) -} - -/// Returns the proper dll filename for the given basename of a file -/// as a String. -#[cfg(not(target_os="ios"))] -#[deprecated(since = "1.0.0", reason = "this function will be removed, use the constants directly")] -#[unstable(feature = "os")] -#[allow(deprecated)] -pub fn dll_filename(base: &str) -> String { - format!("{}{}{}", consts::DLL_PREFIX, base, consts::DLL_SUFFIX) -} - -/// Optionally returns the filesystem path to the current executable which is -/// running but with the executable name. -/// -/// # Examples -/// -/// ``` -/// # #![feature(os, old_path)] -/// use std::os; -/// use std::old_path::{Path, GenericPath}; -/// -/// match os::self_exe_name() { -/// Some(exe_path) => println!("Path of this executable is: {}", exe_path.display()), -/// None => println!("Unable to get the path of this executable!") -/// }; -/// ``` -#[unstable(feature = "os")] -pub fn self_exe_name() -> Option { - env::current_exe().ok().map(|p| path2old(&p)) -} - -/// Optionally returns the filesystem path to the current executable which is -/// running. -/// -/// Like self_exe_name() but without the binary's name. -/// -/// # Examples -/// -/// ``` -/// # #![feature(os, old_path)] -/// use std::os; -/// use std::old_path::{Path, GenericPath}; -/// -/// match os::self_exe_path() { -/// Some(exe_path) => println!("Executable's Path is: {}", exe_path.display()), -/// None => println!("Impossible to fetch the path of this executable.") -/// }; -/// ``` -#[unstable(feature = "os")] -pub fn self_exe_path() -> Option { - env::current_exe().ok().map(|p| { let mut p = path2old(&p); p.pop(); p }) -} - -/// Optionally returns the path to the current user's home directory if known. -/// -/// # Unix -/// -/// Returns the value of the 'HOME' environment variable if it is set -/// and not equal to the empty string. -/// -/// # Windows -/// -/// Returns the value of the 'HOME' environment variable if it is -/// set and not equal to the empty string. Otherwise, returns the value of the -/// 'USERPROFILE' environment variable if it is set and not equal to the empty -/// string. -/// -/// # Examples -/// -/// ``` -/// # #![feature(os, old_path)] -/// use std::os; -/// use std::old_path::{Path, GenericPath}; -/// -/// match os::homedir() { -/// Some(ref p) => println!("{}", p.display()), -/// None => println!("Impossible to get your home dir!") -/// } -/// ``` -#[unstable(feature = "os")] -#[allow(deprecated)] -pub fn homedir() -> Option { - #[inline] - #[cfg(unix)] - fn _homedir() -> Option { - aux_homedir("HOME") - } - - #[inline] - #[cfg(windows)] - fn _homedir() -> Option { - aux_homedir("HOME").or(aux_homedir("USERPROFILE")) - } - - #[inline] - fn aux_homedir(home_name: &str) -> Option { - match getenv_as_bytes(home_name) { - Some(p) => { - if p.is_empty() { None } else { Path::new_opt(p) } - }, - _ => None - } - } - _homedir() -} - -/// Returns the path to a temporary directory. -/// -/// On Unix, returns the value of the 'TMPDIR' environment variable if it is -/// set, otherwise for non-Android it returns '/tmp'. If Android, since there -/// is no global temporary folder (it is usually allocated per-app), we return -/// '/data/local/tmp'. -/// -/// On Windows, returns the value of, in order, the 'TMP', 'TEMP', -/// 'USERPROFILE' environment variable if any are set and not the empty -/// string. Otherwise, tmpdir returns the path to the Windows directory. -#[unstable(feature = "os")] -#[allow(deprecated)] -pub fn tmpdir() -> Path { - return lookup(); - - fn getenv_nonempty(v: &str) -> Option { - match getenv(v) { - Some(x) => - if x.is_empty() { - None - } else { - Path::new_opt(x) - }, - _ => None - } - } - - #[cfg(unix)] - fn lookup() -> Path { - let default = if cfg!(target_os = "android") { - Path::new("/data/local/tmp") - } else { - Path::new("/tmp") - }; - - getenv_nonempty("TMPDIR").unwrap_or(default) - } - - #[cfg(windows)] - fn lookup() -> Path { - getenv_nonempty("TMP").or( - getenv_nonempty("TEMP").or( - getenv_nonempty("USERPROFILE").or( - getenv_nonempty("WINDIR")))).unwrap_or(Path::new("C:\\Windows")) - } -} - -/// Convert a relative path to an absolute path -/// -/// If the given path is relative, return it prepended with the current working -/// directory. If the given path is already an absolute path, return it -/// as is. -/// -/// # Examples -/// -/// ``` -/// # #![feature(os, old_path)] -/// use std::os; -/// use std::old_path::{Path, GenericPath}; -/// -/// // Assume we're in a path like /home/someuser -/// let rel_path = Path::new(".."); -/// let abs_path = os::make_absolute(&rel_path).unwrap(); -/// println!("The absolute path is {}", abs_path.display()); -/// // Prints "The absolute path is /home" -/// ``` -// NB: this is here rather than in path because it is a form of environment -// querying; what it does depends on the process working directory, not just -// the input paths. -#[deprecated(since = "1.0.0", reason = "use env::current_dir + .join directly")] -#[unstable(feature = "os")] -pub fn make_absolute(p: &Path) -> IoResult { - if p.is_absolute() { - Ok(p.clone()) - } else { - env::current_dir().map_err(err2old).map(|cwd| { - let mut cwd = path2old(&cwd); - cwd.push(p); - cwd - }) - } -} - -/// Changes the current working directory to the specified path, returning -/// whether the change was completed successfully or not. -/// -/// # Examples -/// -/// ``` -/// # #![feature(os, old_path)] -/// use std::os; -/// use std::old_path::{Path, GenericPath}; -/// -/// let root = Path::new("/"); -/// assert!(os::change_dir(&root).is_ok()); -/// println!("Successfully changed working directory to {}!", root.display()); -/// ``` -#[unstable(feature = "os")] -pub fn change_dir(p: &Path) -> IoResult<()> { - sys::os::chdir(&path2new(p)).map_err(err2old) -} - -/// Returns the platform-specific value of errno -pub fn errno() -> i32 { - sys::os::errno() as i32 -} - -/// Return the string corresponding to an `errno()` value of `errnum`. -/// -/// # Examples -/// -/// ``` -/// # #![feature(os)] -/// use std::os; -/// -/// // Same as println!("{}", last_os_error()); -/// println!("{}", os::error_string(os::errno() as i32)); -/// ``` -pub fn error_string(errnum: i32) -> String { - return sys::os::error_string(errnum); -} - -/// Get a string representing the platform-dependent last error -pub fn last_os_error() -> String { - error_string(errno()) -} - -/// Sets the process exit code -/// -/// Sets the exit code returned by the process if all supervised tasks -/// terminate successfully (without panicking). If the current root task panics -/// and is supervised by the scheduler then any user-specified exit status is -/// ignored and the process exits with the default panic status. -/// -/// Note that this is not synchronized against modifications of other threads. -#[deprecated(since = "1.0.0", reason = "renamed to env::set_exit_status")] -#[unstable(feature = "os")] -pub fn set_exit_status(code: isize) { - env::set_exit_status(code as i32) -} - -/// Fetches the process's current exit code. This defaults to 0 and can change -/// by calling `set_exit_status`. -#[deprecated(since = "1.0.0", reason = "renamed to env::get_exit_status")] -#[unstable(feature = "os")] -pub fn get_exit_status() -> isize { - env::get_exit_status() as isize -} - -#[cfg(target_os = "macos")] -unsafe fn load_argc_and_argv(argc: isize, - argv: *const *const c_char) -> Vec> { - use ffi::CStr; - - (0..argc).map(|i| { - CStr::from_ptr(*argv.offset(i)).to_bytes().to_vec() - }).collect() -} - -/// Returns the command line arguments -/// -/// Returns a list of the command line arguments. -#[cfg(target_os = "macos")] -fn real_args_as_bytes() -> Vec> { - unsafe { - let (argc, argv) = (*_NSGetArgc() as isize, - *_NSGetArgv() as *const *const c_char); - load_argc_and_argv(argc, argv) - } -} - -// As _NSGetArgc and _NSGetArgv aren't mentioned in iOS docs -// and use underscores in their names - they're most probably -// are considered private and therefore should be avoided -// Here is another way to get arguments using Objective C -// runtime -// -// In general it looks like: -// res = Vec::new() -// let args = [[NSProcessInfo processInfo] arguments] -// for i in 0..[args count] -// res.push([args objectAtIndex:i]) -// res -#[cfg(target_os = "ios")] -fn real_args_as_bytes() -> Vec> { - use ffi::CStr; - use iter::range; - use mem; - - #[link(name = "objc")] - extern { - fn sel_registerName(name: *const libc::c_uchar) -> Sel; - fn objc_msgSend(obj: NsId, sel: Sel, ...) -> NsId; - fn objc_getClass(class_name: *const libc::c_uchar) -> NsId; - } - - #[link(name = "Foundation", kind = "framework")] - extern {} - - type Sel = *const libc::c_void; - type NsId = *const libc::c_void; - - let mut res = Vec::new(); - - unsafe { - let processInfoSel = sel_registerName("processInfo\0".as_ptr()); - let argumentsSel = sel_registerName("arguments\0".as_ptr()); - let utf8Sel = sel_registerName("UTF8String\0".as_ptr()); - let countSel = sel_registerName("count\0".as_ptr()); - let objectAtSel = sel_registerName("objectAtIndex:\0".as_ptr()); - - let klass = objc_getClass("NSProcessInfo\0".as_ptr()); - let info = objc_msgSend(klass, processInfoSel); - let args = objc_msgSend(info, argumentsSel); - - let cnt: isize = mem::transmute(objc_msgSend(args, countSel)); - for i in 0..cnt { - let tmp = objc_msgSend(args, objectAtSel, i); - let utf_c_str: *const libc::c_char = - mem::transmute(objc_msgSend(tmp, utf8Sel)); - res.push(CStr::from_ptr(utf_c_str).to_bytes().to_vec()); - } - } - - res -} - -#[cfg(any(target_os = "linux", - target_os = "android", - target_os = "freebsd", - target_os = "dragonfly", - target_os = "bitrig", - target_os = "openbsd"))] -fn real_args_as_bytes() -> Vec> { - use rt; - rt::args::clone().unwrap_or_else(|| vec![]) -} - -#[cfg(not(windows))] -fn real_args() -> Vec { - real_args_as_bytes().into_iter() - .map(|v| { - String::from_utf8_lossy(&v).into_owned() - }).collect() -} - -#[cfg(windows)] -fn real_args() -> Vec { - use slice; - use iter::range; - - let mut nArgs: c_int = 0; - let lpArgCount: *mut c_int = &mut nArgs; - let lpCmdLine = unsafe { GetCommandLineW() }; - let szArgList = unsafe { CommandLineToArgvW(lpCmdLine, lpArgCount) }; - - let args: Vec<_> = (0..nArgs as usize).map(|i| unsafe { - // Determine the length of this argument. - let ptr = *szArgList.offset(i as isize); - let mut len = 0; - while *ptr.offset(len as isize) != 0 { len += 1; } - - // Push it onto the list. - let ptr = ptr as *const u16; - let buf = slice::from_raw_parts(ptr, len); - let opt_s = String::from_utf16(sys::truncate_utf16_at_nul(buf)); - opt_s.ok().expect("CommandLineToArgvW returned invalid UTF-16") - }).collect(); - - unsafe { - LocalFree(szArgList as *mut c_void); - } - - return args -} - -#[cfg(windows)] -fn real_args_as_bytes() -> Vec> { - real_args().into_iter().map(|s| s.into_bytes()).collect() -} - -type LPCWSTR = *const u16; - -#[cfg(windows)] -#[link_name="kernel32"] -extern "system" { - fn GetCommandLineW() -> LPCWSTR; - fn LocalFree(ptr: *mut c_void); -} - -#[cfg(windows)] -#[link_name="shell32"] -extern "system" { - fn CommandLineToArgvW(lpCmdLine: LPCWSTR, - pNumArgs: *mut c_int) -> *mut *mut u16; -} - -/// Returns the arguments which this program was started with (normally passed -/// via the command line). -/// -/// The first element is traditionally the path to the executable, but it can be -/// set to arbitrary text, and it may not even exist, so this property should not -/// be relied upon for security purposes. -/// -/// The arguments are interpreted as utf-8, with invalid bytes replaced with \uFFFD. -/// See `String::from_utf8_lossy` for details. -/// # Examples -/// -/// ``` -/// # #![feature(os)] -/// use std::os; -/// -/// // Prints each argument on a separate line -/// for argument in os::args().iter() { -/// println!("{}", argument); -/// } -/// ``` -#[deprecated(since = "1.0.0", reason = "use std::env::args() instead")] -#[unstable(feature = "os")] -pub fn args() -> Vec { - real_args() -} - -/// Returns the arguments which this program was started with (normally passed -/// via the command line) as byte vectors. -#[deprecated(since = "1.0.0", reason = "use env::args_os instead")] -#[unstable(feature = "os")] -pub fn args_as_bytes() -> Vec> { - real_args_as_bytes() -} - -#[cfg(target_os = "macos")] -extern { - // These functions are in crt_externs.h. - fn _NSGetArgc() -> *mut c_int; - fn _NSGetArgv() -> *mut *mut *mut c_char; -} - -/// Returns the page size of the current architecture in bytes. -#[deprecated(since = "1.0.0", reason = "renamed to env::page_size")] -#[unstable(feature = "os")] -pub fn page_size() -> usize { - sys::os::page_size() -} - -/// A memory mapped file or chunk of memory. This is a very system-specific -/// interface to the OS's memory mapping facilities (`mmap` on POSIX, -/// `VirtualAlloc`/`CreateFileMapping` on Windows). It makes no attempt at -/// abstracting platform differences, besides in error values returned. Consider -/// yourself warned. -/// -/// The memory map is released (unmapped) when the destructor is run, so don't -/// let it leave scope by accident if you want it to stick around. -pub struct MemoryMap { - data: *mut u8, - len: usize, - kind: MemoryMapKind, -} - -/// Type of memory map -#[allow(raw_pointer_derive)] -#[derive(Copy)] -pub enum MemoryMapKind { - /// Virtual memory map. Usually used to change the permissions of a given - /// chunk of memory. Corresponds to `VirtualAlloc` on Windows. - MapFile(*const u8), - /// Virtual memory map. Usually used to change the permissions of a given - /// chunk of memory, or for allocation. Corresponds to `VirtualAlloc` on - /// Windows. - MapVirtual -} - -/// Options the memory map is created with -#[allow(raw_pointer_derive)] -#[derive(Copy)] -pub enum MapOption { - /// The memory should be readable - MapReadable, - /// The memory should be writable - MapWritable, - /// The memory should be executable - MapExecutable, - /// Create a map for a specific address range. Corresponds to `MAP_FIXED` on - /// POSIX. - MapAddr(*const u8), - /// Create a memory mapping for a file with a given HANDLE. - #[cfg(windows)] - MapFd(libc::HANDLE), - /// Create a memory mapping for a file with a given fd. - #[cfg(not(windows))] - MapFd(c_int), - /// When using `MapFd`, the start of the map is `usize` bytes from the start - /// of the file. - MapOffset(usize), - /// On POSIX, this can be used to specify the default flags passed to - /// `mmap`. By default it uses `MAP_PRIVATE` and, if not using `MapFd`, - /// `MAP_ANON`. This will override both of those. This is platform-specific - /// (the exact values used) and ignored on Windows. - MapNonStandardFlags(c_int), -} - -/// Possible errors when creating a map. -#[derive(Copy, Debug)] -pub enum MapError { - /// # The following are POSIX-specific - /// - /// fd was not open for reading or, if using `MapWritable`, was not open for - /// writing. - ErrFdNotAvail, - /// fd was not valid - ErrInvalidFd, - /// Either the address given by `MapAddr` or offset given by `MapOffset` was - /// not a multiple of `MemoryMap::granularity` (unaligned to page size). - ErrUnaligned, - /// With `MapFd`, the fd does not support mapping. - ErrNoMapSupport, - /// If using `MapAddr`, the address + `min_len` was outside of the process's - /// address space. If using `MapFd`, the target of the fd didn't have enough - /// resources to fulfill the request. - ErrNoMem, - /// A zero-length map was requested. This is invalid according to - /// [POSIX](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mmap.html). - /// Not all platforms obey this, but this wrapper does. - ErrZeroLength, - /// Unrecognized error. The inner value is the unrecognized errno. - ErrUnknown(isize), - /// # The following are Windows-specific - /// - /// Unsupported combination of protection flags - /// (`MapReadable`/`MapWritable`/`MapExecutable`). - ErrUnsupProt, - /// When using `MapFd`, `MapOffset` was given (Windows does not support this - /// at all) - ErrUnsupOffset, - /// When using `MapFd`, there was already a mapping to the file. - ErrAlreadyExists, - /// Unrecognized error from `VirtualAlloc`. The inner value is the return - /// value of GetLastError. - ErrVirtualAlloc(i32), - /// Unrecognized error from `CreateFileMapping`. The inner value is the - /// return value of `GetLastError`. - ErrCreateFileMappingW(i32), - /// Unrecognized error from `MapViewOfFile`. The inner value is the return - /// value of `GetLastError`. - ErrMapViewOfFile(i32) -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for MapError { - fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result { - let str = match *self { - ErrFdNotAvail => "fd not available for reading or writing", - ErrInvalidFd => "Invalid fd", - ErrUnaligned => { - "Unaligned address, invalid flags, negative length or \ - unaligned offset" - } - ErrNoMapSupport=> "File doesn't support mapping", - ErrNoMem => "Invalid address, or not enough available memory", - ErrUnsupProt => "Protection mode unsupported", - ErrUnsupOffset => "Offset in virtual memory mode is unsupported", - ErrAlreadyExists => "File mapping for specified file already exists", - ErrZeroLength => "Zero-length mapping not allowed", - ErrUnknown(code) => { - return write!(out, "Unknown error = {}", code) - }, - ErrVirtualAlloc(code) => { - return write!(out, "VirtualAlloc failure = {}", code) - }, - ErrCreateFileMappingW(code) => { - return write!(out, "CreateFileMappingW failure = {}", code) - }, - ErrMapViewOfFile(code) => { - return write!(out, "MapViewOfFile failure = {}", code) - } - }; - write!(out, "{}", str) - } -} - -impl Error for MapError { - fn description(&self) -> &str { "memory map error" } -} - -// Round up `from` to be divisible by `to` -fn round_up(from: usize, to: usize) -> usize { - let r = if from % to == 0 { - from - } else { - from + to - (from % to) - }; - if r == 0 { - to - } else { - r - } -} - -#[cfg(unix)] -impl MemoryMap { - /// Create a new mapping with the given `options`, at least `min_len` bytes - /// long. `min_len` must be greater than zero; see the note on - /// `ErrZeroLength`. - pub fn new(min_len: usize, options: &[MapOption]) -> Result { - use libc::off_t; - - if min_len == 0 { - return Err(ErrZeroLength) - } - let mut addr: *const u8 = ptr::null(); - let mut prot = 0; - let mut flags = libc::MAP_PRIVATE; - let mut fd = -1; - let mut offset = 0; - let mut custom_flags = false; - let len = round_up(min_len, env::page_size()); - - for &o in options { - match o { - MapReadable => { prot |= libc::PROT_READ; }, - MapWritable => { prot |= libc::PROT_WRITE; }, - MapExecutable => { prot |= libc::PROT_EXEC; }, - MapAddr(addr_) => { - flags |= libc::MAP_FIXED; - addr = addr_; - }, - MapFd(fd_) => { - flags |= libc::MAP_FILE; - fd = fd_; - }, - MapOffset(offset_) => { offset = offset_ as off_t; }, - MapNonStandardFlags(f) => { custom_flags = true; flags = f }, - } - } - if fd == -1 && !custom_flags { flags |= libc::MAP_ANON; } - - let r = unsafe { - libc::mmap(addr as *mut c_void, len as libc::size_t, prot, flags, - fd, offset) - }; - if r == libc::MAP_FAILED { - Err(match errno() as c_int { - libc::EACCES => ErrFdNotAvail, - libc::EBADF => ErrInvalidFd, - libc::EINVAL => ErrUnaligned, - libc::ENODEV => ErrNoMapSupport, - libc::ENOMEM => ErrNoMem, - code => ErrUnknown(code as isize) - }) - } else { - Ok(MemoryMap { - data: r as *mut u8, - len: len, - kind: if fd == -1 { - MapVirtual - } else { - MapFile(ptr::null()) - } - }) - } - } - - /// Granularity that the offset or address must be for `MapOffset` and - /// `MapAddr` respectively. - pub fn granularity() -> usize { - env::page_size() - } -} - -#[cfg(unix)] -impl Drop for MemoryMap { - /// Unmap the mapping. Panics the task if `munmap` panics. - fn drop(&mut self) { - if self.len == 0 { /* workaround for dummy_stack */ return; } - - unsafe { - // `munmap` only panics due to logic errors - libc::munmap(self.data as *mut c_void, self.len as libc::size_t); - } - } -} - -#[cfg(windows)] -impl MemoryMap { - /// Create a new mapping with the given `options`, at least `min_len` bytes long. - pub fn new(min_len: usize, options: &[MapOption]) -> Result { - use libc::types::os::arch::extra::{LPVOID, DWORD, SIZE_T, HANDLE}; - - let mut lpAddress: LPVOID = ptr::null_mut(); - let mut readable = false; - let mut writable = false; - let mut executable = false; - let mut handle: HANDLE = libc::INVALID_HANDLE_VALUE; - let mut offset: usize = 0; - let len = round_up(min_len, env::page_size()); - - for &o in options { - match o { - MapReadable => { readable = true; }, - MapWritable => { writable = true; }, - MapExecutable => { executable = true; } - MapAddr(addr_) => { lpAddress = addr_ as LPVOID; }, - MapFd(handle_) => { handle = handle_; }, - MapOffset(offset_) => { offset = offset_; }, - MapNonStandardFlags(..) => {} - } - } - - let flProtect = match (executable, readable, writable) { - (false, false, false) if handle == libc::INVALID_HANDLE_VALUE => libc::PAGE_NOACCESS, - (false, true, false) => libc::PAGE_READONLY, - (false, true, true) => libc::PAGE_READWRITE, - (true, false, false) if handle == libc::INVALID_HANDLE_VALUE => libc::PAGE_EXECUTE, - (true, true, false) => libc::PAGE_EXECUTE_READ, - (true, true, true) => libc::PAGE_EXECUTE_READWRITE, - _ => return Err(ErrUnsupProt) - }; - - if handle == libc::INVALID_HANDLE_VALUE { - if offset != 0 { - return Err(ErrUnsupOffset); - } - let r = unsafe { - libc::VirtualAlloc(lpAddress, - len as SIZE_T, - libc::MEM_COMMIT | libc::MEM_RESERVE, - flProtect) - }; - match r as usize { - 0 => Err(ErrVirtualAlloc(errno())), - _ => Ok(MemoryMap { - data: r as *mut u8, - len: len, - kind: MapVirtual - }) - } - } else { - let dwDesiredAccess = match (executable, readable, writable) { - (false, true, false) => libc::FILE_MAP_READ, - (false, true, true) => libc::FILE_MAP_WRITE, - (true, true, false) => libc::FILE_MAP_READ | libc::FILE_MAP_EXECUTE, - (true, true, true) => libc::FILE_MAP_WRITE | libc::FILE_MAP_EXECUTE, - _ => return Err(ErrUnsupProt) // Actually, because of the check above, - // we should never get here. - }; - unsafe { - let hFile = handle; - let mapping = libc::CreateFileMappingW(hFile, - ptr::null_mut(), - flProtect, - 0, - 0, - ptr::null()); - if mapping == ptr::null_mut() { - return Err(ErrCreateFileMappingW(errno())); - } - if errno() as c_int == libc::ERROR_ALREADY_EXISTS { - return Err(ErrAlreadyExists); - } - let r = libc::MapViewOfFile(mapping, - dwDesiredAccess, - ((len as u64) >> 32) as DWORD, - (offset & 0xffff_ffff) as DWORD, - 0); - match r as usize { - 0 => Err(ErrMapViewOfFile(errno())), - _ => Ok(MemoryMap { - data: r as *mut u8, - len: len, - kind: MapFile(mapping as *const u8) - }) - } - } - } - } - - /// Granularity of MapAddr() and MapOffset() parameter values. - /// This may be greater than the value returned by page_size(). - pub fn granularity() -> usize { - use mem; - unsafe { - let mut info = mem::zeroed(); - libc::GetSystemInfo(&mut info); - - return info.dwAllocationGranularity as usize; - } - } -} - -#[cfg(windows)] -impl Drop for MemoryMap { - /// Unmap the mapping. Panics the task if any of `VirtualFree`, - /// `UnmapViewOfFile`, or `CloseHandle` fail. - fn drop(&mut self) { - use libc::types::os::arch::extra::{LPCVOID, HANDLE}; - use libc::consts::os::extra::FALSE; - if self.len == 0 { return } - - unsafe { - match self.kind { - MapVirtual => { - if libc::VirtualFree(self.data as *mut c_void, 0, - libc::MEM_RELEASE) == 0 { - println!("VirtualFree failed: {}", errno()); - } - }, - MapFile(mapping) => { - if libc::UnmapViewOfFile(self.data as LPCVOID) == FALSE { - println!("UnmapViewOfFile failed: {}", errno()); - } - if libc::CloseHandle(mapping as HANDLE) == FALSE { - println!("CloseHandle failed: {}", errno()); - } - } - } - } - } -} - -impl MemoryMap { - /// Returns the pointer to the memory created or modified by this map. - pub fn data(&self) -> *mut u8 { self.data } - /// Returns the number of bytes this map applies to. - pub fn len(&self) -> usize { self.len } - /// Returns the type of mapping this represents. - pub fn kind(&self) -> MemoryMapKind { self.kind } -} - -#[cfg(target_os = "linux")] -#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] -#[unstable(feature = "os")] -pub mod consts { - pub use os::arch_consts::ARCH; - - pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `linux`. - pub const SYSNAME: &'static str = "linux"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, `lib`. - pub const DLL_PREFIX: &'static str = "lib"; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.so`. - pub const DLL_SUFFIX: &'static str = ".so"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `so`. - pub const DLL_EXTENSION: &'static str = "so"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. - pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. - pub const EXE_EXTENSION: &'static str = ""; -} - -#[cfg(target_os = "macos")] -#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] -#[unstable(feature = "os")] -pub mod consts { - pub use os::arch_consts::ARCH; - - pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `macos`. - pub const SYSNAME: &'static str = "macos"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, `lib`. - pub const DLL_PREFIX: &'static str = "lib"; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.dylib`. - pub const DLL_SUFFIX: &'static str = ".dylib"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `dylib`. - pub const DLL_EXTENSION: &'static str = "dylib"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. - pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. - pub const EXE_EXTENSION: &'static str = ""; -} - -#[cfg(target_os = "ios")] -#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] -#[unstable(feature = "os")] -pub mod consts { - pub use os::arch_consts::ARCH; - - pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `ios`. - pub const SYSNAME: &'static str = "ios"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. - pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. - pub const EXE_EXTENSION: &'static str = ""; -} - -#[cfg(target_os = "freebsd")] -#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] -#[unstable(feature = "os")] -pub mod consts { - pub use os::arch_consts::ARCH; - - pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `freebsd`. - pub const SYSNAME: &'static str = "freebsd"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, `lib`. - pub const DLL_PREFIX: &'static str = "lib"; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.so`. - pub const DLL_SUFFIX: &'static str = ".so"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `so`. - pub const DLL_EXTENSION: &'static str = "so"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. - pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. - pub const EXE_EXTENSION: &'static str = ""; -} - -#[cfg(target_os = "dragonfly")] -#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] -#[unstable(feature = "os")] -pub mod consts { - pub use os::arch_consts::ARCH; - - pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `dragonfly`. - pub const SYSNAME: &'static str = "dragonfly"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, `lib`. - pub const DLL_PREFIX: &'static str = "lib"; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.so`. - pub const DLL_SUFFIX: &'static str = ".so"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `so`. - pub const DLL_EXTENSION: &'static str = "so"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. - pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. - pub const EXE_EXTENSION: &'static str = ""; -} - -#[cfg(target_os = "bitrig")] -#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] -#[unstable(feature = "os")] -pub mod consts { - pub use os::arch_consts::ARCH; - - pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `bitrig`. - pub const SYSNAME: &'static str = "bitrig"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, `lib`. - pub const DLL_PREFIX: &'static str = "lib"; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.so`. - pub const DLL_SUFFIX: &'static str = ".so"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `so`. - pub const DLL_EXTENSION: &'static str = "so"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. - pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. - pub const EXE_EXTENSION: &'static str = ""; -} - -#[cfg(target_os = "openbsd")] -#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] -#[unstable(feature = "os")] -pub mod consts { - pub use os::arch_consts::ARCH; - - pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `openbsd`. - pub const SYSNAME: &'static str = "openbsd"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, `lib`. - pub const DLL_PREFIX: &'static str = "lib"; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.so`. - pub const DLL_SUFFIX: &'static str = ".so"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `so`. - pub const DLL_EXTENSION: &'static str = "so"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. - pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. - pub const EXE_EXTENSION: &'static str = ""; -} - -#[cfg(target_os = "android")] -#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] -#[unstable(feature = "os")] -pub mod consts { - pub use os::arch_consts::ARCH; - - pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `android`. - pub const SYSNAME: &'static str = "android"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, `lib`. - pub const DLL_PREFIX: &'static str = "lib"; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.so`. - pub const DLL_SUFFIX: &'static str = ".so"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `so`. - pub const DLL_EXTENSION: &'static str = "so"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. - pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. - pub const EXE_EXTENSION: &'static str = ""; -} - -#[cfg(target_os = "windows")] -#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] -#[unstable(feature = "os")] -pub mod consts { - pub use os::arch_consts::ARCH; - - pub const FAMILY: &'static str = "windows"; - - /// A string describing the specific operating system in use: in this - /// case, `windows`. - pub const SYSNAME: &'static str = "windows"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, the empty string. - pub const DLL_PREFIX: &'static str = ""; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.dll`. - pub const DLL_SUFFIX: &'static str = ".dll"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `dll`. - pub const DLL_EXTENSION: &'static str = "dll"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, `.exe`. - pub const EXE_SUFFIX: &'static str = ".exe"; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, `exe`. - pub const EXE_EXTENSION: &'static str = "exe"; -} - -#[cfg(target_arch = "x86")] -mod arch_consts { - pub const ARCH: &'static str = "x86"; -} - -#[cfg(target_arch = "x86_64")] -mod arch_consts { - pub const ARCH: &'static str = "x86_64"; -} - -#[cfg(target_arch = "arm")] -mod arch_consts { - pub const ARCH: &'static str = "arm"; -} - -#[cfg(target_arch = "aarch64")] -mod arch_consts { - pub const ARCH: &'static str = "aarch64"; -} - -#[cfg(target_arch = "mips")] -mod arch_consts { - pub const ARCH: &'static str = "mips"; -} - -#[cfg(target_arch = "mipsel")] -mod arch_consts { - pub const ARCH: &'static str = "mipsel"; -} - -#[cfg(target_arch = "powerpc")] -mod arch_consts { - pub const ARCH: &'static str = "powerpc"; -} - -#[cfg(test)] -mod tests { - #![allow(deprecated)] // rand - - use prelude::v1::*; - - use iter::repeat; - use os::{env, getcwd, getenv, make_absolute}; - use os::{split_paths, join_paths, setenv, unsetenv}; - use os; - use rand::Rng; - use rand; - use old_path::{Path, GenericPath}; - use old_io::{Reader, Writer, Seek}; - - #[test] - pub fn last_os_error() { - debug!("{}", os::last_os_error()); - } - - fn make_rand_name() -> String { - let mut rng = rand::thread_rng(); - let n = format!("TEST{}", rng.gen_ascii_chars().take(10) - .collect::()); - assert!(getenv(&n).is_none()); - n - } - - #[test] - fn test_num_cpus() { - assert!(os::num_cpus() > 0); - } - - #[test] - fn test_setenv() { - let n = make_rand_name(); - setenv(&n, "VALUE"); - assert_eq!(getenv(&n), Some("VALUE".to_string())); - } - - #[test] - fn test_unsetenv() { - let n = make_rand_name(); - setenv(&n, "VALUE"); - unsetenv(&n); - assert_eq!(getenv(&n), None); - } - - #[test] - #[ignore] - fn test_setenv_overwrite() { - let n = make_rand_name(); - setenv(&n, "1"); - setenv(&n, "2"); - assert_eq!(getenv(&n), Some("2".to_string())); - setenv(&n, ""); - assert_eq!(getenv(&n), Some("".to_string())); - } - - // Windows GetEnvironmentVariable requires some extra work to make sure - // the buffer the variable is copied into is the right size - #[test] - #[ignore] - fn test_getenv_big() { - let mut s = "".to_string(); - let mut i = 0; - while i < 100 { - s.push_str("aaaaaaaaaa"); - i += 1; - } - let n = make_rand_name(); - setenv(&n, &s); - debug!("{}", s.clone()); - assert_eq!(getenv(&n), Some(s)); - } - - #[test] - fn test_self_exe_name() { - let path = os::self_exe_name(); - assert!(path.is_some()); - let path = path.unwrap(); - debug!("{}", path.display()); - - // Hard to test this function - assert!(path.is_absolute()); - } - - #[test] - fn test_self_exe_path() { - let path = os::self_exe_path(); - assert!(path.is_some()); - let path = path.unwrap(); - debug!("{}", path.display()); - - // Hard to test this function - assert!(path.is_absolute()); - } - - #[test] - #[ignore] - fn test_env_getenv() { - let e = env(); - assert!(e.len() > 0); - for p in &e { - let (n, v) = (*p).clone(); - debug!("{}", n); - let v2 = getenv(&n); - // MingW seems to set some funky environment variables like - // "=C:=C:\MinGW\msys\1.0\bin" and "!::=::\" that are returned - // from env() but not visible from getenv(). - assert!(v2.is_none() || v2 == Some(v)); - } - } - - #[test] - fn test_env_set_get_huge() { - let n = make_rand_name(); - let s = repeat("x").take(10000).collect::(); - setenv(&n, &s); - assert_eq!(getenv(&n), Some(s)); - unsetenv(&n); - assert_eq!(getenv(&n), None); - } - - #[test] - fn test_env_setenv() { - let n = make_rand_name(); - - let mut e = env(); - setenv(&n, "VALUE"); - assert!(!e.contains(&(n.clone(), "VALUE".to_string()))); - - e = env(); - assert!(e.contains(&(n, "VALUE".to_string()))); - } - - #[test] - fn test() { - assert!((!Path::new("test-path").is_absolute())); - - let cwd = getcwd().unwrap(); - debug!("Current working directory: {}", cwd.display()); - - debug!("{}", make_absolute(&Path::new("test-path")).unwrap().display()); - debug!("{}", make_absolute(&Path::new("/usr/bin")).unwrap().display()); - } - - #[test] - #[cfg(unix)] - fn homedir() { - let oldhome = getenv("HOME"); - - setenv("HOME", "/home/MountainView"); - assert!(os::homedir() == Some(Path::new("/home/MountainView"))); - - setenv("HOME", ""); - assert!(os::homedir().is_none()); - - if let Some(s) = oldhome { - setenv("HOME", s); - } - } - - #[test] - #[cfg(windows)] - fn homedir() { - - let oldhome = getenv("HOME"); - let olduserprofile = getenv("USERPROFILE"); - - setenv("HOME", ""); - setenv("USERPROFILE", ""); - - assert!(os::homedir().is_none()); - - setenv("HOME", "/home/MountainView"); - assert!(os::homedir() == Some(Path::new("/home/MountainView"))); - - setenv("HOME", ""); - - setenv("USERPROFILE", "/home/MountainView"); - assert!(os::homedir() == Some(Path::new("/home/MountainView"))); - - setenv("HOME", "/home/MountainView"); - setenv("USERPROFILE", "/home/PaloAlto"); - assert!(os::homedir() == Some(Path::new("/home/MountainView"))); - - if let Some(s) = oldhome { - setenv("HOME", &s); - } - if let Some(s) = olduserprofile { - setenv("USERPROFILE", &s); - } - } - - #[test] - fn memory_map_rw() { - use result::Result::{Ok, Err}; - - let chunk = match os::MemoryMap::new(16, &[ - os::MapOption::MapReadable, - os::MapOption::MapWritable - ]) { - Ok(chunk) => chunk, - Err(msg) => panic!("{:?}", msg) - }; - assert!(chunk.len >= 16); - - unsafe { - *chunk.data = 0xBE; - assert!(*chunk.data == 0xBE); - } - } - - #[test] - fn memory_map_file() { - use libc; - use os::*; - use old_io::fs::{File, unlink}; - use old_io::SeekStyle::SeekSet; - use old_io::FileMode::Open; - use old_io::FileAccess::ReadWrite; - - #[cfg(not(windows))] - fn get_fd(file: &File) -> libc::c_int { - use os::unix::prelude::*; - file.as_raw_fd() - } - - #[cfg(windows)] - fn get_fd(file: &File) -> libc::HANDLE { - use os::windows::prelude::*; - file.as_raw_handle() - } - - let mut path = tmpdir(); - path.push("mmap_file.tmp"); - let size = MemoryMap::granularity() * 2; - let mut file = File::open_mode(&path, Open, ReadWrite).unwrap(); - file.seek(size as i64, SeekSet).unwrap(); - file.write_u8(0).unwrap(); - - let chunk = MemoryMap::new(size / 2, &[ - MapOption::MapReadable, - MapOption::MapWritable, - MapOption::MapFd(get_fd(&file)), - MapOption::MapOffset(size / 2) - ]).unwrap(); - assert!(chunk.len > 0); - - unsafe { - *chunk.data = 0xbe; - assert!(*chunk.data == 0xbe); - } - drop(chunk); - - unlink(&path).unwrap(); - } - - #[test] - #[cfg(windows)] - fn split_paths_windows() { - fn check_parse(unparsed: &str, parsed: &[&str]) -> bool { - split_paths(unparsed) == - parsed.iter().map(|s| Path::new(*s)).collect::>() - } - - assert!(check_parse("", &mut [""])); - assert!(check_parse(r#""""#, &mut [""])); - assert!(check_parse(";;", &mut ["", "", ""])); - assert!(check_parse(r"c:\", &mut [r"c:\"])); - assert!(check_parse(r"c:\;", &mut [r"c:\", ""])); - assert!(check_parse(r"c:\;c:\Program Files\", - &mut [r"c:\", r"c:\Program Files\"])); - assert!(check_parse(r#"c:\;c:\"foo"\"#, &mut [r"c:\", r"c:\foo\"])); - assert!(check_parse(r#"c:\;c:\"foo;bar"\;c:\baz"#, - &mut [r"c:\", r"c:\foo;bar\", r"c:\baz"])); - } - - #[test] - #[cfg(unix)] - fn split_paths_unix() { - fn check_parse(unparsed: &str, parsed: &[&str]) -> bool { - split_paths(unparsed) == - parsed.iter().map(|s| Path::new(*s)).collect::>() - } - - assert!(check_parse("", &mut [""])); - assert!(check_parse("::", &mut ["", "", ""])); - assert!(check_parse("/", &mut ["/"])); - assert!(check_parse("/:", &mut ["/", ""])); - assert!(check_parse("/:/usr/local", &mut ["/", "/usr/local"])); - } - - #[test] - #[cfg(unix)] - fn join_paths_unix() { - fn test_eq(input: &[&str], output: &str) -> bool { - join_paths(input).unwrap() == output.as_bytes() - } - - assert!(test_eq(&[], "")); - assert!(test_eq(&["/bin", "/usr/bin", "/usr/local/bin"], - "/bin:/usr/bin:/usr/local/bin")); - assert!(test_eq(&["", "/bin", "", "", "/usr/bin", ""], - ":/bin:::/usr/bin:")); - assert!(join_paths(&["/te:st"]).is_err()); - } - - #[test] - #[cfg(windows)] - fn join_paths_windows() { - fn test_eq(input: &[&str], output: &str) -> bool { - join_paths(input).unwrap() == output.as_bytes() - } - - assert!(test_eq(&[], "")); - assert!(test_eq(&[r"c:\windows", r"c:\"], - r"c:\windows;c:\")); - assert!(test_eq(&["", r"c:\windows", "", "", r"c:\", ""], - r";c:\windows;;;c:\;")); - assert!(test_eq(&[r"c:\te;st", r"c:\"], - r#""c:\te;st";c:\"#)); - assert!(join_paths(&[r#"c:\te"st"#]).is_err()); - } - - // More recursive_mkdir tests are in extra::tempfile -} diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 58d3ae9f7cf..9006ed33654 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -35,7 +35,6 @@ //! To build or modify paths, use `PathBuf`: //! //! ```rust -//! # #![feature(convert)] //! use std::path::PathBuf; //! //! let mut path = PathBuf::from("c:\\"); @@ -521,9 +520,9 @@ impl<'a> Component<'a> { pub fn as_os_str(self) -> &'a OsStr { match self { Component::Prefix(p) => p.as_os_str(), - Component::RootDir => OsStr::from_str(MAIN_SEP_STR), - Component::CurDir => OsStr::from_str("."), - Component::ParentDir => OsStr::from_str(".."), + Component::RootDir => OsStr::new(MAIN_SEP_STR), + Component::CurDir => OsStr::new("."), + Component::ParentDir => OsStr::new(".."), Component::Normal(path) => path, } } @@ -893,7 +892,6 @@ impl<'a> cmp::Ord for Components<'a> { /// # Examples /// /// ``` -/// # #![feature(convert)] /// use std::path::PathBuf; /// /// let mut path = PathBuf::from("c:\\"); @@ -918,6 +916,12 @@ impl PathBuf { PathBuf { inner: OsString::new() } } + /// Coerce to a `Path` slice. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn as_path(&self) -> &Path { + self + } + /// Extend `self` with `path`. /// /// If `path` is absolute, it replaces the current path. @@ -985,7 +989,6 @@ impl PathBuf { /// # Examples /// /// ``` - /// # #![feature(convert)] /// use std::path::PathBuf; /// /// let mut buf = PathBuf::from("/"); @@ -1318,7 +1321,7 @@ impl Path { #[stable(feature = "rust1", since = "1.0.0")] pub fn file_name(&self) -> Option<&OsStr> { self.components().next_back().and_then(|p| match p { - Component::Normal(p) => Some(p.as_os_str()), + Component::Normal(p) => Some(p.as_ref()), _ => None }) } diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs index 297eccb9f76..84a45086767 100644 --- a/src/libstd/prelude/v1.rs +++ b/src/libstd/prelude/v1.rs @@ -42,12 +42,11 @@ #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use result::Result::{self, Ok, Err}; #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated)] -#[doc(no_inline)] pub use slice::{SliceConcatExt, AsSlice}; -#[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated)] -#[doc(no_inline)] pub use str::Str; +#[doc(no_inline)] pub use slice::SliceConcatExt; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use string::{String, ToString}; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use vec::Vec; + +#[allow(deprecated)] pub use slice::AsSlice; +#[allow(deprecated)] pub use str::Str; diff --git a/src/libstd/process.rs b/src/libstd/process.rs index b4bd513e8f0..52f5965db80 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -16,15 +16,15 @@ use prelude::v1::*; use io::prelude::*; -use ffi::AsOsStr; +use ffi::OsStr; use fmt; use io::{self, Error, ErrorKind}; use libc; use path; use sync::mpsc::{channel, Receiver}; use sys::pipe2::{self, AnonPipe}; -use sys::process2::Process as ProcessImp; use sys::process2::Command as CommandImp; +use sys::process2::Process as ProcessImp; use sys::process2::ExitStatus as ExitStatusImp; use sys_common::{AsInner, AsInnerMut}; use thread; @@ -147,9 +147,9 @@ impl Command { /// Builder methods are provided to change these defaults and /// otherwise configure the process. #[stable(feature = "process", since = "1.0.0")] - pub fn new(program: S) -> Command { + pub fn new>(program: S) -> Command { Command { - inner: CommandImp::new(program.as_os_str()), + inner: CommandImp::new(program.as_ref()), stdin: None, stdout: None, stderr: None, @@ -158,15 +158,15 @@ impl Command { /// Add an argument to pass to the program. #[stable(feature = "process", since = "1.0.0")] - pub fn arg(&mut self, arg: S) -> &mut Command { - self.inner.arg(arg.as_os_str()); + pub fn arg>(&mut self, arg: S) -> &mut Command { + self.inner.arg(arg.as_ref()); self } /// Add multiple arguments to pass to the program. #[stable(feature = "process", since = "1.0.0")] - pub fn args(&mut self, args: &[S]) -> &mut Command { - self.inner.args(args.iter().map(AsOsStr::as_os_str)); + pub fn args>(&mut self, args: &[S]) -> &mut Command { + self.inner.args(args.iter().map(AsRef::as_ref)); self } @@ -176,16 +176,16 @@ impl Command { /// and case-sensitive on all other platforms. #[stable(feature = "process", since = "1.0.0")] pub fn env(&mut self, key: K, val: V) -> &mut Command - where K: AsOsStr, V: AsOsStr + where K: AsRef, V: AsRef { - self.inner.env(key.as_os_str(), val.as_os_str()); + self.inner.env(key.as_ref(), val.as_ref()); self } /// Removes an environment variable mapping. #[stable(feature = "process", since = "1.0.0")] - pub fn env_remove(&mut self, key: K) -> &mut Command { - self.inner.env_remove(key.as_os_str()); + pub fn env_remove>(&mut self, key: K) -> &mut Command { + self.inner.env_remove(key.as_ref()); self } @@ -199,7 +199,7 @@ impl Command { /// Set the working directory for the child process. #[stable(feature = "process", since = "1.0.0")] pub fn current_dir>(&mut self, dir: P) -> &mut Command { - self.inner.cwd(dir.as_ref().as_os_str()); + self.inner.cwd(dir.as_ref().as_ref()); self } @@ -378,11 +378,6 @@ enum StdioImp { } impl Stdio { - /// A new pipe should be arranged to connect the parent and child processes. - #[unstable(feature = "process_capture")] - #[deprecated(since = "1.0.0", reason = "renamed to `Stdio::piped`")] - pub fn capture() -> Stdio { Stdio::piped() } - /// A new pipe should be arranged to connect the parent and child processes. #[stable(feature = "process", since = "1.0.0")] pub fn piped() -> Stdio { Stdio(StdioImp::Piped) } @@ -461,7 +456,6 @@ impl Child { return Err(Error::new( ErrorKind::InvalidInput, "invalid argument: can't kill an exited process", - None )) } @@ -527,13 +521,28 @@ impl Child { } } +/// Terminates the current process with the specified exit code. +/// +/// This function will never return and will immediately terminate the current +/// process. The exit code is passed through to the underlying OS and will be +/// available for consumption by another process. +/// +/// Note that because this function never returns, and that it terminates the +/// process, no destructors on the current stack or any other thread's stack +/// will be run. If a clean shutdown is needed it is recommended to only call +/// this function at a known point where there are no more destructors left +/// to run. +#[stable(feature = "rust1", since = "1.0.0")] +pub fn exit(code: i32) -> ! { + ::sys::os::exit(code) +} + #[cfg(test)] mod tests { - use io::ErrorKind; + use prelude::v1::*; use io::prelude::*; - use prelude::v1::{Ok, Err, drop, Some, Vec}; - use prelude::v1::{String, Clone}; - use prelude::v1::{Str, AsSlice, ToString}; + + use io::ErrorKind; use old_path::{self, GenericPath}; use old_io::fs::PathExtensions; use rt::running_on_valgrind; @@ -567,7 +576,7 @@ mod tests { assert!(p.is_ok()); let mut p = p.unwrap(); assert!(p.wait().unwrap().code() == Some(1)); - drop(p.wait().clone()); + drop(p.wait()); } #[cfg(all(unix, not(target_os="android")))] @@ -678,7 +687,7 @@ mod tests { fn test_process_output_output() { let Output {status, stdout, stderr} = Command::new("echo").arg("hello").output().unwrap(); - let output_str = str::from_utf8(stdout.as_slice()).unwrap(); + let output_str = str::from_utf8(&stdout).unwrap(); assert!(status.success()); assert_eq!(output_str.trim().to_string(), "hello"); @@ -720,7 +729,7 @@ mod tests { let prog = Command::new("echo").arg("hello").stdout(Stdio::piped()) .spawn().unwrap(); let Output {status, stdout, stderr} = prog.wait_with_output().unwrap(); - let output_str = str::from_utf8(stdout.as_slice()).unwrap(); + let output_str = str::from_utf8(&stdout).unwrap(); assert!(status.success()); assert_eq!(output_str.trim().to_string(), "hello"); @@ -755,7 +764,8 @@ mod tests { let prog = pwd_cmd().spawn().unwrap(); let output = String::from_utf8(prog.wait_with_output().unwrap().stdout).unwrap(); - let parent_dir = os::getcwd().unwrap(); + let parent_dir = ::env::current_dir().unwrap().to_str().unwrap().to_string(); + let parent_dir = old_path::Path::new(parent_dir); let child_dir = old_path::Path::new(output.trim()); let parent_stat = parent_dir.stat().unwrap(); @@ -770,7 +780,8 @@ mod tests { use os; // test changing to the parent of os::getcwd() because we know // the path exists (and os::getcwd() is not expected to be root) - let parent_dir = os::getcwd().unwrap().dir_path(); + let parent_dir = ::env::current_dir().unwrap().to_str().unwrap().to_string(); + let parent_dir = old_path::Path::new(parent_dir).dir_path(); let result = pwd_cmd().current_dir(parent_dir.as_str().unwrap()).output().unwrap(); let output = String::from_utf8(result.stdout).unwrap(); @@ -821,14 +832,13 @@ mod tests { #[cfg(target_os="android")] #[test] fn test_inherit_env() { - use os; + use std::env; if running_on_valgrind() { return; } let mut result = env_cmd().output().unwrap(); let output = String::from_utf8(result.stdout).unwrap(); - let r = os::env(); - for &(ref k, ref v) in &r { + for (ref k, ref v) in env::vars() { // don't check android RANDOM variables if *k != "RANDOM".to_string() { assert!(output.contains(&format!("{}={}", @@ -855,7 +865,7 @@ mod tests { cmd.env("PATH", &p); } let result = cmd.output().unwrap(); - let output = String::from_utf8_lossy(result.stdout.as_slice()).to_string(); + let output = String::from_utf8_lossy(&result.stdout).to_string(); assert!(output.contains("RUN_TEST_NEW_ENV=123"), "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output); @@ -864,7 +874,7 @@ mod tests { #[test] fn test_add_to_env() { let result = env_cmd().env("RUN_TEST_NEW_ENV", "123").output().unwrap(); - let output = String::from_utf8_lossy(result.stdout.as_slice()).to_string(); + let output = String::from_utf8_lossy(&result.stdout).to_string(); assert!(output.contains("RUN_TEST_NEW_ENV=123"), "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output); diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs index 51b6045cf16..7aba40dc6be 100644 --- a/src/libstd/rand/os.rs +++ b/src/libstd/rand/os.rs @@ -15,17 +15,16 @@ pub use self::imp::OsRng; #[cfg(all(unix, not(target_os = "ios")))] mod imp { - extern crate libc; - + use prelude::v1::*; use self::OsRngInner::*; + use libc; + use mem; use old_io::{IoResult, File}; use old_path::Path; use rand::Rng; use rand::reader::ReaderRng; - use result::Result::Ok; - use mem; - use os::errno; + use sys::os::errno; #[cfg(all(target_os = "linux", any(target_arch = "x86_64", @@ -184,14 +183,13 @@ mod imp { #[cfg(target_os = "ios")] mod imp { - extern crate libc; + use prelude::v1::*; - use old_io::{IoResult}; + use old_io::IoResult; use mem; use os; use rand::Rng; - use result::Result::{Ok}; - use self::libc::{c_int, size_t}; + use libc::{c_int, size_t}; /// A random number generator that retrieves randomness straight from /// the operating system. Platform sources: @@ -251,16 +249,14 @@ mod imp { #[cfg(windows)] mod imp { - extern crate libc; + use prelude::v1::*; - use old_io::{IoResult, IoError}; + use io; use mem; - use ops::Drop; - use os; + use old_io::{IoResult, IoError}; use rand::Rng; - use result::Result::{Ok, Err}; - use self::libc::{DWORD, BYTE, LPCSTR, BOOL}; - use self::libc::types::os::arch::extra::{LONG_PTR}; + use libc::types::os::arch::extra::{LONG_PTR}; + use libc::{DWORD, BYTE, LPCSTR, BOOL}; type HCRYPTPROV = LONG_PTR; @@ -330,7 +326,8 @@ mod imp { v.as_mut_ptr()) }; if ret == 0 { - panic!("couldn't generate random bytes: {}", os::last_os_error()); + panic!("couldn't generate random bytes: {}", + io::Error::last_os_error()); } } } @@ -341,7 +338,8 @@ mod imp { CryptReleaseContext(self.hcryptprov, 0) }; if ret == 0 { - panic!("couldn't release context: {}", os::last_os_error()); + panic!("couldn't release context: {}", + io::Error::last_os_error()); } } } diff --git a/src/libstd/rt/args.rs b/src/libstd/rt/args.rs index 428bcaa49f7..2329861f29b 100644 --- a/src/libstd/rt/args.rs +++ b/src/libstd/rt/args.rs @@ -108,7 +108,6 @@ mod imp { #[cfg(test)] mod tests { use prelude::v1::*; - use finally::Finally; use super::*; @@ -127,14 +126,11 @@ mod imp { assert!(take() == Some(expected.clone())); assert!(take() == None); - (|| { - }).finally(|| { - // Restore the actual global state. - match saved_value { - Some(ref args) => put(args.clone()), - None => () - } - }) + // Restore the actual global state. + match saved_value { + Some(ref args) => put(args.clone()), + None => () + } } } } diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index 68137601c40..a5259a00390 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -31,8 +31,6 @@ pub use self::barrier::{Barrier, BarrierWaitResult}; pub use self::poison::{PoisonError, TryLockError, TryLockResult, LockResult}; pub use self::future::Future; -#[allow(deprecated)] -pub use self::task_pool::TaskPool; pub mod mpsc; @@ -44,4 +42,3 @@ mod once; mod poison; mod rwlock; mod semaphore; -mod task_pool; diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index b2b87bb6c44..e14f32865fa 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -114,7 +114,7 @@ //! ``` //! //! Reading from a channel with a timeout requires to use a Timer together -//! with the channel. You can use the select! macro to select either and +//! with the channel. You can use the `select!` macro to select either and //! handle the timeout case. This first example will break out of the loop //! after 10 seconds no matter what: //! diff --git a/src/libstd/sync/poison.rs b/src/libstd/sync/poison.rs index c07c83d37f4..347cd0b464e 100644 --- a/src/libstd/sync/poison.rs +++ b/src/libstd/sync/poison.rs @@ -11,7 +11,7 @@ use prelude::v1::*; use cell::UnsafeCell; -use error::{Error, FromError}; +use error::{Error}; use fmt; use thread; @@ -122,12 +122,6 @@ impl PoisonError { PoisonError { guard: guard } } - /// Consumes this error indicating that a lock is poisoned, returning the - /// underlying guard to allow access regardless. - #[unstable(feature = "std_misc")] - #[deprecated(since = "1.0.0", reason = "renamed to into_inner")] - pub fn into_guard(self) -> T { self.guard } - /// Consumes this error indicating that a lock is poisoned, returning the /// underlying guard to allow access regardless. #[unstable(feature = "std_misc")] @@ -144,8 +138,8 @@ impl PoisonError { pub fn get_mut(&mut self) -> &mut T { &mut self.guard } } -impl FromError> for TryLockError { - fn from_error(err: PoisonError) -> TryLockError { +impl From> for TryLockError { + fn from(err: PoisonError) -> TryLockError { TryLockError::Poisoned(err) } } diff --git a/src/libstd/sync/task_pool.rs b/src/libstd/sync/task_pool.rs deleted file mode 100644 index 51cf70e615b..00000000000 --- a/src/libstd/sync/task_pool.rs +++ /dev/null @@ -1,217 +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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Abstraction of a thread pool for basic parallelism. - -#![deprecated(since = "1.0.0", - reason = "This kind of API needs some time to bake in \ - crates.io. This functionality is available through \ - https://crates.io/crates/threadpool")] -#![unstable(feature = "std_misc")] - -#![allow(deprecated)] - -use core::prelude::*; - -use sync::{Arc, Mutex}; -use sync::mpsc::{channel, Sender, Receiver}; -use thread; -use thunk::Thunk; - -struct Sentinel<'a> { - jobs: &'a Arc>>>, - active: bool -} - -impl<'a> Sentinel<'a> { - fn new(jobs: &'a Arc>>>) -> Sentinel<'a> { - Sentinel { - jobs: jobs, - active: true - } - } - - // Cancel and destroy this sentinel. - fn cancel(mut self) { - self.active = false; - } -} - -#[unsafe_destructor] -impl<'a> Drop for Sentinel<'a> { - fn drop(&mut self) { - if self.active { - spawn_in_pool(self.jobs.clone()) - } - } -} - -/// A thread pool used to execute functions in parallel. -/// -/// Spawns `n` worker threads and replenishes the pool if any worker threads -/// panic. -/// -/// # Examples -/// -/// ``` -/// # #![feature(std_misc, core)] -/// use std::sync::TaskPool; -/// use std::iter::AdditiveIterator; -/// use std::sync::mpsc::channel; -/// -/// let pool = TaskPool::new(4); -/// -/// let (tx, rx) = channel(); -/// for _ in 0..8 { -/// let tx = tx.clone(); -/// pool.execute(move|| { -/// tx.send(1_u32).unwrap(); -/// }); -/// } -/// -/// assert_eq!(rx.iter().take(8).sum(), 8); -/// ``` -pub struct TaskPool { - // How the threadpool communicates with subthreads. - // - // This is the only such Sender, so when it is dropped all subthreads will - // quit. - jobs: Sender> -} - -impl TaskPool { - /// Spawns a new thread pool with `threads` threads. - /// - /// # Panics - /// - /// This function will panic if `threads` is 0. - pub fn new(threads: usize) -> TaskPool { - assert!(threads >= 1); - - let (tx, rx) = channel::(); - let rx = Arc::new(Mutex::new(rx)); - - // Threadpool threads - for _ in 0..threads { - spawn_in_pool(rx.clone()); - } - - TaskPool { jobs: tx } - } - - /// Executes the function `job` on a thread in the pool. - pub fn execute(&self, job: F) - where F : FnOnce(), F : Send + 'static - { - self.jobs.send(Thunk::new(job)).unwrap(); - } -} - -fn spawn_in_pool(jobs: Arc>>>) { - thread::spawn(move || { - // Will spawn a new thread on panic unless it is cancelled. - let sentinel = Sentinel::new(&jobs); - - loop { - let message = { - // Only lock jobs for the time it takes - // to get a job, not run it. - let lock = jobs.lock().unwrap(); - lock.recv() - }; - - match message { - Ok(job) => job.invoke(()), - - // The Taskpool was dropped. - Err(..) => break - } - } - - sentinel.cancel(); - }); -} - -#[cfg(test)] -mod test { - use prelude::v1::*; - use super::*; - use sync::mpsc::channel; - - const TEST_TASKS: usize = 4; - - #[test] - fn test_works() { - use iter::AdditiveIterator; - - let pool = TaskPool::new(TEST_TASKS); - - let (tx, rx) = channel(); - for _ in 0..TEST_TASKS { - let tx = tx.clone(); - pool.execute(move|| { - tx.send(1).unwrap(); - }); - } - - assert_eq!(rx.iter().take(TEST_TASKS).sum(), TEST_TASKS); - } - - #[test] - #[should_panic] - fn test_zero_tasks_panic() { - TaskPool::new(0); - } - - #[test] - fn test_recovery_from_subtask_panic() { - use iter::AdditiveIterator; - - let pool = TaskPool::new(TEST_TASKS); - - // Panic all the existing threads. - for _ in 0..TEST_TASKS { - pool.execute(move|| -> () { panic!() }); - } - - // Ensure new threads were spawned to compensate. - let (tx, rx) = channel(); - for _ in 0..TEST_TASKS { - let tx = tx.clone(); - pool.execute(move|| { - tx.send(1).unwrap(); - }); - } - - assert_eq!(rx.iter().take(TEST_TASKS).sum(), TEST_TASKS); - } - - #[test] - fn test_should_not_panic_on_drop_if_subtasks_panic_after_drop() { - use sync::{Arc, Barrier}; - - let pool = TaskPool::new(TEST_TASKS); - let waiter = Arc::new(Barrier::new(TEST_TASKS + 1)); - - // Panic all the existing threads in a bit. - for _ in 0..TEST_TASKS { - let waiter = waiter.clone(); - pool.execute(move|| { - waiter.wait(); - panic!(); - }); - } - - drop(pool); - - // Kick off the failure. - waiter.wait(); - } -} diff --git a/src/libstd/sys/common/net2.rs b/src/libstd/sys/common/net2.rs index a8ee40639e3..7d42d65d360 100644 --- a/src/libstd/sys/common/net2.rs +++ b/src/libstd/sys/common/net2.rs @@ -75,7 +75,7 @@ fn sockaddr_to_addr(storage: &libc::sockaddr_storage, }))) } _ => { - Err(Error::new(ErrorKind::InvalidInput, "invalid argument", None)) + Err(Error::new(ErrorKind::InvalidInput, "invalid argument")) } } } @@ -158,8 +158,7 @@ pub fn lookup_addr(addr: &IpAddr) -> io::Result { match from_utf8(data.to_bytes()) { Ok(name) => Ok(name.to_string()), Err(_) => Err(io::Error::new(io::ErrorKind::Other, - "failed to lookup address information", - Some("invalid host name".to_string()))) + "failed to lookup address information")) } } @@ -259,6 +258,12 @@ impl TcpStream { } } +impl FromInner for TcpStream { + fn from_inner(socket: Socket) -> TcpStream { + TcpStream { inner: socket } + } +} + //////////////////////////////////////////////////////////////////////////////// // TCP listeners //////////////////////////////////////////////////////////////////////////////// @@ -312,6 +317,12 @@ impl TcpListener { } } +impl FromInner for TcpListener { + fn from_inner(socket: Socket) -> TcpListener { + TcpListener { inner: socket } + } +} + //////////////////////////////////////////////////////////////////////////////// // UDP //////////////////////////////////////////////////////////////////////////////// @@ -424,3 +435,9 @@ impl UdpSocket { self.inner.duplicate().map(|s| UdpSocket { inner: s }) } } + +impl FromInner for UdpSocket { + fn from_inner(socket: Socket) -> UdpSocket { + UdpSocket { inner: socket } + } +} diff --git a/src/libstd/sys/unix/backtrace.rs b/src/libstd/sys/unix/backtrace.rs index 99a554a835f..ca805ad0242 100644 --- a/src/libstd/sys/unix/backtrace.rs +++ b/src/libstd/sys/unix/backtrace.rs @@ -251,7 +251,6 @@ fn print(w: &mut Write, idx: isize, addr: *mut libc::c_void, fn print(w: &mut Write, idx: isize, addr: *mut libc::c_void, symaddr: *mut libc::c_void) -> io::Result<()> { use env; - use ffi::AsOsStr; use os::unix::prelude::*; use ptr; diff --git a/src/libstd/sys/unix/ext.rs b/src/libstd/sys/unix/ext.rs index 0805949d560..fbfbb40701f 100644 --- a/src/libstd/sys/unix/ext.rs +++ b/src/libstd/sys/unix/ext.rs @@ -32,102 +32,171 @@ #![stable(feature = "rust1", since = "1.0.0")] /// Unix-specific extensions to general I/O primitives -#[unstable(feature = "io_ext", - reason = "may want a slightly different organization or a more \ - general file descriptor primitive")] +#[stable(feature = "rust1", since = "1.0.0")] pub mod io { #[allow(deprecated)] use old_io; use fs; use libc; use net; - use sys_common::AsInner; + use sys_common::{net2, AsInner, FromInner}; + use sys; /// Raw file descriptors. - pub type Fd = libc::c_int; + #[stable(feature = "rust1", since = "1.0.0")] + pub type RawFd = libc::c_int; - /// Extract raw file descriptor + /// A trait to extract the raw unix file descriptor from an underlying + /// object. + /// + /// This is only available on unix platforms and must be imported in order + /// to call the method. Windows platforms have a corresponding `AsRawHandle` + /// and `AsRawSocket` set of traits. + #[stable(feature = "rust1", since = "1.0.0")] pub trait AsRawFd { - /// Extract the raw file descriptor, without taking any ownership. - fn as_raw_fd(&self) -> Fd; + /// Extract the raw file descriptor. + /// + /// This method does **not** pass ownership of the raw file descriptor + /// to the caller. The descriptor is only guarantee to be valid while + /// the original object has not yet been destroyed. + #[stable(feature = "rust1", since = "1.0.0")] + fn as_raw_fd(&self) -> RawFd; + } + + /// A trait to express the ability to construct an object from a raw file + /// descriptor. + #[unstable(feature = "from_raw_os", + reason = "recent addition to std::os::unix::io")] + pub trait FromRawFd { + /// Constructs a new instances of `Self` from the given raw file + /// descriptor. + /// + /// This function **consumes ownership** of the specified file + /// descriptor. The returned object will take responsibility for closing + /// it when the object goes out of scope. + /// + /// Callers should normally only pass in a valid file descriptor to this + /// method or otherwise methods will return errors. + fn from_raw_fd(fd: RawFd) -> Self; } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for old_io::fs::File { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd() } } + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for fs::File { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd().raw() } } + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawFd for fs::File { + fn from_raw_fd(fd: RawFd) -> fs::File { + fs::File::from_inner(sys::fs2::File::from_inner(fd)) + } + } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for old_io::pipe::PipeStream { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for old_io::net::pipe::UnixStream { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for old_io::net::pipe::UnixListener { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for old_io::net::pipe::UnixAcceptor { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd() } } + #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] impl AsRawFd for old_io::net::tcp::TcpStream { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd() } } + #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] impl AsRawFd for old_io::net::tcp::TcpListener { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd() } } + #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] impl AsRawFd for old_io::net::tcp::TcpAcceptor { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for old_io::net::udp::UdpSocket { - fn as_raw_fd(&self) -> Fd { + fn as_raw_fd(&self) -> RawFd { self.as_inner().fd() } } + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for net::TcpStream { - fn as_raw_fd(&self) -> Fd { *self.as_inner().socket().as_inner() } + fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } } + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for net::TcpListener { - fn as_raw_fd(&self) -> Fd { *self.as_inner().socket().as_inner() } + fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } } + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for net::UdpSocket { - fn as_raw_fd(&self) -> Fd { *self.as_inner().socket().as_inner() } + fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } + } + + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawFd for net::TcpStream { + fn from_raw_fd(fd: RawFd) -> net::TcpStream { + let socket = sys::net::Socket::from_inner(fd); + net::TcpStream::from_inner(net2::TcpStream::from_inner(socket)) + } + } + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawFd for net::TcpListener { + fn from_raw_fd(fd: RawFd) -> net::TcpListener { + let socket = sys::net::Socket::from_inner(fd); + net::TcpListener::from_inner(net2::TcpListener::from_inner(socket)) + } + } + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawFd for net::UdpSocket { + fn from_raw_fd(fd: RawFd) -> net::UdpSocket { + let socket = sys::net::Socket::from_inner(fd); + net::UdpSocket::from_inner(net2::UdpSocket::from_inner(socket)) + } } } @@ -138,7 +207,7 @@ pub mod io { /// Unix-specific extension to the primitives in the `std::ffi` module #[stable(feature = "rust1", since = "1.0.0")] pub mod ffi { - use ffi::{CString, NulError, OsStr, OsString}; + use ffi::{OsStr, OsString}; use mem; use prelude::v1::*; use sys::os_str::Buf; @@ -175,10 +244,6 @@ pub mod ffi { /// Get the underlying byte view of the `OsStr` slice. #[stable(feature = "rust1", since = "1.0.0")] fn as_bytes(&self) -> &[u8]; - - /// Convert the `OsStr` slice into a `CString`. - #[stable(feature = "rust1", since = "1.0.0")] - fn to_cstring(&self) -> Result; } #[stable(feature = "rust1", since = "1.0.0")] @@ -189,9 +254,6 @@ pub mod ffi { fn as_bytes(&self) -> &[u8] { &self.as_inner().inner } - fn to_cstring(&self) -> Result { - CString::new(self.as_bytes()) - } } } @@ -302,7 +364,7 @@ pub mod process { #[stable(feature = "rust1", since = "1.0.0")] pub mod prelude { #[doc(no_inline)] - pub use super::io::{Fd, AsRawFd}; + pub use super::io::{RawFd, AsRawFd}; #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] pub use super::ffi::{OsStrExt, OsStringExt}; #[doc(no_inline)] diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 2569653811f..6b085c8eb7a 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -388,9 +388,7 @@ mod tests { fn test_file_desc() { // Run this test with some pipes so we don't have to mess around with // opening or closing files. - let os::Pipe { reader, writer } = unsafe { os::pipe().unwrap() }; - let mut reader = FileDesc::new(reader, true); - let mut writer = FileDesc::new(writer, true); + let (mut reader, mut writer) = unsafe { ::sys::os::pipe().unwrap() }; writer.write(b"test").unwrap(); let mut buf = [0; 4]; diff --git a/src/libstd/sys/unix/fs2.rs b/src/libstd/sys/unix/fs2.rs index 202e5ddaec4..c0426af051b 100644 --- a/src/libstd/sys/unix/fs2.rs +++ b/src/libstd/sys/unix/fs2.rs @@ -12,7 +12,7 @@ use core::prelude::*; use io::prelude::*; use os::unix::prelude::*; -use ffi::{CString, CStr, OsString, AsOsStr, OsStr}; +use ffi::{CString, CStr, OsString, OsStr}; use io::{self, Error, SeekFrom}; use libc::{self, c_int, size_t, off_t, c_char, mode_t}; use mem; @@ -276,8 +276,14 @@ impl File { } fn cstr(path: &Path) -> io::Result { - let cstring = try!(path.as_os_str().to_cstring()); - Ok(cstring) + path.as_os_str().to_cstring().ok_or( + io::Error::new(io::ErrorKind::InvalidInput, "path contained a null")) +} + +impl FromInner for File { + fn from_inner(fd: c_int) -> File { + File(FileDesc::new(fd)) + } } pub fn mkdir(p: &Path) -> io::Result<()> { diff --git a/src/libstd/sys/unix/helper_signal.rs b/src/libstd/sys/unix/helper_signal.rs index 17c8b21f8b3..fe0ede80fc6 100644 --- a/src/libstd/sys/unix/helper_signal.rs +++ b/src/libstd/sys/unix/helper_signal.rs @@ -11,15 +11,15 @@ #![allow(deprecated)] use libc; -use os; +use sys::os; use sys::fs::FileDesc; pub type signal = libc::c_int; pub fn new() -> (signal, signal) { - let os::Pipe { reader, writer } = unsafe { os::pipe().unwrap() }; - (reader, writer) + let (a, b) = unsafe { os::pipe().unwrap() }; + (a.unwrap(), b.unwrap()) } pub fn signal(fd: libc::c_int) { diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index b22fa33e562..908136a42ab 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -17,7 +17,7 @@ use str; use sys::c; use net::SocketAddr; use sys::fd::FileDesc; -use sys_common::AsInner; +use sys_common::{AsInner, FromInner}; pub use sys::{cvt, cvt_r}; @@ -35,7 +35,8 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> { .to_string() }; Err(io::Error::new(io::ErrorKind::Other, - "failed to lookup address information", Some(detail))) + &format!("failed to lookup address information: {}", + detail)[..])) } impl Socket { @@ -72,3 +73,7 @@ impl Socket { impl AsInner for Socket { fn as_inner(&self) -> &c_int { self.0.as_inner() } } + +impl FromInner for Socket { + fn from_inner(fd: c_int) -> Socket { Socket(FileDesc::new(fd)) } +} diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index fab443feebd..7b13e951b9b 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -16,7 +16,7 @@ use prelude::v1::*; use os::unix::prelude::*; use error::Error as StdError; -use ffi::{CString, CStr, OsString, OsStr, AsOsStr}; +use ffi::{CString, CStr, OsString, OsStr}; use fmt; use io; use iter; @@ -125,7 +125,8 @@ pub fn getcwd() -> io::Result { } pub fn chdir(p: &path::Path) -> io::Result<()> { - let p = try!(CString::new(p.as_os_str().as_bytes())); + let p: &OsStr = p.as_ref(); + let p = try!(CString::new(p.as_bytes())); unsafe { match libc::chdir(p.as_ptr()) == (0 as c_int) { true => Ok(()), @@ -158,13 +159,13 @@ impl<'a> Iterator for SplitPaths<'a> { pub struct JoinPathsError; pub fn join_paths(paths: I) -> Result - where I: Iterator, T: AsOsStr + where I: Iterator, T: AsRef { let mut joined = Vec::new(); let sep = b':'; for (i, path) in paths.enumerate() { - let path = path.as_os_str().as_bytes(); + let path = path.as_ref().as_bytes(); if i > 0 { joined.push(sep) } if path.contains(&sep) { return Err(JoinPathsError) @@ -464,7 +465,7 @@ pub fn page_size() -> usize { } pub fn temp_dir() -> PathBuf { - getenv("TMPDIR".as_os_str()).map(os2path).unwrap_or_else(|| { + getenv("TMPDIR".as_ref()).map(os2path).unwrap_or_else(|| { if cfg!(target_os = "android") { PathBuf::from("/data/local/tmp") } else { @@ -474,7 +475,7 @@ pub fn temp_dir() -> PathBuf { } pub fn home_dir() -> Option { - return getenv("HOME".as_os_str()).or_else(|| unsafe { + return getenv("HOME".as_ref()).or_else(|| unsafe { fallback() }).map(os2path); @@ -505,3 +506,7 @@ pub fn home_dir() -> Option { } } } + +pub fn exit(code: i32) -> ! { + unsafe { libc::exit(code as c_int) } +} diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs index 0d35ace185d..8095325f83d 100644 --- a/src/libstd/sys/unix/process.rs +++ b/src/libstd/sys/unix/process.rs @@ -19,8 +19,9 @@ use hash::Hash; use old_io::process::{ProcessExit, ExitStatus, ExitSignal}; use old_io::{IoResult, EndOfFile}; use libc::{self, pid_t, c_void, c_int}; +use io; use mem; -use os; +use sys::os; use old_path::BytesContainer; use ptr; use sync::mpsc::{channel, Sender, Receiver}; @@ -496,7 +497,8 @@ impl Process { n if n > 0 => { ret = true; } 0 => return true, -1 if wouldblock() => return ret, - n => panic!("bad read {:?} ({:?})", os::last_os_error(), n), + n => panic!("bad read {} ({})", + io::Error::last_os_error(), n), } } } diff --git a/src/libstd/sys/unix/process2.rs b/src/libstd/sys/unix/process2.rs index 20c409154b8..c2a8b26aef4 100644 --- a/src/libstd/sys/unix/process2.rs +++ b/src/libstd/sys/unix/process2.rs @@ -54,7 +54,7 @@ impl Command { self.args.push(arg.to_cstring().unwrap()) } pub fn args<'a, I: Iterator>(&mut self, args: I) { - self.args.extend(args.map(|s| OsStrExt::to_cstring(s).unwrap())) + self.args.extend(args.map(|s| s.to_cstring().unwrap())) } fn init_env_map(&mut self) { if self.env.is_none() { diff --git a/src/libstd/sys/unix/timer.rs b/src/libstd/sys/unix/timer.rs index d9a162302fc..9309147b15c 100644 --- a/src/libstd/sys/unix/timer.rs +++ b/src/libstd/sys/unix/timer.rs @@ -54,7 +54,8 @@ use self::Req::*; use old_io::IoResult; use libc; use mem; -use os; +use sys::os; +use io; use ptr; use sync::atomic::{self, Ordering}; use sync::mpsc::{channel, Sender, Receiver, TryRecvError}; @@ -209,7 +210,7 @@ fn helper(input: libc::c_int, messages: Receiver, _: ()) { -1 if os::errno() == libc::EINTR as i32 => {} n => panic!("helper thread failed in select() with error: {} ({})", - n, os::last_os_error()) + n, io::Error::last_os_error()) } } } diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index b9be4eb6bf5..e74de595f97 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -433,6 +433,7 @@ extern "system" { TokenHandle: *mut libc::HANDLE) -> libc::BOOL; pub fn GetCurrentProcess() -> libc::HANDLE; pub fn GetStdHandle(which: libc::DWORD) -> libc::HANDLE; + pub fn ExitProcess(uExitCode: libc::c_uint) -> !; } #[link(name = "userenv")] diff --git a/src/libstd/sys/windows/ext.rs b/src/libstd/sys/windows/ext.rs index 7955397892b..2dd61861bd6 100644 --- a/src/libstd/sys/windows/ext.rs +++ b/src/libstd/sys/windows/ext.rs @@ -16,112 +16,188 @@ #![stable(feature = "rust1", since = "1.0.0")] -#[unstable(feature = "io_ext", - reason = "organization may change slightly and the primitives \ - provided may be tweaked")] +#[stable(feature = "rust1", since = "1.0.0")] pub mod io { use fs; use libc; use net; - use sys_common::AsInner; + use sys_common::{net2, AsInner, FromInner}; + use sys; #[allow(deprecated)] use old_io; /// Raw HANDLEs. - pub type Handle = libc::HANDLE; + #[stable(feature = "rust1", since = "1.0.0")] + pub type RawHandle = libc::HANDLE; /// Raw SOCKETs. - pub type Socket = libc::SOCKET; + #[stable(feature = "rust1", since = "1.0.0")] + pub type RawSocket = libc::SOCKET; /// Extract raw handles. + #[stable(feature = "rust1", since = "1.0.0")] pub trait AsRawHandle { /// Extract the raw handle, without taking any ownership. - fn as_raw_handle(&self) -> Handle; + #[stable(feature = "rust1", since = "1.0.0")] + fn as_raw_handle(&self) -> RawHandle; + } + + /// Construct I/O objects from raw handles. + #[unstable(feature = "from_raw_os", + reason = "recent addition to the std::os::windows::io module")] + pub trait FromRawHandle { + /// Construct a new I/O object from the specified raw handle. + /// + /// This function will **consume ownership** of the handle given, + /// passing responsibility for closing the handle to the returned + /// object. + fn from_raw_handle(handle: RawHandle) -> Self; } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawHandle for old_io::fs::File { - fn as_raw_handle(&self) -> Handle { + fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle() } } + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawHandle for fs::File { - fn as_raw_handle(&self) -> Handle { + fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle().raw() } } + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawHandle for fs::File { + fn from_raw_handle(handle: RawHandle) -> fs::File { + fs::File::from_inner(sys::fs2::File::from_inner(handle)) + } + } + #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawHandle for old_io::pipe::PipeStream { - fn as_raw_handle(&self) -> Handle { + fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawHandle for old_io::net::pipe::UnixStream { - fn as_raw_handle(&self) -> Handle { + fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawHandle for old_io::net::pipe::UnixListener { - fn as_raw_handle(&self) -> Handle { + fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawHandle for old_io::net::pipe::UnixAcceptor { - fn as_raw_handle(&self) -> Handle { + fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle() } } /// Extract raw sockets. + #[stable(feature = "rust1", since = "1.0.0")] pub trait AsRawSocket { - fn as_raw_socket(&self) -> Socket; + /// Extract the underlying raw socket from this object. + #[stable(feature = "rust1", since = "1.0.0")] + fn as_raw_socket(&self) -> RawSocket; + } + + /// Create I/O objects from raw sockets. + #[unstable(feature = "from_raw_os", reason = "recent addition to module")] + pub trait FromRawSocket { + /// Creates a new I/O object from the given raw socket. + /// + /// This function will **consume ownership** of the socket provided and + /// it will be closed when the returned object goes out of scope. + fn from_raw_socket(sock: RawSocket) -> Self; } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawSocket for old_io::net::tcp::TcpStream { - fn as_raw_socket(&self) -> Socket { + fn as_raw_socket(&self) -> RawSocket { self.as_inner().fd() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawSocket for old_io::net::tcp::TcpListener { - fn as_raw_socket(&self) -> Socket { + fn as_raw_socket(&self) -> RawSocket { self.as_inner().socket() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawSocket for old_io::net::tcp::TcpAcceptor { - fn as_raw_socket(&self) -> Socket { + fn as_raw_socket(&self) -> RawSocket { self.as_inner().socket() } } #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawSocket for old_io::net::udp::UdpSocket { - fn as_raw_socket(&self) -> Socket { + fn as_raw_socket(&self) -> RawSocket { self.as_inner().fd() } } + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawSocket for net::TcpStream { - fn as_raw_socket(&self) -> Socket { *self.as_inner().socket().as_inner() } + fn as_raw_socket(&self) -> RawSocket { + *self.as_inner().socket().as_inner() + } } + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawSocket for net::TcpListener { - fn as_raw_socket(&self) -> Socket { *self.as_inner().socket().as_inner() } + fn as_raw_socket(&self) -> RawSocket { + *self.as_inner().socket().as_inner() + } } + #[stable(feature = "rust1", since = "1.0.0")] impl AsRawSocket for net::UdpSocket { - fn as_raw_socket(&self) -> Socket { *self.as_inner().socket().as_inner() } + fn as_raw_socket(&self) -> RawSocket { + *self.as_inner().socket().as_inner() + } + } + + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawSocket for net::TcpStream { + fn from_raw_socket(sock: RawSocket) -> net::TcpStream { + let sock = sys::net::Socket::from_inner(sock); + net::TcpStream::from_inner(net2::TcpStream::from_inner(sock)) + } + } + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawSocket for net::TcpListener { + fn from_raw_socket(sock: RawSocket) -> net::TcpListener { + let sock = sys::net::Socket::from_inner(sock); + net::TcpListener::from_inner(net2::TcpListener::from_inner(sock)) + } + } + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawSocket for net::UdpSocket { + fn from_raw_socket(sock: RawSocket) -> net::UdpSocket { + let sock = sys::net::Socket::from_inner(sock); + net::UdpSocket::from_inner(net2::UdpSocket::from_inner(sock)) + } } } @@ -230,7 +306,7 @@ pub mod fs { #[stable(feature = "rust1", since = "1.0.0")] pub mod prelude { #[doc(no_inline)] - pub use super::io::{Socket, Handle, AsRawSocket, AsRawHandle}; + pub use super::io::{RawSocket, RawHandle, AsRawSocket, AsRawHandle}; #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] pub use super::ffi::{OsStrExt, OsStringExt}; #[doc(no_inline)] diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 3330130c770..0bbb1a9e927 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -136,7 +136,7 @@ impl FileDesc { } } - /// Extract the actual filedescriptor without closing it. + #[allow(dead_code)] pub fn unwrap(self) -> fd_t { let fd = self.fd; unsafe { mem::forget(self) }; diff --git a/src/libstd/sys/windows/fs2.rs b/src/libstd/sys/windows/fs2.rs index 99835265111..d03e45649ed 100644 --- a/src/libstd/sys/windows/fs2.rs +++ b/src/libstd/sys/windows/fs2.rs @@ -20,11 +20,12 @@ use mem; use path::{Path, PathBuf}; use ptr; use sync::Arc; -use sys::handle::Handle as RawHandle; +use sys::handle::Handle; use sys::{c, cvt}; +use sys_common::FromInner; use vec::Vec; -pub struct File { handle: RawHandle } +pub struct File { handle: Handle } pub struct FileAttr { data: c::WIN32_FILE_ATTRIBUTE_DATA } pub struct ReadDir { @@ -192,7 +193,7 @@ impl File { if handle == libc::INVALID_HANDLE_VALUE { Err(Error::last_os_error()) } else { - Ok(File { handle: RawHandle::new(handle) }) + Ok(File { handle: Handle::new(handle) }) } } @@ -260,7 +261,13 @@ impl File { Ok(newpos as u64) } - pub fn handle(&self) -> &RawHandle { &self.handle } + pub fn handle(&self) -> &Handle { &self.handle } +} + +impl FromInner for File { + fn from_inner(handle: libc::HANDLE) -> File { + File { handle: Handle::new(handle) } + } } pub fn to_utf16(s: &Path) -> Vec { diff --git a/src/libstd/sys/windows/net.rs b/src/libstd/sys/windows/net.rs index 88d043de479..12a8ef99d76 100644 --- a/src/libstd/sys/windows/net.rs +++ b/src/libstd/sys/windows/net.rs @@ -20,7 +20,7 @@ use num::{SignedInt, Int}; use rt; use sync::{Once, ONCE_INIT}; use sys::c; -use sys_common::AsInner; +use sys_common::{AsInner, FromInner}; pub type wrlen_t = i32; @@ -126,10 +126,14 @@ impl Socket { impl Drop for Socket { fn drop(&mut self) { - unsafe { cvt(libc::closesocket(self.0)).unwrap(); } + let _ = unsafe { libc::closesocket(self.0) }; } } impl AsInner for Socket { fn as_inner(&self) -> &libc::SOCKET { &self.0 } } + +impl FromInner for Socket { + fn from_inner(sock: libc::SOCKET) -> Socket { Socket(sock) } +} diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index 167db1e8ac2..d5843a2f998 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -16,7 +16,7 @@ use prelude::v1::*; use os::windows::prelude::*; use error::Error as StdError; -use ffi::{OsString, OsStr, AsOsStr}; +use ffi::{OsString, OsStr}; use fmt; use io; use libc::types::os::arch::extra::LPWCH; @@ -31,7 +31,7 @@ use ptr; use slice; use sys::c; use sys::fs::FileDesc; -use sys::handle::Handle as RawHandle; +use sys::handle::Handle; use libc::funcs::extra::kernel32::{ GetEnvironmentStringsW, @@ -199,13 +199,13 @@ impl<'a> Iterator for SplitPaths<'a> { pub struct JoinPathsError; pub fn join_paths(paths: I) -> Result - where I: Iterator, T: AsOsStr + where I: Iterator, T: AsRef { let mut joined = Vec::new(); let sep = b';' as u16; for (i, path) in paths.enumerate() { - let path = path.as_os_str(); + let path = path.as_ref(); if i > 0 { joined.push(sep) } let v = path.encode_wide().collect::>(); if v.contains(&(b'"' as u16)) { @@ -245,7 +245,8 @@ pub fn getcwd() -> io::Result { } pub fn chdir(p: &path::Path) -> io::Result<()> { - let mut p = p.as_os_str().encode_wide().collect::>(); + let p: &OsStr = p.as_ref(); + let mut p = p.encode_wide().collect::>(); p.push(0); unsafe { @@ -361,15 +362,15 @@ pub fn temp_dir() -> PathBuf { } pub fn home_dir() -> Option { - getenv("HOME".as_os_str()).or_else(|| { - getenv("USERPROFILE".as_os_str()) + getenv("HOME".as_ref()).or_else(|| { + getenv("USERPROFILE".as_ref()) }).map(PathBuf::from).or_else(|| unsafe { let me = c::GetCurrentProcess(); let mut token = ptr::null_mut(); if c::OpenProcessToken(me, c::TOKEN_READ, &mut token) == 0 { return None } - let _handle = RawHandle::new(token); + let _handle = Handle::new(token); super::fill_utf16_buf_new(|buf, mut sz| { match c::GetUserProfileDirectoryW(token, buf, &mut sz) { 0 if libc::GetLastError() != 0 => 0, @@ -379,3 +380,7 @@ pub fn home_dir() -> Option { }, super::os2path).ok() }) } + +pub fn exit(code: i32) -> ! { + unsafe { c::ExitProcess(code as libc::c_uint) } +} diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index 297f6e173ab..b10042090dd 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -23,7 +23,7 @@ use mem; use old_io::process::{ProcessExit, ExitStatus}; use old_io::{IoResult, IoError}; use old_io; -use os; +use fs::PathExt; use old_path::{BytesContainer, GenericPath}; use ptr; use str; @@ -142,14 +142,19 @@ impl Process { let program = cfg.env().and_then(|env| { for (key, v) in env { if b"PATH" != key.container_as_bytes() { continue } + let v = match ::str::from_utf8(v.container_as_bytes()) { + Ok(s) => s, + Err(..) => continue, + }; // Split the value and test each path to see if the // program exists. - for path in os::split_paths(v.container_as_bytes()) { - let path = path.join(cfg.program().as_bytes()) + for path in ::env::split_paths(v) { + let program = str::from_utf8(cfg.program().as_bytes()).unwrap(); + let path = path.join(program) .with_extension(env::consts::EXE_EXTENSION); if path.exists() { - return Some(CString::from_slice(path.as_vec())) + return Some(CString::new(path.to_str().unwrap()).unwrap()) } } break @@ -482,9 +487,9 @@ mod tests { #[test] fn test_make_command_line() { fn test_wrapper(prog: &str, args: &[&str]) -> String { - make_command_line(&CString::from_slice(prog.as_bytes()), + make_command_line(&CString::new(prog).unwrap(), &args.iter() - .map(|a| CString::from_slice(a.as_bytes())) + .map(|a| CString::new(*a).unwrap()) .collect::>()) } diff --git a/src/libstd/sys/windows/process2.rs b/src/libstd/sys/windows/process2.rs index 9e9bb86446e..7e832b6384d 100644 --- a/src/libstd/sys/windows/process2.rs +++ b/src/libstd/sys/windows/process2.rs @@ -445,10 +445,9 @@ mod tests { fn test_wrapper(prog: &str, args: &[&str]) -> String { String::from_utf16( &make_command_line(OsStr::from_str(prog), - args.iter() - .map(|a| OsString::from_str(a)) - .collect::>() - .as_slice())).unwrap() + &args.iter() + .map(|a| OsString::from(a)) + .collect::>())).unwrap() } assert_eq!( diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs index d1bff0e135d..91f6f328ff6 100644 --- a/src/libstd/sys/windows/stdio.rs +++ b/src/libstd/sys/windows/stdio.rs @@ -41,7 +41,7 @@ fn get(handle: libc::DWORD) -> io::Result { Err(io::Error::last_os_error()) } else if handle.is_null() { Err(io::Error::new(io::ErrorKind::Other, - "no stdio handle available for this process", None)) + "no stdio handle available for this process")) } else { let ret = NoClose::new(handle); let mut out = 0; @@ -160,6 +160,5 @@ impl Drop for NoClose { } fn invalid_encoding() -> io::Error { - io::Error::new(io::ErrorKind::InvalidInput, "text was not valid unicode", - None) + io::Error::new(io::ErrorKind::InvalidInput, "text was not valid unicode") } diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index a2b824bb016..b9cbd01bed1 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -294,12 +294,6 @@ impl LocalKey { } } } - - /// Deprecated - #[unstable(feature = "std_misc")] - #[deprecated(since = "1.0.0", - reason = "function renamed to state() and returns more info")] - pub fn destroyed(&'static self) -> bool { self.state() == LocalKeyState::Destroyed } } #[cfg(all(any(target_os = "macos", target_os = "linux"), not(target_arch = "aarch64")))] diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 074030bd07b..1202b353317 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -189,8 +189,6 @@ use sys_common::{stack, thread_info}; use thunk::Thunk; use time::Duration; -#[allow(deprecated)] use old_io::Writer; - //////////////////////////////////////////////////////////////////////////////// // Thread-local storage //////////////////////////////////////////////////////////////////////////////// @@ -243,28 +241,6 @@ impl Builder { self } - /// Redirect thread-local stdout. - #[unstable(feature = "std_misc", - reason = "Will likely go away after proc removal")] - #[deprecated(since = "1.0.0", - reason = "the old I/O module is deprecated and this function \ - will be removed with no replacement")] - #[allow(deprecated)] - pub fn stdout(self, _stdout: Box) -> Builder { - self - } - - /// Redirect thread-local stderr. - #[unstable(feature = "std_misc", - reason = "Will likely go away after proc removal")] - #[deprecated(since = "1.0.0", - reason = "the old I/O module is deprecated and this function \ - will be removed with no replacement")] - #[allow(deprecated)] - pub fn stderr(self, _stderr: Box) -> Builder { - self - } - /// Spawn a new thread, and return a join handle for it. /// /// The child thread may outlive the parent (unless the parent thread @@ -568,71 +544,6 @@ impl Thread { } } - /// Deprecated: use module-level free function. - #[deprecated(since = "1.0.0", reason = "use module-level free function")] - #[unstable(feature = "std_misc", - reason = "may change with specifics of new Send semantics")] - pub fn spawn(f: F) -> Thread where F: FnOnce(), F: Send + 'static { - Builder::new().spawn(f).unwrap().thread().clone() - } - - /// Deprecated: use module-level free function. - #[deprecated(since = "1.0.0", reason = "use module-level free function")] - #[unstable(feature = "std_misc", - reason = "may change with specifics of new Send semantics")] - pub fn scoped<'a, T, F>(f: F) -> JoinGuard<'a, T> where - T: Send + 'a, F: FnOnce() -> T, F: Send + 'a - { - Builder::new().scoped(f).unwrap() - } - - /// Deprecated: use module-level free function. - #[deprecated(since = "1.0.0", reason = "use module-level free function")] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn current() -> Thread { - thread_info::current_thread() - } - - /// Deprecated: use module-level free function. - #[deprecated(since = "1.0.0", reason = "use module-level free function")] - #[unstable(feature = "std_misc", reason = "name may change")] - pub fn yield_now() { - unsafe { imp::yield_now() } - } - - /// Deprecated: use module-level free function. - #[deprecated(since = "1.0.0", reason = "use module-level free function")] - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn panicking() -> bool { - unwind::panicking() - } - - /// Deprecated: use module-level free function. - #[deprecated(since = "1.0.0", reason = "use module-level free function")] - #[unstable(feature = "std_misc", reason = "recently introduced")] - pub fn park() { - let thread = current(); - let mut guard = thread.inner.lock.lock().unwrap(); - while !*guard { - guard = thread.inner.cvar.wait(guard).unwrap(); - } - *guard = false; - } - - /// Deprecated: use module-level free function. - #[deprecated(since = "1.0.0", reason = "use module-level free function")] - #[unstable(feature = "std_misc", reason = "recently introduced")] - pub fn park_timeout(duration: Duration) { - let thread = current(); - let mut guard = thread.inner.lock.lock().unwrap(); - if !*guard { - let (g, _) = thread.inner.cvar.wait_timeout(guard, duration).unwrap(); - guard = g; - } - *guard = false; - } - /// Atomically makes the handle's token available if it is not already. /// /// See the module doc for more detail. @@ -762,8 +673,8 @@ impl<'a, T: Send + 'a> JoinGuard<'a, T> { &self.inner.thread } - /// Wait for the associated thread to finish, returning the result of the thread's - /// calculation. + /// Wait for the associated thread to finish, returning the result of the + /// thread's calculation. /// /// # Panics /// @@ -777,17 +688,6 @@ impl<'a, T: Send + 'a> JoinGuard<'a, T> { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl JoinGuard<'static, T> { - /// Detaches the child thread, allowing it to outlive its parent. - #[deprecated(since = "1.0.0", reason = "use spawn instead")] - #[unstable(feature = "std_misc")] - pub fn detach(mut self) { - unsafe { imp::detach(self.inner.native) }; - self.inner.joined = true; // avoid joining in the destructor - } -} - #[unsafe_destructor] #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: Send + 'a> Drop for JoinGuard<'a, T> { @@ -810,7 +710,6 @@ mod test { use any::Any; use sync::mpsc::{channel, Sender}; - use boxed::BoxAny; use result; use std::old_io::{ChanReader, ChanWriter}; use super::{Builder}; diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 1b03a180720..f88381fb36f 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -92,7 +92,7 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[ ("main", "1.0.0", Active), // Deprecate after snapshot - // SNAP a923278 + // SNAP 5520801 ("unsafe_destructor", "1.0.0", Active), // A temporary feature gate used to enable parser extensions needed @@ -102,9 +102,6 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[ // A way to temporarily opt out of opt in copy. This will *never* be accepted. ("opt_out_copy", "1.0.0", Removed), - // A way to temporarily opt out of the new orphan rules. This will *never* be accepted. - ("old_orphan_check", "1.0.0", Deprecated), - // OIBIT specific features ("optin_builtin_traits", "1.0.0", Active), @@ -161,10 +158,6 @@ enum Status { /// currently being considered for addition/removal. Active, - /// Represents a feature gate that is temporarily enabling deprecated behavior. - /// This gate will never be accepted. - Deprecated, - /// Represents a feature which has since been removed (it was once Active) Removed, @@ -277,9 +270,6 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType)] = &[ ("stable", Whitelisted), ("unstable", Whitelisted), - // FIXME: #19470 this shouldn't be needed forever - ("old_orphan_check", Whitelisted), - ("rustc_paren_sugar", Gated("unboxed_closures", "unboxed_closures are still evolving")), ("rustc_reflect_like", Gated("reflect", @@ -327,7 +317,6 @@ pub struct Features { pub allow_trace_macros: bool, pub allow_internal_unstable: bool, pub allow_custom_derive: bool, - pub old_orphan_check: bool, pub simd_ffi: bool, pub unmarked_api: bool, /// spans of #![feature] attrs for stable language features. for error reporting @@ -349,7 +338,6 @@ impl Features { allow_trace_macros: false, allow_internal_unstable: false, allow_custom_derive: false, - old_orphan_check: false, simd_ffi: false, unmarked_api: false, declared_stable_lang_features: Vec::new(), @@ -573,14 +561,6 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { }, _ => {} } - - if attr::contains_name(&i.attrs[..], - "old_orphan_check") { - self.gate_feature( - "old_orphan_check", - i.span, - "the new orphan check rules will eventually be strictly enforced"); - } } _ => {} @@ -699,13 +679,6 @@ fn check_crate_inner(cm: &CodeMap, span_handler: &SpanHandler, Some(&(name, _, Active)) => { cx.features.push(name); } - Some(&(name, _, Deprecated)) => { - cx.features.push(name); - span_handler.span_warn( - mi.span, - "feature is deprecated and will only be available \ - for a limited time, please rewrite code that relies on it"); - } Some(&(_, _, Removed)) => { span_handler.span_err(mi.span, "feature has been removed"); } @@ -737,7 +710,6 @@ fn check_crate_inner(cm: &CodeMap, span_handler: &SpanHandler, allow_trace_macros: cx.has_feature("trace_macros"), allow_internal_unstable: cx.has_feature("allow_internal_unstable"), allow_custom_derive: cx.has_feature("custom_derive"), - old_orphan_check: cx.has_feature("old_orphan_check"), simd_ffi: cx.has_feature("simd_ffi"), unmarked_api: cx.has_feature("unmarked_api"), declared_stable_lang_features: accepted_features, diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index c471d9e3179..0980acd3433 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -37,7 +37,6 @@ #![feature(unicode)] #![feature(path_ext)] #![feature(str_char)] -#![feature(convert)] #![feature(into_cow)] #![feature(slice_patterns)] diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index bcb265af926..78470f00207 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -620,8 +620,8 @@ impl<'a> StringReader<'a> { let base = 10; // find the integer representing the name - self.scan_digits(base); - let encoded_name: u32 = self.with_str_from(start_bpos, |s| { + self.scan_digits(base, base); + let encoded_name : u32 = self.with_str_from(start_bpos, |s| { u32::from_str_radix(s, 10).unwrap_or_else(|_| { panic!("expected digits representing a name, got {:?}, {}, range [{:?},{:?}]", s, whence, start_bpos, self.last_pos); @@ -638,7 +638,7 @@ impl<'a> StringReader<'a> { // find the integer representing the ctxt let start_bpos = self.last_pos; - self.scan_digits(base); + self.scan_digits(base, base); let encoded_ctxt : ast::SyntaxContext = self.with_str_from(start_bpos, |s| { u32::from_str_radix(s, 10).unwrap_or_else(|_| { panic!("expected digits representing a ctxt, got {:?}, {}", s, whence); @@ -652,16 +652,28 @@ impl<'a> StringReader<'a> { ctxt: encoded_ctxt, } } - /// Scan through any digits (base `radix`) or underscores, and return how - /// many digits there were. - fn scan_digits(&mut self, radix: u32) -> usize { + /// Scan through any digits (base `scan_radix`) or underscores, + /// and return how many digits there were. + /// + /// `real_radix` represents the true radix of the number we're + /// interested in, and errors will be emitted for any digits + /// between `real_radix` and `scan_radix`. + fn scan_digits(&mut self, real_radix: u32, scan_radix: u32) -> usize { + assert!(real_radix <= scan_radix); let mut len = 0; loop { let c = self.curr; if c == Some('_') { debug!("skipping a _"); self.bump(); continue; } - match c.and_then(|cc| cc.to_digit(radix)) { + match c.and_then(|cc| cc.to_digit(scan_radix)) { Some(_) => { debug!("{:?} in scan_digits", c); + // check that the hypothetical digit is actually + // in range for the true radix + if c.unwrap().to_digit(real_radix).is_none() { + self.err_span_(self.last_pos, self.pos, + &format!("invalid digit for a base {} literal", + real_radix)); + } len += 1; self.bump(); } @@ -680,11 +692,11 @@ impl<'a> StringReader<'a> { if c == '0' { match self.curr.unwrap_or('\0') { - 'b' => { self.bump(); base = 2; num_digits = self.scan_digits(2); } - 'o' => { self.bump(); base = 8; num_digits = self.scan_digits(8); } - 'x' => { self.bump(); base = 16; num_digits = self.scan_digits(16); } + 'b' => { self.bump(); base = 2; num_digits = self.scan_digits(2, 10); } + 'o' => { self.bump(); base = 8; num_digits = self.scan_digits(8, 10); } + 'x' => { self.bump(); base = 16; num_digits = self.scan_digits(16, 16); } '0'...'9' | '_' | '.' => { - num_digits = self.scan_digits(10) + 1; + num_digits = self.scan_digits(10, 10) + 1; } _ => { // just a 0 @@ -692,7 +704,7 @@ impl<'a> StringReader<'a> { } } } else if c.is_digit(10) { - num_digits = self.scan_digits(10) + 1; + num_digits = self.scan_digits(10, 10) + 1; } else { num_digits = 0; } @@ -711,7 +723,7 @@ impl<'a> StringReader<'a> { // with a number self.bump(); if self.curr.unwrap_or('\0').is_digit(10) { - self.scan_digits(10); + self.scan_digits(10, 10); self.scan_float_exponent(); } let last_pos = self.last_pos; @@ -934,7 +946,7 @@ impl<'a> StringReader<'a> { if self.curr_is('-') || self.curr_is('+') { self.bump(); } - if self.scan_digits(10) == 0 { + if self.scan_digits(10, 10) == 0 { self.err_span_(self.last_pos, self.pos, "expected at least one digit in exponent") } } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 544862a374a..f59e1d8214a 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -736,7 +736,20 @@ pub fn integer_lit(s: &str, suffix: Option<&str>, sd: &SpanHandler, sp: Span) -> let res = match u64::from_str_radix(s, base).ok() { Some(r) => r, - None => { sd.span_err(sp, "int literal is too large"); 0 } + None => { + // small bases are lexed as if they were base 10, e.g, the string + // might be `0b10201`. This will cause the conversion above to fail, + // but these cases have errors in the lexer: we don't want to emit + // two errors, and we especially don't want to emit this error since + // it isn't necessarily true. + let already_errored = base < 10 && + s.chars().any(|c| c.to_digit(10).map_or(false, |d| d >= base)); + + if !already_errored { + sd.span_err(sp, "int literal is too large"); + } + 0 + } }; // adjust the sign diff --git a/src/libsyntax/util/small_vector.rs b/src/libsyntax/util/small_vector.rs index 5bd6591cfb0..1649934f4b1 100644 --- a/src/libsyntax/util/small_vector.rs +++ b/src/libsyntax/util/small_vector.rs @@ -226,13 +226,13 @@ mod test { fn test_move_iter() { let v = SmallVector::zero(); let v: Vec = v.into_iter().collect(); - assert_eq!(Vec::new(), v); + assert_eq!(v, Vec::new()); let v = SmallVector::one(1); - assert_eq!([1], v.into_iter().collect::>()); + assert_eq!(v.into_iter().collect::>(), [1]); let v = SmallVector::many(vec![1, 2, 3]); - assert_eq!([1, 2, 3], v.into_iter().collect::>()); + assert_eq!(v.into_iter().collect::>(), [1, 2, 3]); } #[test] diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index ed2d00d6ad7..38d58f042b9 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -62,7 +62,6 @@ #![feature(std_misc)] #![feature(str_char)] #![feature(path_ext)] -#![feature(convert)] #![cfg_attr(windows, feature(libc))] #[macro_use] extern crate log; diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index ee0d190d729..f7e5c9f1dee 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -43,8 +43,6 @@ #![feature(std_misc)] #![feature(libc)] #![feature(set_stdio)] -#![feature(os)] -#![feature(convert)] #![cfg_attr(test, feature(old_io))] extern crate getopts; @@ -857,7 +855,8 @@ fn get_concurrency() -> usize { if std::rt::util::limit_thread_creation_due_to_osx_and_valgrind() { 1 } else { - std::os::num_cpus() + extern { fn rust_get_num_cpus() -> libc::uintptr_t; } + unsafe { rust_get_num_cpus() as usize } } } } diff --git a/src/rustbook/main.rs b/src/rustbook/main.rs index 4a652f846ed..09fcd518c1e 100644 --- a/src/rustbook/main.rs +++ b/src/rustbook/main.rs @@ -15,7 +15,6 @@ #![feature(rustdoc)] #![feature(rustc_private)] #![feature(path_relative_from)] -#![feature(convert)] extern crate rustdoc; extern crate rustc_back; diff --git a/src/snapshots.txt b/src/snapshots.txt index 8b05f7c8955..74d8b222c54 100644 --- a/src/snapshots.txt +++ b/src/snapshots.txt @@ -1,3 +1,13 @@ +S 2015-03-27 5520801 + bitrig-x86_64 41de2c7a69a1ac648d3fa3b65e96a29bdc122163 + freebsd-x86_64 0910bbad35e213f679d0433884fd51398eb3bc8d + linux-i386 1ef82402ed16f5a6d2f87a9a62eaa83170e249ec + linux-x86_64 ef2154372e97a3cb687897d027fd51c8f2c5f349 + macos-i386 0310b1a970f2da7e61770fd14dbbbdca3b518234 + macos-x86_64 5f35d9c920b8083a7420ef8cf5b00d5ef3085dfa + winnt-i386 808b7961f85872f04ec15ad0d3e9e23ae9bc0c3b + winnt-x86_64 903a99a58f57a9bd9848cc68a2445dda881f1ee8 + S 2015-03-25 a923278 bitrig-x86_64 41de2c7a69a1ac648d3fa3b65e96a29bdc122163 freebsd-x86_64 cd02c86a9218da73b2a45aff293787010d33bf3e diff --git a/src/test/bench/shootout-binarytrees.rs b/src/test/bench/shootout-binarytrees.rs index 64c38722137..ce050cc7323 100644 --- a/src/test/bench/shootout-binarytrees.rs +++ b/src/test/bench/shootout-binarytrees.rs @@ -38,11 +38,10 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED // OF THE POSSIBILITY OF SUCH DAMAGE. -#![feature(rustc_private, core)] +#![feature(rustc_private, core, step_by)] extern crate arena; -use std::iter::range_step; use std::thread; use arena::TypedArena; @@ -109,7 +108,7 @@ fn main() { let long_lived_arena = TypedArena::new(); let long_lived_tree = bottom_up_tree(&long_lived_arena, 0, max_depth); - let messages = range_step(min_depth, max_depth + 1, 2).map(|depth| { + let messages = (min_depth..max_depth + 1).step_by(2).map(|depth| { use std::num::Int; let iterations = 2.pow((max_depth - depth + min_depth) as u32); thread::scoped(move || inner(depth, iterations)) diff --git a/src/test/bench/shootout-fannkuch-redux.rs b/src/test/bench/shootout-fannkuch-redux.rs index 3a1da4c32af..af9ef80e609 100644 --- a/src/test/bench/shootout-fannkuch-redux.rs +++ b/src/test/bench/shootout-fannkuch-redux.rs @@ -38,9 +38,9 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED // OF THE POSSIBILITY OF SUCH DAMAGE. -#![feature(core)] +#![feature(step_by)] -use std::{cmp, iter, mem}; +use std::{cmp, mem}; use std::thread; fn rotate(x: &mut [i32]) { @@ -163,7 +163,7 @@ fn fannkuch(n: i32) -> (i32, i32) { let mut futures = vec![]; let k = perm.max() / N; - for (_, j) in (0..N).zip(iter::count(0, k)) { + for (_, j) in (0..N).zip((0..).step_by(k)) { let max = cmp::min(j+k, perm.max()); futures.push(thread::scoped(move|| { diff --git a/src/test/bench/shootout-k-nucleotide-pipes.rs b/src/test/bench/shootout-k-nucleotide-pipes.rs index de1d0103657..c190641bfbf 100644 --- a/src/test/bench/shootout-k-nucleotide-pipes.rs +++ b/src/test/bench/shootout-k-nucleotide-pipes.rs @@ -193,7 +193,7 @@ fn main() { // start processing if this is the one ('>', false) => { - match line[1..].find_str("THREE") { + match line[1..].find("THREE") { Some(_) => { proc_mode = true; } None => { } } diff --git a/src/test/bench/shootout-spectralnorm.rs b/src/test/bench/shootout-spectralnorm.rs index cd89b822035..c0268e816cf 100644 --- a/src/test/bench/shootout-spectralnorm.rs +++ b/src/test/bench/shootout-spectralnorm.rs @@ -118,7 +118,9 @@ fn dot(v: &[f64], u: &[f64]) -> f64 { fn parallel<'a,T, F>(v: &mut [T], ref f: F) where T: Send + Sync + 'a, F: Fn(usize, &mut [T]) + Sync + 'a { - let size = v.len() / os::num_cpus() + 1; + // FIXME: pick a more appropriate parallel factor + let parallelism = 4; + let size = v.len() / parallelism + 1; v.chunks_mut(size).enumerate().map(|(i, chunk)| { thread::scoped(move|| { f(i * size, chunk) diff --git a/src/test/compile-fail/const-eval-overflow-2.rs b/src/test/compile-fail/const-eval-overflow-2.rs new file mode 100644 index 00000000000..be04bc9bd3b --- /dev/null +++ b/src/test/compile-fail/const-eval-overflow-2.rs @@ -0,0 +1,30 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Evaluation of constants in refutable patterns goes through +// different compiler control-flow paths. + +#![allow(unused_imports)] + +use std::fmt; +use std::{i8, i16, i32, i64, isize}; +use std::{u8, u16, u32, u64, usize}; + +const NEG_128: i8 = -128; +const NEG_NEG_128: i8 = -NEG_128; +//~^ ERROR constant evaluation error: attempted to negate with overflow +//~| ERROR attempted to negate with overflow + +fn main() { + match -128i8 { + NEG_NEG_128 => println!("A"), + _ => println!("B"), + } +} diff --git a/src/test/compile-fail/const-eval-overflow-3.rs b/src/test/compile-fail/const-eval-overflow-3.rs new file mode 100644 index 00000000000..c2bc5b2648a --- /dev/null +++ b/src/test/compile-fail/const-eval-overflow-3.rs @@ -0,0 +1,39 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Evaluation of constants in array-elem count goes through different +// compiler control-flow paths. +// +// This test is checking the count in an array expression. + +// FIXME (#23926): the error output is not consistent between a +// self-hosted and a cross-compiled setup; therefore resorting to +// error-pattern for now. + +// error-pattern: expected constant integer for repeat count, but attempted to add with overflow + +#![allow(unused_imports)] + +use std::fmt; +use std::{i8, i16, i32, i64, isize}; +use std::{u8, u16, u32, u64, usize}; + +const A_I8_I + : [u32; (i8::MAX as usize) + 1] + = [0; (i8::MAX + 1) as usize]; + +fn main() { + foo(&A_I8_I[..]); +} + +fn foo(x: T) { + println!("{:?}", x); +} + diff --git a/src/test/compile-fail/const-eval-overflow-3b.rs b/src/test/compile-fail/const-eval-overflow-3b.rs new file mode 100644 index 00000000000..719b21000f7 --- /dev/null +++ b/src/test/compile-fail/const-eval-overflow-3b.rs @@ -0,0 +1,43 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Evaluation of constants in array-elem count goes through different +// compiler control-flow paths. +// +// This test is checking the count in an array expression. +// +// This is a variation of another such test, but in this case the +// types for the left- and right-hand sides of the addition do not +// match (as well as overflow). + +// FIXME (#23926): the error output is not consistent between a +// self-hosted and a cross-compiled setup; therefore resorting to +// error-pattern for now. + +// error-pattern: mismatched types + +#![allow(unused_imports)] + +use std::fmt; +use std::{i8, i16, i32, i64, isize}; +use std::{u8, u16, u32, u64, usize}; + +const A_I8_I + : [u32; (i8::MAX as usize) + 1] + = [0; (i8::MAX + 1u8) as usize]; + +fn main() { + foo(&A_I8_I[..]); +} + +fn foo(x: T) { + println!("{:?}", x); +} + diff --git a/src/test/compile-fail/const-eval-overflow-4.rs b/src/test/compile-fail/const-eval-overflow-4.rs new file mode 100644 index 00000000000..f1f125adaa7 --- /dev/null +++ b/src/test/compile-fail/const-eval-overflow-4.rs @@ -0,0 +1,36 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-test this should fail to compile (#23833) + +// Evaluation of constants in array-elem count goes through different +// compiler control-flow paths. +// +// This test is checking the count in an array type. + +#![allow(unused_imports)] + +use std::fmt; +use std::{i8, i16, i32, i64, isize}; +use std::{u8, u16, u32, u64, usize}; + +const A_I8_T + : [u32; (i8::MAX as i8 + 1i8) as usize] + //~^ ERROR error evaluating count: attempted to add with overflow + = [0; (i8::MAX as usize) + 1]; + +fn main() { + foo(&A_I8_T[..]); +} + +fn foo(x: T) { + println!("{:?}", x); +} + diff --git a/src/test/compile-fail/const-eval-overflow-4b.rs b/src/test/compile-fail/const-eval-overflow-4b.rs new file mode 100644 index 00000000000..6322b56a82f --- /dev/null +++ b/src/test/compile-fail/const-eval-overflow-4b.rs @@ -0,0 +1,36 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Evaluation of constants in array-elem count goes through different +// compiler control-flow paths. +// +// This test is checking the count in an array type. + +#![allow(unused_imports)] + +use std::fmt; +use std::{i8, i16, i32, i64, isize}; +use std::{u8, u16, u32, u64, usize}; + +const A_I8_T + : [u32; (i8::MAX as i8 + 1u8) as usize] + //~^ ERROR mismatched types + //~| the trait `core::ops::Add` is not implemented for the type `i8` + //~| the trait `core::ops::Add` is not implemented for the type `i8` + = [0; (i8::MAX as usize) + 1]; + +fn main() { + foo(&A_I8_T[..]); +} + +fn foo(x: T) { + println!("{:?}", x); +} + diff --git a/src/test/compile-fail/const-eval-overflow.rs b/src/test/compile-fail/const-eval-overflow.rs new file mode 100644 index 00000000000..f647c43e137 --- /dev/null +++ b/src/test/compile-fail/const-eval-overflow.rs @@ -0,0 +1,129 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(unused_imports)] + +// Note: the relevant lint pass here runs before some of the constant +// evaluation below (e.g. that performed by trans and llvm), so if you +// change this warn to a deny, then the compiler will exit before +// those errors are detected. +#![warn(unsigned_negation)] + +use std::fmt; +use std::{i8, i16, i32, i64, isize}; +use std::{u8, u16, u32, u64, usize}; + +const VALS_I8: (i8, i8, i8, i8) = + (-i8::MIN, + //~^ ERROR attempted to negate with overflow + i8::MIN - 1, + //~^ ERROR attempted to sub with overflow + i8::MAX + 1, + //~^ ERROR attempted to add with overflow + i8::MIN * 2, + //~^ ERROR attempted to mul with overflow + ); + +const VALS_I16: (i16, i16, i16, i16) = + (-i16::MIN, + //~^ ERROR attempted to negate with overflow + i16::MIN - 1, + //~^ ERROR attempted to sub with overflow + i16::MAX + 1, + //~^ ERROR attempted to add with overflow + i16::MIN * 2, + //~^ ERROR attempted to mul with overflow + ); + +const VALS_I32: (i32, i32, i32, i32) = + (-i32::MIN, + //~^ ERROR attempted to negate with overflow + i32::MIN - 1, + //~^ ERROR attempted to sub with overflow + i32::MAX + 1, + //~^ ERROR attempted to add with overflow + i32::MIN * 2, + //~^ ERROR attempted to mul with overflow + ); + +const VALS_I64: (i64, i64, i64, i64) = + (-i64::MIN, + //~^ ERROR attempted to negate with overflow + i64::MIN - 1, + //~^ ERROR attempted to sub with overflow + i64::MAX + 1, + //~^ ERROR attempted to add with overflow + i64::MAX * 2, + //~^ ERROR attempted to mul with overflow + ); + +const VALS_U8: (u8, u8, u8, u8) = + (-u8::MIN, + //~^ WARNING negation of unsigned int variable may be unintentional + // (The above is separately linted; unsigned negation is defined to be !x+1.) + u8::MIN - 1, + //~^ ERROR attempted to sub with overflow + u8::MAX + 1, + //~^ ERROR attempted to add with overflow + u8::MAX * 2, + //~^ ERROR attempted to mul with overflow + ); + +const VALS_U16: (u16, u16, u16, u16) = + (-u16::MIN, + //~^ WARNING negation of unsigned int variable may be unintentional + // (The above is separately linted; unsigned negation is defined to be !x+1.) + u16::MIN - 1, + //~^ ERROR attempted to sub with overflow + u16::MAX + 1, + //~^ ERROR attempted to add with overflow + u16::MAX * 2, + //~^ ERROR attempted to mul with overflow + ); + +const VALS_U32: (u32, u32, u32, u32) = + (-u32::MIN, + //~^ WARNING negation of unsigned int variable may be unintentional + // (The above is separately linted; unsigned negation is defined to be !x+1.) + u32::MIN - 1, + //~^ ERROR attempted to sub with overflow + u32::MAX + 1, + //~^ ERROR attempted to add with overflow + u32::MAX * 2, + //~^ ERROR attempted to mul with overflow + ); + +const VALS_U64: (u64, u64, u64, u64) = + (-u64::MIN, + //~^ WARNING negation of unsigned int variable may be unintentional + // (The above is separately linted; unsigned negation is defined to be !x+1.) + u64::MIN - 1, + //~^ ERROR attempted to sub with overflow + u64::MAX + 1, + //~^ ERROR attempted to add with overflow + u64::MAX * 2, + //~^ ERROR attempted to mul with overflow + ); + +fn main() { + foo(VALS_I8); + foo(VALS_I16); + foo(VALS_I32); + foo(VALS_I64); + + foo(VALS_U8); + foo(VALS_U16); + foo(VALS_U32); + foo(VALS_U64); +} + +fn foo(x: T) { + println!("{:?}", x); +} diff --git a/src/test/compile-fail/discrim-ill-typed.rs b/src/test/compile-fail/discrim-ill-typed.rs new file mode 100644 index 00000000000..23106c99594 --- /dev/null +++ b/src/test/compile-fail/discrim-ill-typed.rs @@ -0,0 +1,118 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// When explicit discriminant value has +// a type that does not match the representation +// type, rustc should fail gracefully. + +// See also run-pass/discrim-explicit-23030.rs where the input types +// are correct. + +#![allow(dead_code, unused_variables, unused_imports)] + +use std::{i8,u8,i16,u16,i32,u32,i64, u64}; + +fn f_i8() { + #[repr(i8)] + enum A { + Ok = i8::MAX - 1, + Ok2, + OhNo = 0_u8, + //~^ ERROR mismatched types + } + + let x = A::Ok; +} + +fn f_u8() { + #[repr(u8)] + enum A { + Ok = u8::MAX - 1, + Ok2, + OhNo = 0_i8, + //~^ ERROR mismatched types + } + + let x = A::Ok; +} + +fn f_i16() { + #[repr(i16)] + enum A { + Ok = i16::MAX - 1, + Ok2, + OhNo = 0_u16, + //~^ ERROR mismatched types + } + + let x = A::Ok; +} + +fn f_u16() { + #[repr(u16)] + enum A { + Ok = u16::MAX - 1, + Ok2, + OhNo = 0_i16, + //~^ ERROR mismatched types + } + + let x = A::Ok; +} + +fn f_i32() { + #[repr(i32)] + enum A { + Ok = i32::MAX - 1, + Ok2, + OhNo = 0_u32, + //~^ ERROR mismatched types + } + + let x = A::Ok; +} + +fn f_u32() { + #[repr(u32)] + enum A { + Ok = u32::MAX - 1, + Ok2, + OhNo = 0_i32, + //~^ ERROR mismatched types + } + + let x = A::Ok; +} + +fn f_i64() { + #[repr(i64)] + enum A { + Ok = i64::MAX - 1, + Ok2, + OhNo = 0_u64, + //~^ ERROR mismatched types + } + + let x = A::Ok; +} + +fn f_u64() { + #[repr(u64)] + enum A { + Ok = u64::MAX - 1, + Ok2, + OhNo = 0_i64, + //~^ ERROR mismatched types + } + + let x = A::Ok; +} + +fn main() { } diff --git a/src/test/compile-fail/discrim-overflow-2.rs b/src/test/compile-fail/discrim-overflow-2.rs new file mode 100644 index 00000000000..76378d5c802 --- /dev/null +++ b/src/test/compile-fail/discrim-overflow-2.rs @@ -0,0 +1,94 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-linelength + +// Issue 23030: Detect overflowing discriminant +// +// Check that we detect the overflow even if enum is not used. + +// See also run-pass/discrim-explicit-23030.rs where the suggested +// workaround is tested. + +use std::{i8,u8,i16,u16,i32,u32,i64, u64}; + +fn f_i8() { + #[repr(i8)] + enum A { + Ok = i8::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed on value after 127: i8; set explicitly via OhNo = -128 if that is desired outcome + } +} + +fn f_u8() { + #[repr(u8)] + enum A { + Ok = u8::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed on value after 255: u8; set explicitly via OhNo = 0 if that is desired outcome + } +} + +fn f_i16() { + #[repr(i16)] + enum A { + Ok = i16::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } +} + +fn f_u16() { + #[repr(u16)] + enum A { + Ok = u16::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } +} + +fn f_i32() { + #[repr(i32)] + enum A { + Ok = i32::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } +} + +fn f_u32() { + #[repr(u32)] + enum A { + Ok = u32::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } +} + +fn f_i64() { + #[repr(i64)] + enum A { + Ok = i64::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } +} + +fn f_u64() { + #[repr(u64)] + enum A { + Ok = u64::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } +} + +fn main() { } diff --git a/src/test/compile-fail/discrim-overflow.rs b/src/test/compile-fail/discrim-overflow.rs new file mode 100644 index 00000000000..5d7e61e9d1e --- /dev/null +++ b/src/test/compile-fail/discrim-overflow.rs @@ -0,0 +1,108 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-linelength + +// Issue 23030: Detect overflowing discriminant + +// See also run-pass/discrim-explicit-23030.rs where the suggested +// workaround is tested. + +use std::{i8,u8,i16,u16,i32,u32,i64, u64}; + +fn f_i8() { + #[repr(i8)] + enum A { + Ok = i8::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed on value after 127: i8; set explicitly via OhNo = -128 if that is desired outcome + } + + let x = A::Ok; +} + +fn f_u8() { + #[repr(u8)] + enum A { + Ok = u8::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed on value after 255: u8; set explicitly via OhNo = 0 if that is desired outcome + } + + let x = A::Ok; +} + +fn f_i16() { + #[repr(i16)] + enum A { + Ok = i16::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } + + let x = A::Ok; +} + +fn f_u16() { + #[repr(u16)] + enum A { + Ok = u16::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } + + let x = A::Ok; +} + +fn f_i32() { + #[repr(i32)] + enum A { + Ok = i32::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } + + let x = A::Ok; +} + +fn f_u32() { + #[repr(u32)] + enum A { + Ok = u32::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } + + let x = A::Ok; +} + +fn f_i64() { + #[repr(i64)] + enum A { + Ok = i64::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } + + let x = A::Ok; +} + +fn f_u64() { + #[repr(u64)] + enum A { + Ok = u64::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } + + let x = A::Ok; +} + +fn main() { } diff --git a/src/test/compile-fail/dropck_arr_cycle_checked.rs b/src/test/compile-fail/dropck_arr_cycle_checked.rs index 3aa2fae2826..40d992fe21f 100644 --- a/src/test/compile-fail/dropck_arr_cycle_checked.rs +++ b/src/test/compile-fail/dropck_arr_cycle_checked.rs @@ -20,9 +20,9 @@ use id::Id; mod s { #![allow(unstable)] - use std::sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering}; + use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; - static S_COUNT: AtomicUint = ATOMIC_UINT_INIT; + static S_COUNT: AtomicUsize = ATOMIC_USIZE_INIT; pub fn next_count() -> usize { S_COUNT.fetch_add(1, Ordering::SeqCst) + 1 diff --git a/src/test/compile-fail/dropck_tarena_cycle_checked.rs b/src/test/compile-fail/dropck_tarena_cycle_checked.rs index 74e3c724b67..9488882ca94 100644 --- a/src/test/compile-fail/dropck_tarena_cycle_checked.rs +++ b/src/test/compile-fail/dropck_tarena_cycle_checked.rs @@ -27,9 +27,9 @@ use id::Id; mod s { #![allow(unstable)] - use std::sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering}; + use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; - static S_COUNT: AtomicUint = ATOMIC_UINT_INIT; + static S_COUNT: AtomicUsize = ATOMIC_USIZE_INIT; pub fn next_count() -> usize { S_COUNT.fetch_add(1, Ordering::SeqCst) + 1 diff --git a/src/test/compile-fail/dropck_vec_cycle_checked.rs b/src/test/compile-fail/dropck_vec_cycle_checked.rs index 3f69c7d1a9c..9d92552244f 100644 --- a/src/test/compile-fail/dropck_vec_cycle_checked.rs +++ b/src/test/compile-fail/dropck_vec_cycle_checked.rs @@ -19,9 +19,9 @@ use id::Id; mod s { #![allow(unstable)] - use std::sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering}; + use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; - static S_COUNT: AtomicUint = ATOMIC_UINT_INIT; + static S_COUNT: AtomicUsize = ATOMIC_USIZE_INIT; pub fn next_count() -> usize { S_COUNT.fetch_add(1, Ordering::SeqCst) + 1 diff --git a/src/test/compile-fail/estr-subtyping.rs b/src/test/compile-fail/estr-subtyping.rs index 6e64e01d741..b5c6db0cea9 100644 --- a/src/test/compile-fail/estr-subtyping.rs +++ b/src/test/compile-fail/estr-subtyping.rs @@ -18,7 +18,7 @@ fn has_uniq(x: String) { fn has_slice(x: &str) { wants_uniq(x); //~ ERROR mismatched types - wants_slice(x.as_slice()); + wants_slice(x); } fn main() { diff --git a/src/test/compile-fail/huge-array-simple.rs b/src/test/compile-fail/huge-array-simple.rs index 105f885f287..54340cf7ac4 100644 --- a/src/test/compile-fail/huge-array-simple.rs +++ b/src/test/compile-fail/huge-array-simple.rs @@ -8,9 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: too big for the current +// FIXME (#23926): the error output is not consistent between a +// self-hosted and a cross-compiled setup. Skipping for now. + +// ignore-test FIXME(#23926) + #![allow(exceeding_bitshifts)] fn main() { - let fat : [u8; (1<<61)+(1<<31)] = [0; (1u64<<61) as usize +(1u64<<31) as usize]; + let _fat : [u8; (1<<61)+(1<<31)] = + [0; (1u64<<61) as usize +(1u64<<31) as usize]; } diff --git a/src/test/compile-fail/issue-13058.rs b/src/test/compile-fail/issue-13058.rs index 50c4ac94d90..8886dd80be5 100644 --- a/src/test/compile-fail/issue-13058.rs +++ b/src/test/compile-fail/issue-13058.rs @@ -8,14 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::iter::{Range,range}; +use std::ops::Range; trait Itble<'r, T, I: Iterator> { fn iter(&'r self) -> I; } impl<'r> Itble<'r, usize, Range> for (usize, usize) { fn iter(&'r self) -> Range { let &(min, max) = self; - range(min, max) + min..max } } diff --git a/src/test/compile-fail/issue-17651.rs b/src/test/compile-fail/issue-17651.rs index 8ebf80a8db0..9e49abc463f 100644 --- a/src/test/compile-fail/issue-17651.rs +++ b/src/test/compile-fail/issue-17651.rs @@ -13,6 +13,6 @@ fn main() { // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. - (|| Box::new(*[0].as_slice()))(); + (|| Box::new(*(&[0][..])))(); //~^ ERROR the trait `core::marker::Sized` is not implemented for the type `[_]` } diff --git a/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-2.rs b/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-2.rs index 0a8e4514b43..d2d0dbf3e98 100644 --- a/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-2.rs +++ b/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-2.rs @@ -10,14 +10,14 @@ // ignore-tidy-linelength -use std::iter::{Range,range}; +use std::ops::Range; trait Itble<'r, T, I: Iterator> { fn iter(&'r self) -> I; } impl<'r> Itble<'r, usize, Range> for (usize, usize) { fn iter(&'r self) -> Range { let &(min, max) = self; - range(min, max) + min..max } } diff --git a/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs b/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs index 0212adff305..a7cabae16be 100644 --- a/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs +++ b/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs @@ -8,9 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Note: This test is checking that we forbid a coding pattern that +// Issue #5873 explicitly wants to allow. + enum State { ST_NULL, ST_WHITESPACE } fn main() { [State::ST_NULL; (State::ST_WHITESPACE as usize)]; - //~^ ERROR expected constant integer for repeat count, found non-constant expression + //~^ ERROR expected constant integer for repeat count, but non-constant path } diff --git a/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs b/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs index 26528543b43..3ce206ff7fb 100644 --- a/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs +++ b/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs @@ -12,6 +12,7 @@ fn main() { fn bar(n: usize) { - let _x = [0; n]; //~ ERROR expected constant integer for repeat count, found variable + let _x = [0; n]; + //~^ ERROR expected constant integer for repeat count, found variable } } diff --git a/src/test/compile-fail/variance-deprecated-markers.rs b/src/test/compile-fail/variance-deprecated-markers.rs deleted file mode 100644 index 8f9d24cb132..00000000000 --- a/src/test/compile-fail/variance-deprecated-markers.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test that the deprecated markers still have their old effect. - -#![feature(rustc_attrs)] - -use std::marker; - -#[rustc_variance] -struct A(marker::CovariantType); //~ ERROR types=[[+];[];[]] - -#[rustc_variance] -struct B(marker::ContravariantType); //~ ERROR types=[[-];[];[]] - -#[rustc_variance] -struct C(marker::InvariantType); //~ ERROR types=[[o];[];[]] - -#[rustc_variance] -struct D<'a>(marker::CovariantLifetime<'a>); //~ ERROR regions=[[+];[];[]] - -#[rustc_variance] -struct E<'a>(marker::ContravariantLifetime<'a>); //~ ERROR regions=[[-];[];[]] - -#[rustc_variance] -struct F<'a>(marker::InvariantLifetime<'a>); //~ ERROR regions=[[o];[];[]] - -fn main() { } diff --git a/src/test/compile-fail/vec-must-not-hide-type-from-dropck.rs b/src/test/compile-fail/vec-must-not-hide-type-from-dropck.rs index 6aaf51278af..44a3f716e3e 100644 --- a/src/test/compile-fail/vec-must-not-hide-type-from-dropck.rs +++ b/src/test/compile-fail/vec-must-not-hide-type-from-dropck.rs @@ -30,9 +30,9 @@ use id::Id; mod s { #![allow(unstable)] - use std::sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering}; + use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; - static S_COUNT: AtomicUint = ATOMIC_UINT_INIT; + static S_COUNT: AtomicUsize = ATOMIC_USIZE_INIT; /// generates globally unique count (global across the current /// process, that is) diff --git a/src/test/compile-fail/vec_refs_data_with_early_death.rs b/src/test/compile-fail/vec_refs_data_with_early_death.rs index a191b3e56c4..0025449a3db 100644 --- a/src/test/compile-fail/vec_refs_data_with_early_death.rs +++ b/src/test/compile-fail/vec_refs_data_with_early_death.rs @@ -27,5 +27,5 @@ fn main() { v.push(&x); //~ ERROR `x` does not live long enough v.push(&y); //~ ERROR `y` does not live long enough - assert_eq!(v.as_slice(), [&3, &4]); + assert_eq!(v, [&3, &4]); } diff --git a/src/test/parse-fail/issue-1802-1.rs b/src/test/parse-fail/issue-1802-1.rs index 8ce99f517c4..00fb2808faa 100644 --- a/src/test/parse-fail/issue-1802-1.rs +++ b/src/test/parse-fail/issue-1802-1.rs @@ -10,5 +10,5 @@ // error-pattern:no valid digits found for number fn main() { - log(error, 0b42); + log(error, 0b); } diff --git a/src/test/parse-fail/lex-bad-binary-literal.rs b/src/test/parse-fail/lex-bad-binary-literal.rs new file mode 100644 index 00000000000..e92000c54ba --- /dev/null +++ b/src/test/parse-fail/lex-bad-binary-literal.rs @@ -0,0 +1,21 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + 0b121; //~ ERROR invalid digit for a base 2 literal + 0b10_10301; //~ ERROR invalid digit for a base 2 literal + 0b30; //~ ERROR invalid digit for a base 2 literal + 0b41; //~ ERROR invalid digit for a base 2 literal + 0b5; //~ ERROR invalid digit for a base 2 literal + 0b6; //~ ERROR invalid digit for a base 2 literal + 0b7; //~ ERROR invalid digit for a base 2 literal + 0b8; //~ ERROR invalid digit for a base 2 literal + 0b9; //~ ERROR invalid digit for a base 2 literal +} diff --git a/src/test/parse-fail/lex-bad-octal-literal.rs b/src/test/parse-fail/lex-bad-octal-literal.rs new file mode 100644 index 00000000000..bf9880cb6cf --- /dev/null +++ b/src/test/parse-fail/lex-bad-octal-literal.rs @@ -0,0 +1,14 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + 0o18; //~ ERROR invalid digit for a base 8 literal + 0o1234_9_5670; //~ ERROR invalid digit for a base 8 literal +} diff --git a/src/test/run-fail/assert-eq-macro-panic.rs b/src/test/run-fail/assert-eq-macro-panic.rs index fd6d69efb4f..0b35062b186 100644 --- a/src/test/run-fail/assert-eq-macro-panic.rs +++ b/src/test/run-fail/assert-eq-macro-panic.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:assertion failed: `(left == right) && (right == left)` (left: `14`, right: `15`) +// error-pattern:assertion failed: `(left == right)` (left: `14`, right: `15`) fn main() { assert_eq!(14,15); diff --git a/src/test/run-fail/rt-set-exit-status-panic.rs b/src/test/run-fail/rt-set-exit-status-panic.rs index 0e72ab22dc8..249e2e1ac2d 100644 --- a/src/test/run-fail/rt-set-exit-status-panic.rs +++ b/src/test/run-fail/rt-set-exit-status-panic.rs @@ -10,16 +10,16 @@ // error-pattern:whatever -#![feature(os, rustc_private)] +#![feature(exit_status, rustc_private)] #[macro_use] extern crate log; -use std::os; +use std::env; fn main() { error!("whatever"); // Setting the exit status only works when the scheduler terminates // normally. In this case we're going to panic, so instead of // returning 50 the process will return the typical rt failure code. - os::set_exit_status(50); + env::set_exit_status(50); panic!(); } diff --git a/src/test/run-fail/rt-set-exit-status-panic2.rs b/src/test/run-fail/rt-set-exit-status-panic2.rs index a71ce9ebab5..fddff3c5a9f 100644 --- a/src/test/run-fail/rt-set-exit-status-panic2.rs +++ b/src/test/run-fail/rt-set-exit-status-panic2.rs @@ -10,10 +10,10 @@ // error-pattern:whatever -#![feature(os, rustc_private)] +#![feature(exit_status, rustc_private)] #[macro_use] extern crate log; -use std::os; +use std::env; use std::thread; struct r { @@ -25,7 +25,7 @@ struct r { // runtime's exit code impl Drop for r { fn drop(&mut self) { - os::set_exit_status(50); + env::set_exit_status(50); } } diff --git a/src/test/run-fail/rt-set-exit-status.rs b/src/test/run-fail/rt-set-exit-status.rs index 9425a1b1902..c33a8d2d032 100644 --- a/src/test/run-fail/rt-set-exit-status.rs +++ b/src/test/run-fail/rt-set-exit-status.rs @@ -10,14 +10,14 @@ // error-pattern:whatever -#![feature(rustc_private, os)] +#![feature(rustc_private, exit_status)] #[macro_use] extern crate log; -use std::os; +use std::env; fn main() { error!("whatever"); // 101 is the code the runtime uses on task panic and the value // compiletest expects run-fail tests to return. - os::set_exit_status(101); + env::set_exit_status(101); } diff --git a/src/test/run-make/link-path-order/main.rs b/src/test/run-make/link-path-order/main.rs index b1576ccd48e..c1787eb03f5 100644 --- a/src/test/run-make/link-path-order/main.rs +++ b/src/test/run-make/link-path-order/main.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(libc, os)] +#![feature(libc, exit_status)] extern crate libc; @@ -23,6 +23,6 @@ fn main() { }; if result != 1 { - std::os::set_exit_status(255); + std::env::set_exit_status(255); } } diff --git a/src/test/run-make/unicode-input/span_length.rs b/src/test/run-make/unicode-input/span_length.rs index ebf3226334c..a70a1600765 100644 --- a/src/test/run-make/unicode-input/span_length.rs +++ b/src/test/run-make/unicode-input/span_length.rs @@ -95,10 +95,10 @@ fn main() { let expected_span = format!("\n{}^{}\n", repeat(" ").take(offset + 7).collect::(), repeat("~").take(8).collect::()); - assert!(err.contains(expected_span.as_slice())); + assert!(err.contains(&expected_span)); // Second snake is 8 ~s long, with 36 preceding spaces let expected_span = format!("\n{}^{}\n", repeat(" ").take(offset + 36).collect::(), repeat("~").take(8).collect::()); - assert!(err.contains(expected_span.as_slice())); + assert!(err.contains(&expected_span)); } diff --git a/src/test/run-pass-fulldeps/compiler-calls.rs b/src/test/run-pass-fulldeps/compiler-calls.rs index 7a3c32a45f9..4bacde0aadf 100644 --- a/src/test/run-pass-fulldeps/compiler-calls.rs +++ b/src/test/run-pass-fulldeps/compiler-calls.rs @@ -77,6 +77,6 @@ fn main() { let mut tc = TestCalls { count: 1 }; // we should never get use this filename, but lets make sure they are valid args. let args = vec!["compiler-calls".to_string(), "foo.rs".to_string()]; - rustc_driver::run_compiler(args.as_slice(), &mut tc); + rustc_driver::run_compiler(&args, &mut tc); assert!(tc.count == 30); } diff --git a/src/test/run-pass/create-dir-all-bare.rs b/src/test/run-pass-fulldeps/create-dir-all-bare.rs similarity index 84% rename from src/test/run-pass/create-dir-all-bare.rs rename to src/test/run-pass-fulldeps/create-dir-all-bare.rs index 475df629f63..e4fb7c19909 100644 --- a/src/test/run-pass/create-dir-all-bare.rs +++ b/src/test/run-pass-fulldeps/create-dir-all-bare.rs @@ -8,10 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(tempdir)] +// ignore-android + +#![feature(rustc_private)] + +extern crate rustc_back; use std::env; -use std::fs::{self, TempDir}; +use std::fs; +use rustc_back::tempdir::TempDir; fn main() { let td = TempDir::new("create-dir-all-bare").unwrap(); diff --git a/src/test/run-pass/rename-directory.rs b/src/test/run-pass-fulldeps/rename-directory.rs similarity index 89% rename from src/test/run-pass/rename-directory.rs rename to src/test/run-pass-fulldeps/rename-directory.rs index f149a70817a..a1e016bf2ea 100644 --- a/src/test/run-pass/rename-directory.rs +++ b/src/test/run-pass-fulldeps/rename-directory.rs @@ -11,12 +11,16 @@ // This test can't be a unit test in std, // because it needs TempDir, which is in extra +// ignore-android // pretty-expanded FIXME #23616 -#![feature(tempdir, path_ext)] +#![feature(rustc_private, path_ext)] + +extern crate rustc_back; use std::ffi::CString; -use std::fs::{self, TempDir, File, PathExt}; +use std::fs::{self, File, PathExt}; +use rustc_back::tempdir::TempDir; fn rename_directory() { let tmpdir = TempDir::new("rename_directory").ok().expect("rename_directory failed"); diff --git a/src/test/run-pass/backtrace.rs b/src/test/run-pass/backtrace.rs index 226a7c12df9..14d8bce061f 100644 --- a/src/test/run-pass/backtrace.rs +++ b/src/test/run-pass/backtrace.rs @@ -80,9 +80,9 @@ fn runtest(me: &str) { let s = str::from_utf8(&out.error).unwrap(); let mut i = 0; for _ in 0..2 { - i += s[i + 10..].find_str("stack backtrace").unwrap() + 10; + i += s[i + 10..].find("stack backtrace").unwrap() + 10; } - assert!(s[i + 10..].find_str("stack backtrace").is_none(), + assert!(s[i + 10..].find("stack backtrace").is_none(), "bad output4: {}", s); } diff --git a/src/test/run-pass/big-literals.rs b/src/test/run-pass/big-literals.rs index 09746380eba..b73eac0c714 100644 --- a/src/test/run-pass/big-literals.rs +++ b/src/test/run-pass/big-literals.rs @@ -10,11 +10,16 @@ // pretty-expanded FIXME #23616 +#![feature(core)] + +// Catch mistakes in the overflowing literals lint. +#![deny(overflowing_literals)] + pub fn main() { assert_eq!(0xffffffff, (-1 as u32)); assert_eq!(4294967295, (-1 as u32)); assert_eq!(0xffffffffffffffff, (-1 as u64)); assert_eq!(18446744073709551615, (-1 as u64)); - assert_eq!(-2147483648 - 1, 2147483647); + assert_eq!((-2147483648i32).wrapping_sub(1), 2147483647); } diff --git a/src/test/run-pass/capturing-logging.rs b/src/test/run-pass/capturing-logging.rs index b20de7113ec..f9b429a935a 100644 --- a/src/test/run-pass/capturing-logging.rs +++ b/src/test/run-pass/capturing-logging.rs @@ -22,7 +22,7 @@ use log::{set_logger, Logger, LogRecord}; use std::sync::mpsc::channel; use std::fmt; use std::old_io::{ChanReader, ChanWriter, Reader, Writer}; -use std::thread::Thread; +use std::thread; struct MyWriter(ChanWriter); @@ -36,7 +36,7 @@ impl Logger for MyWriter { fn main() { let (tx, rx) = channel(); let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx)); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { set_logger(box MyWriter(w) as Box); debug!("debug"); info!("info"); diff --git a/src/test/run-pass/child-outlives-parent.rs b/src/test/run-pass/child-outlives-parent.rs index 64642e51c09..7da1416602f 100644 --- a/src/test/run-pass/child-outlives-parent.rs +++ b/src/test/run-pass/child-outlives-parent.rs @@ -14,10 +14,10 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; fn child2(_s: String) { } pub fn main() { - let _x = Thread::spawn(move|| child2("hi".to_string())); + let _x = thread::spawn(move|| child2("hi".to_string())); } diff --git a/src/test/run-pass/clone-with-exterior.rs b/src/test/run-pass/clone-with-exterior.rs index fa663105ccd..16efceb9d7e 100644 --- a/src/test/run-pass/clone-with-exterior.rs +++ b/src/test/run-pass/clone-with-exterior.rs @@ -13,7 +13,7 @@ #![allow(unknown_features)] #![feature(box_syntax, std_misc)] -use std::thread::Thread; +use std::thread; struct Pair { a: isize, @@ -23,7 +23,7 @@ struct Pair { pub fn main() { let z: Box<_> = box Pair { a : 10, b : 12}; - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { assert_eq!(z.a, 10); assert_eq!(z.b, 12); }); diff --git a/src/test/run-pass/comm.rs b/src/test/run-pass/comm.rs index 43f10cfd060..859599596ae 100644 --- a/src/test/run-pass/comm.rs +++ b/src/test/run-pass/comm.rs @@ -10,12 +10,12 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; use std::sync::mpsc::{channel, Sender}; pub fn main() { let (tx, rx) = channel(); - let _t = Thread::spawn(move|| { child(&tx) }); + let _t = thread::scoped(move|| { child(&tx) }); let y = rx.recv().unwrap(); println!("received"); println!("{}", y); diff --git a/src/test/run-pass/core-run-destroy.rs b/src/test/run-pass/core-run-destroy.rs index a969f691154..03bf3851257 100644 --- a/src/test/run-pass/core-run-destroy.rs +++ b/src/test/run-pass/core-run-destroy.rs @@ -24,7 +24,7 @@ use std::old_io::{Process, Command, timer}; use std::time::Duration; use std::str; use std::sync::mpsc::channel; -use std::thread::Thread; +use std::thread; macro_rules! succeed { ($e:expr) => ( match $e { Ok(..) => {}, Err(e) => panic!("panic: {}", e) } @@ -86,7 +86,7 @@ pub fn test_destroy_actually_kills(force: bool) { let (tx, rx1) = channel(); let mut t = timer::Timer::new().unwrap(); let rx2 = t.oneshot(Duration::milliseconds(1000)); - Thread::spawn(move|| { + thread::spawn(move|| { select! { _ = rx2.recv() => unsafe { libc::exit(1) }, _ = rx1.recv() => {} diff --git a/src/test/run-pass/deriving-encodable-decodable-box.rs b/src/test/run-pass/deriving-encodable-decodable-box.rs index 17f4d93e24c..6ccedb0ad98 100644 --- a/src/test/run-pass/deriving-encodable-decodable-box.rs +++ b/src/test/run-pass/deriving-encodable-decodable-box.rs @@ -12,7 +12,7 @@ #![allow(unknown_features)] #![feature(box_syntax)] -#![feature(old_orphan_check, rustc_private)] +#![feature(rustc_private)] extern crate serialize; diff --git a/src/test/run-pass/deriving-encodable-decodable-cell-refcell.rs b/src/test/run-pass/deriving-encodable-decodable-cell-refcell.rs index d116c2dfc2a..d216062bb2d 100644 --- a/src/test/run-pass/deriving-encodable-decodable-cell-refcell.rs +++ b/src/test/run-pass/deriving-encodable-decodable-cell-refcell.rs @@ -13,7 +13,7 @@ // pretty-expanded FIXME #23616 -#![feature(old_orphan_check, rustc_private)] +#![feature(rustc_private)] extern crate serialize; diff --git a/src/test/run-pass/deriving-global.rs b/src/test/run-pass/deriving-global.rs index 2ca34e91b62..105d421b404 100644 --- a/src/test/run-pass/deriving-global.rs +++ b/src/test/run-pass/deriving-global.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(old_orphan_check, rand, rustc_private)] +#![feature(rand, rustc_private)] extern crate serialize; extern crate rand; diff --git a/src/test/run-pass/discrim-explicit-23030.rs b/src/test/run-pass/discrim-explicit-23030.rs new file mode 100644 index 00000000000..aed7b1527ce --- /dev/null +++ b/src/test/run-pass/discrim-explicit-23030.rs @@ -0,0 +1,156 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Issue 23030: Workaround overflowing discriminant +// with explicit assignments. + +// See also compile-fail/overflow-discrim.rs, which shows what +// happens if you leave the OhNo explicit cases out here. + +use std::{i8,u8,i16,u16,i32,u32,i64,u64,isize,usize}; + +fn f_i8() { + #[repr(i8)] + enum A { + Ok = i8::MAX - 1, + Ok2, + OhNo = i8::MIN, + NotTheEnd = -1, + Zero, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); + let z = (A::NotTheEnd, A::Zero).1 as i8; + assert_eq!(z, 0); +} + +fn f_u8() { + #[repr(u8)] + enum A { + Ok = u8::MAX - 1, + Ok2, + OhNo = u8::MIN, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); +} + +fn f_i16() { + #[repr(i16)] + enum A { + Ok = i16::MAX - 1, + Ok2, + OhNo = i16::MIN, + NotTheEnd = -1, + Zero, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); + let z = (A::NotTheEnd, A::Zero).1 as i16; + assert_eq!(z, 0); +} + +fn f_u16() { + #[repr(u16)] + enum A { + Ok = u16::MAX - 1, + Ok2, + OhNo = u16::MIN, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); +} + +fn f_i32() { + #[repr(i32)] + enum A { + Ok = i32::MAX - 1, + Ok2, + OhNo = i32::MIN, + NotTheEnd = -1, + Zero, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); + let z = (A::NotTheEnd, A::Zero).1 as i32; + assert_eq!(z, 0); +} + +fn f_u32() { + #[repr(u32)] + enum A { + Ok = u32::MAX - 1, + Ok2, + OhNo = u32::MIN, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); +} + +fn f_i64() { + #[repr(i64)] + enum A { + Ok = i64::MAX - 1, + Ok2, + OhNo = i64::MIN, + NotTheEnd = -1, + Zero, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); + let z = (A::NotTheEnd, A::Zero).1 as i64; + assert_eq!(z, 0); +} + +fn f_u64() { + #[repr(u64)] + enum A { + Ok = u64::MAX - 1, + Ok2, + OhNo = u64::MIN, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); +} + +fn f_isize() { + #[repr(isize)] + enum A { + Ok = isize::MAX - 1, + Ok2, + OhNo = isize::MIN, + NotTheEnd = -1, + Zero, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); + let z = (A::NotTheEnd, A::Zero).1 as isize; + assert_eq!(z, 0); +} + +fn f_usize() { + #[repr(usize)] + enum A { + Ok = usize::MAX - 1, + Ok2, + OhNo = usize::MIN, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); +} + +fn main() { + f_i8(); f_u8(); + f_i16(); f_u16(); + f_i32(); f_u32(); + f_i64(); f_u64(); + + f_isize(); f_usize(); +} diff --git a/src/test/run-pass/drop-with-type-ascription-2.rs b/src/test/run-pass/drop-with-type-ascription-2.rs index ddfaf54493f..3d4af80e30b 100644 --- a/src/test/run-pass/drop-with-type-ascription-2.rs +++ b/src/test/run-pass/drop-with-type-ascription-2.rs @@ -14,7 +14,7 @@ fn main() { let args = vec!("foobie", "asdf::asdf"); - let arr: Vec<&str> = args[1].split_str("::").collect(); + let arr: Vec<&str> = args[1].split("::").collect(); assert_eq!(arr[0], "asdf"); assert_eq!(arr[0], "asdf"); } diff --git a/src/test/run-pass/env-home-dir.rs b/src/test/run-pass/env-home-dir.rs index 2d0128ba89e..7fb96112125 100644 --- a/src/test/run-pass/env-home-dir.rs +++ b/src/test/run-pass/env-home-dir.rs @@ -11,7 +11,6 @@ // pretty-expanded FIXME #23616 #![feature(path)] -#![feature(convert)] use std::env::*; use std::path::PathBuf; diff --git a/src/test/run-pass/extern-call-scrub.rs b/src/test/run-pass/extern-call-scrub.rs index 069ecd92a56..e8c9bc76335 100644 --- a/src/test/run-pass/extern-call-scrub.rs +++ b/src/test/run-pass/extern-call-scrub.rs @@ -15,7 +15,7 @@ #![feature(libc, std_misc)] extern crate libc; -use std::thread::Thread; +use std::thread; mod rustrt { extern crate libc; @@ -46,7 +46,7 @@ fn count(n: libc::uintptr_t) -> libc::uintptr_t { pub fn main() { // Make sure we're on a task with small Rust stacks (main currently // has a large stack) - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { let result = count(12); println!("result = {}", result); assert_eq!(result, 2048); diff --git a/src/test/run-pass/hashmap-memory.rs b/src/test/run-pass/hashmap-memory.rs index 3d1b74438a8..5c96aaf4bd8 100644 --- a/src/test/run-pass/hashmap-memory.rs +++ b/src/test/run-pass/hashmap-memory.rs @@ -25,7 +25,7 @@ mod map_reduce { use std::collections::HashMap; use std::sync::mpsc::{channel, Sender}; use std::str; - use std::thread::Thread; + use std::thread; pub type putter<'a> = Box; @@ -37,7 +37,7 @@ mod map_reduce { for i in &inputs { let ctrl = ctrl.clone(); let i = i.clone(); - Thread::spawn(move|| map_task(ctrl.clone(), i.clone()) ); + thread::spawn(move|| map_task(ctrl.clone(), i.clone()) ); } } diff --git a/src/test/run-pass/init-large-type.rs b/src/test/run-pass/init-large-type.rs index ca4dba4198c..26d58d34b9d 100644 --- a/src/test/run-pass/init-large-type.rs +++ b/src/test/run-pass/init-large-type.rs @@ -16,7 +16,7 @@ #![feature(intrinsics, std_misc)] -use std::thread::Thread; +use std::thread; extern "rust-intrinsic" { pub fn init() -> T; @@ -26,7 +26,7 @@ const SIZE: usize = 1024 * 1024; fn main() { // do the test in a new thread to avoid (spurious?) stack overflows - let _ = Thread::scoped(|| { + let _ = thread::scoped(|| { let _memory: [u8; SIZE] = unsafe { init() }; }).join(); } diff --git a/src/test/run-pass/issue-11881.rs b/src/test/run-pass/issue-11881.rs index 811926826dd..35c25b33a97 100644 --- a/src/test/run-pass/issue-11881.rs +++ b/src/test/run-pass/issue-11881.rs @@ -10,7 +10,7 @@ // pretty-expanded FIXME #23616 -#![feature(old_orphan_check, rustc_private, old_io)] +#![feature(rustc_private, old_io)] extern crate rbml; extern crate serialize; diff --git a/src/test/run-pass/issue-13304.rs b/src/test/run-pass/issue-13304.rs index 876b329998e..c260aa95b57 100644 --- a/src/test/run-pass/issue-13304.rs +++ b/src/test/run-pass/issue-13304.rs @@ -29,8 +29,8 @@ fn main() { fn parent() { let args: Vec = env::args().collect(); let mut p = Command::new(&args[0]).arg("child") - .stdout(Stdio::capture()) - .stdin(Stdio::capture()) + .stdout(Stdio::piped()) + .stdin(Stdio::piped()) .spawn().unwrap(); p.stdin.as_mut().unwrap().write_all(b"test1\ntest2\ntest3").unwrap(); let out = p.wait_with_output().unwrap(); diff --git a/src/test/run-pass/issue-13494.rs b/src/test/run-pass/issue-13494.rs index 6159edbfe1e..d1b1647de78 100644 --- a/src/test/run-pass/issue-13494.rs +++ b/src/test/run-pass/issue-13494.rs @@ -16,7 +16,7 @@ #![feature(std_misc)] use std::sync::mpsc::{channel, Sender, Receiver}; -use std::thread::Thread; +use std::thread; fn helper(rx: Receiver>) { for tx in rx.iter() { @@ -26,7 +26,7 @@ fn helper(rx: Receiver>) { fn main() { let (tx, rx) = channel(); - let _t = Thread::spawn(move|| { helper(rx) }); + let _t = thread::scoped(move|| { helper(rx) }); let (snd, rcv) = channel::(); for _ in 1..100000 { snd.send(1).unwrap(); @@ -37,4 +37,5 @@ fn main() { _ = rcv.recv() => () } } + drop(tx); } diff --git a/src/test/run-pass/issue-14021.rs b/src/test/run-pass/issue-14021.rs index e773f03f212..907967d115d 100644 --- a/src/test/run-pass/issue-14021.rs +++ b/src/test/run-pass/issue-14021.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(old_orphan_check, rustc_private)] +#![feature(rustc_private)] extern crate serialize; diff --git a/src/test/run-pass/issue-14456.rs b/src/test/run-pass/issue-14456.rs index f897b00ceff..ab9633ca1fe 100644 --- a/src/test/run-pass/issue-14456.rs +++ b/src/test/run-pass/issue-14456.rs @@ -38,9 +38,9 @@ fn child() { fn test() { let args: Vec = env::args().collect(); let mut p = Command::new(&args[0]).arg("child") - .stdin(Stdio::capture()) - .stdout(Stdio::capture()) - .stderr(Stdio::capture()) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) .spawn().unwrap(); assert!(p.wait().unwrap().success()); } diff --git a/src/test/run-pass/issue-15734.rs b/src/test/run-pass/issue-15734.rs index d058cb73711..67ce6a1c44f 100644 --- a/src/test/run-pass/issue-15734.rs +++ b/src/test/run-pass/issue-15734.rs @@ -13,7 +13,7 @@ // pretty-expanded FIXME #23616 -#![feature(old_orphan_check, core)] +#![feature(core)] use std::ops::Index; diff --git a/src/test/run-pass/issue-17351.rs b/src/test/run-pass/issue-17351.rs index 0dac3295c1b..6e93194647a 100644 --- a/src/test/run-pass/issue-17351.rs +++ b/src/test/run-pass/issue-17351.rs @@ -12,6 +12,10 @@ #![feature(core)] +trait Str { fn foo(&self) {} } +impl Str for str {} +impl<'a, S: ?Sized> Str for &'a S where S: Str {} + fn main() { let _: &Str = &"x"; } diff --git a/src/test/run-pass/issue-17746.rs b/src/test/run-pass/issue-17746.rs new file mode 100644 index 00000000000..a66d5e10288 --- /dev/null +++ b/src/test/run-pass/issue-17746.rs @@ -0,0 +1,33 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #17746 + +fn main() {} + +struct A; + +impl A { + fn b(&mut self) { + self.a() + } +} + +trait Foo { + fn dummy(&self) {} +} +trait Bar { + fn a(&self); +} + +impl Foo for A {} +impl Bar for T where T: Foo { + fn a(&self) {} +} diff --git a/src/test/run-pass/issue-20454.rs b/src/test/run-pass/issue-20454.rs index 0e3d4e0e40d..d527d9519cf 100644 --- a/src/test/run-pass/issue-20454.rs +++ b/src/test/run-pass/issue-20454.rs @@ -12,10 +12,12 @@ use std::thread; -fn main() { - thread::Thread::spawn(move || { // no need for -> () +fn _foo() { + let _t = thread::scoped(move || { // no need for -> () loop { println!("hello"); } }); } + +fn main() {} diff --git a/src/test/run-pass/issue-20797.rs b/src/test/run-pass/issue-20797.rs index d0720ec593f..45d31d4a7f1 100644 --- a/src/test/run-pass/issue-20797.rs +++ b/src/test/run-pass/issue-20797.rs @@ -12,8 +12,6 @@ // pretty-expanded FIXME #23616 -#![feature(convert)] - use std::default::Default; use std::io; use std::fs; diff --git a/src/test/run-pass/issue-22577.rs b/src/test/run-pass/issue-22577.rs index a47c844e199..2c4141b0bd3 100644 --- a/src/test/run-pass/issue-22577.rs +++ b/src/test/run-pass/issue-22577.rs @@ -15,13 +15,14 @@ use std::{fs, net}; fn assert_both() {} +fn assert_send() {} fn main() { assert_both::(); assert_both::(); assert_both::(); assert_both::(); - assert_both::(); + assert_send::(); assert_both::(); assert_both::(); diff --git a/src/test/run-pass/issue-2718.rs b/src/test/run-pass/issue-2718.rs index 7842bcb7dd1..71d1439dd2b 100644 --- a/src/test/run-pass/issue-2718.rs +++ b/src/test/run-pass/issue-2718.rs @@ -21,7 +21,7 @@ pub mod pipes { use std::mem::{forget, transmute}; use std::mem::{replace, swap}; use std::mem; - use std::thread::Thread; + use std::thread; use std::marker::Send; pub struct Stuff { @@ -115,7 +115,7 @@ pub mod pipes { let old_state = swap_state_acq(&mut (*p).state, blocked); match old_state { - empty | blocked => { Thread::yield_now(); } + empty | blocked => { thread::yield_now(); } full => { let payload = replace(&mut p.payload, None); return Some(payload.unwrap()) diff --git a/src/test/run-pass/issue-3609.rs b/src/test/run-pass/issue-3609.rs index 2bd56e81687..45eb21374e2 100644 --- a/src/test/run-pass/issue-3609.rs +++ b/src/test/run-pass/issue-3609.rs @@ -11,7 +11,7 @@ #![allow(unknown_features)] #![feature(std_misc)] -use std::thread::Thread; +use std::thread; use std::sync::mpsc::Sender; use std::thunk::Invoke; @@ -24,7 +24,7 @@ enum Msg } fn foo(name: String, samples_chan: Sender) { - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { let mut samples_chan = samples_chan; // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. diff --git a/src/test/run-pass/issue-3743.rs b/src/test/run-pass/issue-3743.rs index 03699ff8d60..7f66b6b25b8 100644 --- a/src/test/run-pass/issue-3743.rs +++ b/src/test/run-pass/issue-3743.rs @@ -10,7 +10,6 @@ // If `Mul` used an associated type for its output, this test would // work more smoothly. -#![feature(old_orphan_check)] use std::ops::Mul; diff --git a/src/test/run-pass/issue-8827.rs b/src/test/run-pass/issue-8827.rs index 4e1ff84291e..280311af6fb 100644 --- a/src/test/run-pass/issue-8827.rs +++ b/src/test/run-pass/issue-8827.rs @@ -10,12 +10,12 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; use std::sync::mpsc::{channel, Receiver}; fn periodical(n: isize) -> Receiver { let (chan, port) = channel(); - Thread::spawn(move|| { + thread::spawn(move|| { loop { for _ in 1..n { match chan.send(false) { @@ -34,7 +34,7 @@ fn periodical(n: isize) -> Receiver { fn integers() -> Receiver { let (chan, port) = channel(); - Thread::spawn(move|| { + thread::spawn(move|| { let mut i = 1; loop { match chan.send(i) { diff --git a/src/test/run-pass/issue-9396.rs b/src/test/run-pass/issue-9396.rs index aeba6889f49..bfaf060e43c 100644 --- a/src/test/run-pass/issue-9396.rs +++ b/src/test/run-pass/issue-9396.rs @@ -14,12 +14,12 @@ use std::sync::mpsc::{TryRecvError, channel}; use std::old_io::timer::Timer; -use std::thread::Thread; +use std::thread; use std::time::Duration; pub fn main() { let (tx, rx) = channel(); - let _t = Thread::scoped(move||{ + let _t = thread::scoped(move||{ let mut timer = Timer::new().unwrap(); timer.sleep(Duration::milliseconds(10)); tx.send(()).unwrap(); diff --git a/src/test/run-pass/ivec-tag.rs b/src/test/run-pass/ivec-tag.rs index d5138f6fdbc..8ae084dce8c 100644 --- a/src/test/run-pass/ivec-tag.rs +++ b/src/test/run-pass/ivec-tag.rs @@ -12,7 +12,7 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; use std::sync::mpsc::{channel, Sender}; fn producer(tx: &Sender>) { @@ -23,7 +23,7 @@ fn producer(tx: &Sender>) { pub fn main() { let (tx, rx) = channel::>(); - let _prod = Thread::spawn(move|| { + let _prod = thread::scoped(move|| { producer(&tx) }); diff --git a/src/test/run-pass/kindck-implicit-close-over-mut-var.rs b/src/test/run-pass/kindck-implicit-close-over-mut-var.rs index 4645e8ff392..11b1d70137d 100644 --- a/src/test/run-pass/kindck-implicit-close-over-mut-var.rs +++ b/src/test/run-pass/kindck-implicit-close-over-mut-var.rs @@ -10,7 +10,7 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; fn user(_i: isize) {} @@ -18,7 +18,7 @@ fn foo() { // Here, i is *copied* into the proc (heap closure). // Requires allocation. The proc's copy is not mutable. let mut i = 0; - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { user(i); println!("spawned {}", i) }); @@ -31,7 +31,7 @@ fn bar() { // mutable outside of the proc. let mut i = 0; while i < 10 { - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { user(i); }); i += 1; @@ -42,7 +42,7 @@ fn car() { // Here, i must be shadowed in the proc to be mutable. let mut i = 0; while i < 10 { - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { let mut i = i; i += 1; user(i); diff --git a/src/test/run-pass/macro-with-braces-in-expr-position.rs b/src/test/run-pass/macro-with-braces-in-expr-position.rs index 80a3b8c9edd..4881a5ab647 100644 --- a/src/test/run-pass/macro-with-braces-in-expr-position.rs +++ b/src/test/run-pass/macro-with-braces-in-expr-position.rs @@ -10,13 +10,13 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; macro_rules! expr { ($e: expr) => { $e } } macro_rules! spawn { ($($code: tt)*) => { - expr!(Thread::spawn(move|| {$($code)*})) + expr!(thread::spawn(move|| {$($code)*})) } } diff --git a/src/test/run-pass/method-two-traits-distinguished-via-where-clause.rs b/src/test/run-pass/method-two-traits-distinguished-via-where-clause.rs index 329b77776b6..77072bdec90 100644 --- a/src/test/run-pass/method-two-traits-distinguished-via-where-clause.rs +++ b/src/test/run-pass/method-two-traits-distinguished-via-where-clause.rs @@ -33,6 +33,6 @@ impl B for *const [T] { fn main() { let x: [isize; 4] = [1,2,3,4]; - let xptr = x.as_slice() as *const [isize]; + let xptr = &x[..] as *const [isize]; xptr.foo(); } diff --git a/src/test/run-pass/minmax-stability-issue-23687.rs b/src/test/run-pass/minmax-stability-issue-23687.rs new file mode 100644 index 00000000000..86dd1a04532 --- /dev/null +++ b/src/test/run-pass/minmax-stability-issue-23687.rs @@ -0,0 +1,83 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(core)] +use std::fmt::Debug; +use std::cmp::{self, PartialOrd, Ordering}; +use std::iter::MinMaxResult::MinMax; + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +struct Foo { + n: u8, + name: &'static str +} + +impl PartialOrd for Foo { + fn partial_cmp(&self, other: &Foo) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Foo { + fn cmp(&self, other: &Foo) -> Ordering { + self.n.cmp(&other.n) + } +} + +fn main() { + let a = Foo { n: 4, name: "a" }; + let b = Foo { n: 4, name: "b" }; + let c = Foo { n: 8, name: "c" }; + let d = Foo { n: 8, name: "d" }; + let e = Foo { n: 22, name: "e" }; + let f = Foo { n: 22, name: "f" }; + + let data = [a, b, c, d, e, f]; + + // `min` should return the left when the values are equal + assert_eq!(data.iter().min(), Some(&a)); + assert_eq!(data.iter().min_by(|a| a.n), Some(&a)); + assert_eq!(cmp::min(a, b), a); + assert_eq!(cmp::min(b, a), b); + assert_eq!(cmp::partial_min(a, b), Some(a)); + assert_eq!(cmp::partial_min(b, a), Some(b)); + + // `max` should return the right when the values are equal + assert_eq!(data.iter().max(), Some(&f)); + assert_eq!(data.iter().max_by(|a| a.n), Some(&f)); + assert_eq!(cmp::max(e, f), f); + assert_eq!(cmp::max(f, e), e); + assert_eq!(cmp::partial_max(e, f), Some(f)); + assert_eq!(cmp::partial_max(f, e), Some(e)); + + // Similar for `min_max` + assert_eq!(data.iter().min_max(), MinMax(&a, &f)); + assert_eq!(data[1..5].iter().min_max(), MinMax(&b, &e)); + assert_eq!(data[2..4].iter().min_max(), MinMax(&c, &d)); + + let mut presorted = data.to_vec(); + presorted.sort(); + assert_stable(&presorted); + + let mut presorted = data.to_vec(); + presorted.sort_by(|a, b| a.cmp(b)); + assert_stable(&presorted); + + // Assert that sorted and min/max are the same + fn assert_stable(presorted: &[T]) { + for slice in presorted.windows(2) { + let a = &slice[0]; + let b = &slice[1]; + + assert_eq!(a, cmp::min(a, b)); + assert_eq!(b, cmp::max(a, b)); + } + } +} diff --git a/src/test/run-pass/moves-based-on-type-capture-clause.rs b/src/test/run-pass/moves-based-on-type-capture-clause.rs index f0eba366e71..b6509d28036 100644 --- a/src/test/run-pass/moves-based-on-type-capture-clause.rs +++ b/src/test/run-pass/moves-based-on-type-capture-clause.rs @@ -10,11 +10,11 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; pub fn main() { let x = "Hello world!".to_string(); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { println!("{}", x); }); } diff --git a/src/test/run-pass/option-ext.rs b/src/test/run-pass/option-ext.rs index 8f5a5e8ece7..03ba6097cd9 100644 --- a/src/test/run-pass/option-ext.rs +++ b/src/test/run-pass/option-ext.rs @@ -12,7 +12,7 @@ pub fn main() { let thing = "{{ f }}"; - let f = thing.find_str("{{"); + let f = thing.find("{{"); if f.is_none() { println!("None!"); diff --git a/src/test/run-pass/out-of-stack-new-thread-no-split.rs b/src/test/run-pass/out-of-stack-new-thread-no-split.rs index 3c322f72b75..f08ed6e7f9c 100644 --- a/src/test/run-pass/out-of-stack-new-thread-no-split.rs +++ b/src/test/run-pass/out-of-stack-new-thread-no-split.rs @@ -18,7 +18,7 @@ use std::old_io::process::Command; use std::env; -use std::thread::Thread; +use std::thread; // lifted from the test module // Inlining to avoid llvm turning the recursive functions into tail calls, @@ -37,7 +37,7 @@ fn recurse() { fn main() { let args: Vec = env::args().collect(); if args.len() > 1 && args[1] == "recurse" { - let _t = Thread::scoped(recurse); + let _t = thread::scoped(recurse); } else { let recurse = Command::new(&args[0]).arg("recurse").output().unwrap(); assert!(!recurse.status.success()); diff --git a/src/test/run-pass/process-exit.rs b/src/test/run-pass/process-exit.rs new file mode 100644 index 00000000000..9ef66ff2d71 --- /dev/null +++ b/src/test/run-pass/process-exit.rs @@ -0,0 +1,31 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::env; +use std::process::{self, Command, Stdio}; + +fn main() { + let args: Vec = env::args().collect(); + if args.len() > 1 && args[1] == "child" { + child(); + } else { + parent(); + } +} + +fn parent() { + let args: Vec = env::args().collect(); + let status = Command::new(&args[0]).arg("child").status().unwrap(); + assert_eq!(status.code(), Some(2)); +} + +fn child() -> i32 { + process::exit(2); +} diff --git a/src/test/run-pass/regions-refcell.rs b/src/test/run-pass/regions-refcell.rs index febf5f92ef6..63525b36206 100644 --- a/src/test/run-pass/regions-refcell.rs +++ b/src/test/run-pass/regions-refcell.rs @@ -29,7 +29,7 @@ fn foo<'a>(map: RefCell>) { // supposed to match the lifetime `'a`) ... fn foo<'a>(map: RefCell>) { let one = [1]; - assert_eq!(map.borrow().get("one"), Some(&one.as_slice())); + assert_eq!(map.borrow().get("one"), Some(&&one[..])); } #[cfg(all(not(cannot_use_this_yet),not(cannot_use_this_yet_either)))] diff --git a/src/test/run-pass/running-with-no-runtime.rs b/src/test/run-pass/running-with-no-runtime.rs index c5b59e6c6e0..abad08c7ac6 100644 --- a/src/test/run-pass/running-with-no-runtime.rs +++ b/src/test/run-pass/running-with-no-runtime.rs @@ -10,7 +10,7 @@ #![feature(start, os, std_misc, old_io)] -use std::ffi; +use std::ffi::CStr; use std::old_io::process::{Command, ProcessOutput}; use std::os; use std::rt::unwind::try; @@ -38,7 +38,7 @@ fn start(argc: isize, argv: *const *const u8) -> isize { let args = unsafe { (0..argc as usize).map(|i| { let ptr = *argv.offset(i as isize) as *const _; - ffi::c_str_to_bytes(&ptr).to_vec() + CStr::from_ptr(ptr).to_bytes().to_vec() }).collect::>() }; let me = &*args[0]; diff --git a/src/test/run-pass/rust-log-filter.rs b/src/test/run-pass/rust-log-filter.rs index bc379f1a76f..660b1e2036d 100644 --- a/src/test/run-pass/rust-log-filter.rs +++ b/src/test/run-pass/rust-log-filter.rs @@ -19,7 +19,7 @@ extern crate log; use std::sync::mpsc::{channel, Sender, Receiver}; -use std::thread::Thread; +use std::thread; pub struct ChannelLogger { tx: Sender @@ -41,7 +41,7 @@ impl log::Logger for ChannelLogger { pub fn main() { let (logger, rx) = ChannelLogger::new(); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { log::set_logger(logger); info!("foo"); diff --git a/src/test/run-pass/send-is-not-static-par-for.rs b/src/test/run-pass/send-is-not-static-par-for.rs index 5815eaa01ea..99ae3b7c7d8 100644 --- a/src/test/run-pass/send-is-not-static-par-for.rs +++ b/src/test/run-pass/send-is-not-static-par-for.rs @@ -11,7 +11,7 @@ // pretty-expanded FIXME #23616 #![feature(core, std_misc)] -use std::thread::Thread; +use std::thread; use std::sync::Mutex; fn par_for(iter: I, f: F) @@ -21,7 +21,7 @@ fn par_for(iter: I, f: F) { let f = &f; let _guards: Vec<_> = iter.map(|elem| { - Thread::scoped(move || { + thread::scoped(move || { f(elem) }) }).collect(); diff --git a/src/test/run-pass/send-resource.rs b/src/test/run-pass/send-resource.rs index 2c897c48a33..3f64b2adb63 100644 --- a/src/test/run-pass/send-resource.rs +++ b/src/test/run-pass/send-resource.rs @@ -12,7 +12,7 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; use std::sync::mpsc::channel; struct test { @@ -32,7 +32,7 @@ fn test(f: isize) -> test { pub fn main() { let (tx, rx) = channel(); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { let (tx2, rx2) = channel(); tx.send(tx2).unwrap(); diff --git a/src/test/run-pass/simd-binop.rs b/src/test/run-pass/simd-binop.rs index 0d26b75c2ad..9f7b78e4e33 100644 --- a/src/test/run-pass/simd-binop.rs +++ b/src/test/run-pass/simd-binop.rs @@ -32,6 +32,7 @@ pub fn main() { assert!(eq_u32x4(u32x4(1, 2, 3, 4) + u32x4(4, 3, 2, 1), u32x4(5, 5, 5, 5))); assert!(eq_u32x4(u32x4(4, 5, 6, 7) - u32x4(4, 3, 2, 1), u32x4(0, 2, 4, 6))); assert!(eq_u32x4(u32x4(1, 2, 3, 4) * u32x4(4, 3, 2, 1), u32x4(4, 6, 6, 4))); + assert!(eq_u32x4(u32x4(1, 2, 3, 4) / u32x4(4, 3, 2, 1), u32x4(0, 0, 1, 4))); assert!(eq_u32x4(u32x4(1, 2, 3, 4) & u32x4(4, 3, 2, 1), u32x4(0, 2, 2, 0))); assert!(eq_u32x4(u32x4(1, 2, 3, 4) | u32x4(4, 3, 2, 1), u32x4(5, 3, 3, 5))); assert!(eq_u32x4(u32x4(1, 2, 3, 4) ^ u32x4(4, 3, 2, 1), u32x4(5, 1, 1, 5))); @@ -41,6 +42,7 @@ pub fn main() { assert!(eq_i32x4(i32x4(1, 2, 3, 4) + i32x4(4, 3, 2, 1), i32x4(5, 5, 5, 5))); assert!(eq_i32x4(i32x4(1, 2, 3, 4) - i32x4(4, 3, 2, 1), i32x4(-3, -1, 1, 3))); assert!(eq_i32x4(i32x4(1, 2, 3, 4) * i32x4(4, 3, 2, 1), i32x4(4, 6, 6, 4))); + assert!(eq_i32x4(i32x4(1, 2, 3, 4) / i32x4(4, 3, 2, 1), i32x4(0, 0, 1, 4))); assert!(eq_i32x4(i32x4(1, 2, 3, 4) & i32x4(4, 3, 2, 1), i32x4(0, 2, 2, 0))); assert!(eq_i32x4(i32x4(1, 2, 3, 4) | i32x4(4, 3, 2, 1), i32x4(5, 3, 3, 5))); assert!(eq_i32x4(i32x4(1, 2, 3, 4) ^ i32x4(4, 3, 2, 1), i32x4(5, 1, 1, 5))); diff --git a/src/test/run-pass/small-enum-range-edge.rs b/src/test/run-pass/small-enum-range-edge.rs index df204065d16..a87a3072c8a 100644 --- a/src/test/run-pass/small-enum-range-edge.rs +++ b/src/test/run-pass/small-enum-range-edge.rs @@ -10,6 +10,9 @@ // pretty-expanded FIXME #23616 +// this is for the wrapping_add call below. +#![feature(core)] + /*! * Tests the range assertion wraparound case in trans::middle::adt::load_discr. */ @@ -29,8 +32,8 @@ static CLs: Es = Es::Ls; static CHs: Es = Es::Hs; pub fn main() { - assert_eq!((Eu::Hu as u8) + 1, Eu::Lu as u8); - assert_eq!((Es::Hs as i8) + 1, Es::Ls as i8); + assert_eq!((Eu::Hu as u8).wrapping_add(1), Eu::Lu as u8); + assert_eq!((Es::Hs as i8).wrapping_add(1), Es::Ls as i8); assert_eq!(CLu as u8, Eu::Lu as u8); assert_eq!(CHu as u8, Eu::Hu as u8); assert_eq!(CLs as i8, Es::Ls as i8); diff --git a/src/test/run-pass/stat.rs b/src/test/run-pass/stat.rs deleted file mode 100644 index c453f9252ef..00000000000 --- a/src/test/run-pass/stat.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// pretty-expanded FIXME #23616 - -#![feature(tempdir, path_ext)] - -use std::fs::{File, TempDir}; -use std::io::prelude::*; - -pub fn main() { - let dir = TempDir::new_in(".", "").unwrap(); - let path = dir.path().join("file"); - - { - match File::create(&path) { - Err(..) => unreachable!(), - Ok(f) => { - let mut f = f; - for _ in 0..1000 { - f.write(&[0]); - } - } - } - } - - assert!(path.exists()); - assert_eq!(path.metadata().unwrap().len(), 1000); -} diff --git a/src/test/run-pass/syntax-extension-source-utils.rs b/src/test/run-pass/syntax-extension-source-utils.rs index b3f503aad34..8834fd39d1d 100644 --- a/src/test/run-pass/syntax-extension-source-utils.rs +++ b/src/test/run-pass/syntax-extension-source-utils.rs @@ -36,7 +36,6 @@ pub fn main() { assert!( include_str!("syntax-extension-source-utils-files/includeme.\ fragment").to_string() - .as_slice() .starts_with("/* this is for ")); assert!( include_bytes!("syntax-extension-source-utils-files/includeme.fragment") @@ -44,8 +43,5 @@ pub fn main() { // The Windows tests are wrapped in an extra module for some reason assert!((m1::m2::where_am_i().ends_with("m1::m2"))); - assert!(match (47, "( 2 * 3 ) + 5") { - (line!(), stringify!((2*3) + 5)) => true, - _ => false - }) + assert_eq!((46, "( 2 * 3 ) + 5"), (line!(), stringify!((2*3) + 5))); } diff --git a/src/test/run-pass/task-comm-0.rs b/src/test/run-pass/task-comm-0.rs index 05197cd6a3d..786dd2c7612 100644 --- a/src/test/run-pass/task-comm-0.rs +++ b/src/test/run-pass/task-comm-0.rs @@ -10,7 +10,7 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; use std::sync::mpsc::{channel, Sender}; pub fn main() { test05(); } @@ -26,7 +26,7 @@ fn test05_start(tx : &Sender) { fn test05() { let (tx, rx) = channel(); - let _t = Thread::spawn(move|| { test05_start(&tx) }); + let _t = thread::scoped(move|| { test05_start(&tx) }); let mut value: isize = rx.recv().unwrap(); println!("{}", value); value = rx.recv().unwrap(); diff --git a/src/test/run-pass/task-comm-1.rs b/src/test/run-pass/task-comm-1.rs index e882d8506fc..9c3466f162b 100644 --- a/src/test/run-pass/task-comm-1.rs +++ b/src/test/run-pass/task-comm-1.rs @@ -10,13 +10,13 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; pub fn main() { test00(); } fn start() { println!("Started / Finished task."); } fn test00() { - let _ = Thread::scoped(move|| start() ).join(); + let _ = thread::scoped(move|| start() ).join(); println!("Completing."); } diff --git a/src/test/run-pass/task-comm-10.rs b/src/test/run-pass/task-comm-10.rs index 99eebdb601a..f25bb3ff71a 100644 --- a/src/test/run-pass/task-comm-10.rs +++ b/src/test/run-pass/task-comm-10.rs @@ -10,7 +10,7 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; use std::sync::mpsc::{channel, Sender}; fn start(tx: &Sender>) { @@ -29,10 +29,10 @@ fn start(tx: &Sender>) { pub fn main() { let (tx, rx) = channel(); - let _child = Thread::spawn(move|| { start(&tx) }); + let _child = thread::scoped(move|| { start(&tx) }); let mut c = rx.recv().unwrap(); c.send("A".to_string()).unwrap(); c.send("B".to_string()).unwrap(); - Thread::yield_now(); + thread::yield_now(); } diff --git a/src/test/run-pass/task-comm-11.rs b/src/test/run-pass/task-comm-11.rs index 9ef5afab2e0..ec9ed53c1dc 100644 --- a/src/test/run-pass/task-comm-11.rs +++ b/src/test/run-pass/task-comm-11.rs @@ -13,7 +13,7 @@ #![feature(std_misc)] use std::sync::mpsc::{channel, Sender}; -use std::thread::Thread; +use std::thread; fn start(tx: &Sender>) { let (tx2, _rx) = channel(); @@ -22,7 +22,7 @@ fn start(tx: &Sender>) { pub fn main() { let (tx, rx) = channel(); - let _child = Thread::spawn(move|| { + let _child = thread::scoped(move|| { start(&tx) }); let _tx = rx.recv().unwrap(); diff --git a/src/test/run-pass/task-comm-12.rs b/src/test/run-pass/task-comm-12.rs index 8921529c6be..03305091a2d 100644 --- a/src/test/run-pass/task-comm-12.rs +++ b/src/test/run-pass/task-comm-12.rs @@ -10,7 +10,7 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; pub fn main() { test00(); } @@ -18,14 +18,14 @@ fn start(_task_number: isize) { println!("Started / Finished task."); } fn test00() { let i: isize = 0; - let mut result = Thread::scoped(move|| { + let mut result = thread::scoped(move|| { start(i) }); // Sleep long enough for the task to finish. let mut i = 0_usize; while i < 10000 { - Thread::yield_now(); + thread::yield_now(); i += 1; } diff --git a/src/test/run-pass/task-comm-13.rs b/src/test/run-pass/task-comm-13.rs index 3a0757548e8..15ceacd672f 100644 --- a/src/test/run-pass/task-comm-13.rs +++ b/src/test/run-pass/task-comm-13.rs @@ -11,7 +11,7 @@ #![feature(std_misc)] use std::sync::mpsc::{channel, Sender}; -use std::thread::Thread; +use std::thread; fn start(tx: &Sender, start: isize, number_of_messages: isize) { let mut i: isize = 0; @@ -21,6 +21,6 @@ fn start(tx: &Sender, start: isize, number_of_messages: isize) { pub fn main() { println!("Check that we don't deadlock."); let (tx, rx) = channel(); - let _ = Thread::scoped(move|| { start(&tx, 0, 10) }).join(); + let _t = thread::scoped(move|| { start(&tx, 0, 10) }).join(); println!("Joined task"); } diff --git a/src/test/run-pass/task-comm-14.rs b/src/test/run-pass/task-comm-14.rs index 2ef09cdcf87..1e2d9fe52df 100644 --- a/src/test/run-pass/task-comm-14.rs +++ b/src/test/run-pass/task-comm-14.rs @@ -11,7 +11,7 @@ #![feature(std_misc)] use std::sync::mpsc::{channel, Sender}; -use std::thread::Thread; +use std::thread; pub fn main() { let (tx, rx) = channel(); @@ -21,7 +21,7 @@ pub fn main() { while (i > 0) { println!("{}", i); let tx = tx.clone(); - Thread::spawn({let i = i; move|| { child(i, &tx) }}); + thread::scoped({let i = i; move|| { child(i, &tx) }}); i = i - 1; } diff --git a/src/test/run-pass/task-comm-15.rs b/src/test/run-pass/task-comm-15.rs index 605900495b5..2663595aecf 100644 --- a/src/test/run-pass/task-comm-15.rs +++ b/src/test/run-pass/task-comm-15.rs @@ -13,7 +13,7 @@ #![feature(std_misc)] use std::sync::mpsc::{channel, Sender}; -use std::thread::Thread; +use std::thread; fn start(tx: &Sender, i0: isize) { let mut i = i0; @@ -29,7 +29,7 @@ pub fn main() { // the child's point of view the receiver may die. We should // drop messages on the floor in this case, and not crash! let (tx, rx) = channel(); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { start(&tx, 10) }); rx.recv(); diff --git a/src/test/run-pass/task-comm-17.rs b/src/test/run-pass/task-comm-17.rs index 6c27292d19d..de334c77aa3 100644 --- a/src/test/run-pass/task-comm-17.rs +++ b/src/test/run-pass/task-comm-17.rs @@ -16,11 +16,11 @@ // This test is specifically about spawning temporary closures. -use std::thread::Thread; +use std::thread; fn f() { } pub fn main() { - let _t = Thread::scoped(move|| f() ).join(); + let _t = thread::scoped(move|| f() ).join(); } diff --git a/src/test/run-pass/task-comm-3.rs b/src/test/run-pass/task-comm-3.rs index d742b7bb11a..254ad653c48 100644 --- a/src/test/run-pass/task-comm-3.rs +++ b/src/test/run-pass/task-comm-3.rs @@ -12,7 +12,7 @@ // no-pretty-expanded FIXME #15189 -use std::thread::Thread; +use std::thread; use std::sync::mpsc::{channel, Sender}; pub fn main() { println!("===== WITHOUT THREADS ====="); test00(); } @@ -42,7 +42,7 @@ fn test00() { let mut results = Vec::new(); while i < number_of_tasks { let tx = tx.clone(); - results.push(Thread::scoped({ + results.push(thread::scoped({ let i = i; move|| { test00_start(&tx, i, number_of_messages) diff --git a/src/test/run-pass/task-comm-7.rs b/src/test/run-pass/task-comm-7.rs index 82e8fe0af41..b05e36552a2 100644 --- a/src/test/run-pass/task-comm-7.rs +++ b/src/test/run-pass/task-comm-7.rs @@ -14,7 +14,7 @@ #![allow(dead_assignment)] use std::sync::mpsc::{channel, Sender}; -use std::thread::Thread; +use std::thread; pub fn main() { test00(); } @@ -31,19 +31,19 @@ fn test00() { let number_of_messages: isize = 10; let tx2 = tx.clone(); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { test00_start(&tx2, number_of_messages * 0, number_of_messages); }); let tx2 = tx.clone(); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { test00_start(&tx2, number_of_messages * 1, number_of_messages); }); let tx2 = tx.clone(); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { test00_start(&tx2, number_of_messages * 2, number_of_messages); }); let tx2 = tx.clone(); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { test00_start(&tx2, number_of_messages * 3, number_of_messages); }); diff --git a/src/test/run-pass/task-comm-9.rs b/src/test/run-pass/task-comm-9.rs index 3e4a75b8e22..758764aa9fd 100644 --- a/src/test/run-pass/task-comm-9.rs +++ b/src/test/run-pass/task-comm-9.rs @@ -10,7 +10,7 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; use std::sync::mpsc::{channel, Sender}; pub fn main() { test00(); } @@ -26,7 +26,7 @@ fn test00() { let (tx, rx) = channel(); let number_of_messages: isize = 10; - let result = Thread::scoped(move|| { + let result = thread::scoped(move|| { test00_start(&tx, number_of_messages); }); diff --git a/src/test/run-pass/task-life-0.rs b/src/test/run-pass/task-life-0.rs index 7da7a1afb9a..b97f4355b3e 100644 --- a/src/test/run-pass/task-life-0.rs +++ b/src/test/run-pass/task-life-0.rs @@ -12,10 +12,10 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; pub fn main() { - let _t = Thread::spawn(move|| child("Hello".to_string()) ); + let _t = thread::scoped(move|| child("Hello".to_string()) ); } fn child(_s: String) { diff --git a/src/test/run-pass/task-spawn-move-and-copy.rs b/src/test/run-pass/task-spawn-move-and-copy.rs index 637f564f726..aa7b61bf112 100644 --- a/src/test/run-pass/task-spawn-move-and-copy.rs +++ b/src/test/run-pass/task-spawn-move-and-copy.rs @@ -13,7 +13,7 @@ #![allow(unknown_features)] #![feature(box_syntax, std_misc)] -use std::thread::Thread; +use std::thread; use std::sync::mpsc::channel; pub fn main() { @@ -22,7 +22,7 @@ pub fn main() { let x: Box = box 1; let x_in_parent = &(*x) as *const isize as usize; - let _t = Thread::spawn(move || { + let _t = thread::scoped(move || { let x_in_child = &(*x) as *const isize as usize; tx.send(x_in_child).unwrap(); }); diff --git a/src/test/run-pass/tcp-accept-stress.rs b/src/test/run-pass/tcp-accept-stress.rs index 99d36a179aa..00467e56334 100644 --- a/src/test/run-pass/tcp-accept-stress.rs +++ b/src/test/run-pass/tcp-accept-stress.rs @@ -19,7 +19,7 @@ use std::old_io::{TcpListener, Listener, Acceptor, EndOfFile, TcpStream}; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::mpsc::channel; -use std::thread::Thread; +use std::thread; static N: usize = 8; static M: usize = 20; @@ -40,7 +40,7 @@ fn test() { let a = a.clone(); let cnt = cnt.clone(); let srv_tx = srv_tx.clone(); - Thread::scoped(move|| { + thread::scoped(move|| { let mut a = a; loop { match a.accept() { @@ -59,7 +59,7 @@ fn test() { let _t = (0..N).map(|_| { let cli_tx = cli_tx.clone(); - Thread::scoped(move|| { + thread::scoped(move|| { for _ in 0..M { let _s = TcpStream::connect(addr).unwrap(); } diff --git a/src/test/run-pass/tcp-connect-timeouts.rs b/src/test/run-pass/tcp-connect-timeouts.rs index a9a16cd72df..64f07a60b35 100644 --- a/src/test/run-pass/tcp-connect-timeouts.rs +++ b/src/test/run-pass/tcp-connect-timeouts.rs @@ -26,7 +26,7 @@ use std::old_io::test::*; use std::old_io; use std::time::Duration; use std::sync::mpsc::channel; -use std::thread::Thread; +use std::thread; #[cfg_attr(target_os = "freebsd", ignore)] fn eventual_timeout() { @@ -34,7 +34,7 @@ fn eventual_timeout() { let (tx1, rx1) = channel(); let (_tx2, rx2) = channel::<()>(); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { let _l = TcpListener::bind(addr).unwrap().listen(); tx1.send(()).unwrap(); let _ = rx2.recv(); diff --git a/src/test/run-pass/tcp-stress.rs b/src/test/run-pass/tcp-stress.rs index 489abf163c0..4209d5986ba 100644 --- a/src/test/run-pass/tcp-stress.rs +++ b/src/test/run-pass/tcp-stress.rs @@ -23,12 +23,12 @@ extern crate libc; use std::sync::mpsc::channel; use std::old_io::net::tcp::{TcpListener, TcpStream}; use std::old_io::{Acceptor, Listener, Reader, Writer}; -use std::thread::{Builder, Thread}; +use std::thread::{self, Builder}; use std::time::Duration; fn main() { // This test has a chance to time out, try to not let it time out - Thread::spawn(move|| -> () { + thread::spawn(move|| -> () { use std::old_io::timer; timer::sleep(Duration::milliseconds(30 * 1000)); println!("timed out!"); @@ -36,7 +36,7 @@ fn main() { }); let (tx, rx) = channel(); - Thread::spawn(move || -> () { + thread::spawn(move || -> () { let mut listener = TcpListener::bind("127.0.0.1:0").unwrap(); tx.send(listener.socket_name().unwrap()).unwrap(); let mut acceptor = listener.listen(); diff --git a/src/test/run-pass/tempfile.rs b/src/test/run-pass/tempfile.rs index 74290518364..49fac24d0b3 100644 --- a/src/test/run-pass/tempfile.rs +++ b/src/test/run-pass/tempfile.rs @@ -24,7 +24,7 @@ use std::old_path::{Path, GenericPath}; use std::old_io::fs::PathExtensions; use std::old_io::{fs, TempDir}; use std::old_io; -use std::os; +use std::env; use std::sync::mpsc::channel; use std::thread; @@ -129,7 +129,7 @@ fn test_rm_tempdir_close() { // to depend on std fn recursive_mkdir_rel() { let path = Path::new("frob"); - let cwd = os::getcwd().unwrap(); + let cwd = Path::new(env::current_dir().unwrap().to_str().unwrap()); println!("recursive_mkdir_rel: Making: {} in cwd {} [{}]", path.display(), cwd.display(), path.exists()); fs::mkdir_recursive(&path, old_io::USER_RWX); @@ -147,7 +147,7 @@ fn recursive_mkdir_dot() { fn recursive_mkdir_rel_2() { let path = Path::new("./frob/baz"); - let cwd = os::getcwd().unwrap(); + let cwd = Path::new(env::current_dir().unwrap().to_str().unwrap()); println!("recursive_mkdir_rel_2: Making: {} in cwd {} [{}]", path.display(), cwd.display(), path.exists()); fs::mkdir_recursive(&path, old_io::USER_RWX); @@ -196,7 +196,7 @@ pub fn dont_double_panic() { fn in_tmpdir(f: F) where F: FnOnce() { let tmpdir = TempDir::new("test").ok().expect("can't make tmpdir"); - assert!(os::change_dir(tmpdir.path()).is_ok()); + assert!(env::set_current_dir(tmpdir.path().as_str().unwrap()).is_ok()); f(); } diff --git a/src/test/run-pass/threads.rs b/src/test/run-pass/threads.rs index 4fc09952904..969a42a6f87 100644 --- a/src/test/run-pass/threads.rs +++ b/src/test/run-pass/threads.rs @@ -10,12 +10,12 @@ #![feature(std_misc)] -use std::thread::Thread; +use std::thread; pub fn main() { let mut i = 10; while i > 0 { - Thread::scoped({let i = i; move|| child(i)}); + thread::scoped({let i = i; move|| child(i)}); i = i - 1; } println!("main thread exiting"); diff --git a/src/test/run-pass/trait-bounds-in-arc.rs b/src/test/run-pass/trait-bounds-in-arc.rs index 2d97633771e..02ea7037056 100644 --- a/src/test/run-pass/trait-bounds-in-arc.rs +++ b/src/test/run-pass/trait-bounds-in-arc.rs @@ -19,7 +19,7 @@ use std::sync::Arc; use std::sync::mpsc::channel; -use std::thread::Thread; +use std::thread; trait Pet { fn name(&self, blk: Box); @@ -83,13 +83,13 @@ pub fn main() { box dogge2 as Box)); let (tx1, rx1) = channel(); let arc1 = arc.clone(); - let _t1 = Thread::spawn(move|| { check_legs(arc1); tx1.send(()); }); + let _t1 = thread::scoped(move|| { check_legs(arc1); tx1.send(()); }); let (tx2, rx2) = channel(); let arc2 = arc.clone(); - let _t2 = Thread::spawn(move|| { check_names(arc2); tx2.send(()); }); + let _t2 = thread::scoped(move|| { check_names(arc2); tx2.send(()); }); let (tx3, rx3) = channel(); let arc3 = arc.clone(); - let _t3 = Thread::spawn(move|| { check_pedigree(arc3); tx3.send(()); }); + let _t3 = thread::scoped(move|| { check_pedigree(arc3); tx3.send(()); }); rx1.recv(); rx2.recv(); rx3.recv(); diff --git a/src/test/run-pass/unit-like-struct-drop-run.rs b/src/test/run-pass/unit-like-struct-drop-run.rs index 9e1ced36402..c2db63ed251 100644 --- a/src/test/run-pass/unit-like-struct-drop-run.rs +++ b/src/test/run-pass/unit-like-struct-drop-run.rs @@ -14,7 +14,6 @@ #![feature(alloc)] -use std::boxed::BoxAny; use std::thread; struct Foo; diff --git a/src/test/run-pass/variadic-ffi.rs b/src/test/run-pass/variadic-ffi.rs index 1688482ca37..d81dc3afcd7 100644 --- a/src/test/run-pass/variadic-ffi.rs +++ b/src/test/run-pass/variadic-ffi.rs @@ -14,7 +14,7 @@ extern crate libc; -use std::ffi::{self, CString}; +use std::ffi::{CStr, CString}; use libc::{c_char, c_int}; @@ -25,7 +25,7 @@ extern { unsafe fn check(expected: &str, f: F) where F: FnOnce(*mut c_char) -> T { let mut x = [0 as c_char; 50]; f(&mut x[0] as *mut c_char); - assert_eq!(expected.as_bytes(), ffi::c_str_to_bytes(&x.as_ptr())); + assert_eq!(expected.as_bytes(), CStr::from_ptr(x.as_ptr()).to_bytes()); } pub fn main() {