diff options
| author | bors <bors@rust-lang.org> | 2015-01-07 05:31:23 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2015-01-07 05:31:23 +0000 |
| commit | 9e4e524e0eb17c8f463e731f23b544003e8709c6 (patch) | |
| tree | 916024d35e08f0826c20654f629ec596b5cb1f14 /src/libstd | |
| parent | ea6f65c5f1a3f84e010d2cef02a0160804e9567a (diff) | |
| parent | a64000820f0fc32be4d7535a9a92418a434fa4ba (diff) | |
| download | rust-9e4e524e0eb17c8f463e731f23b544003e8709c6.tar.gz rust-9e4e524e0eb17c8f463e731f23b544003e8709c6.zip | |
auto merge of #20677 : alexcrichton/rust/rollup, r=alexcrichton
Diffstat (limited to 'src/libstd')
73 files changed, 871 insertions, 1378 deletions
diff --git a/src/libstd/bitflags.rs b/src/libstd/bitflags.rs index ed3f2cbe1a1..5764962b51b 100644 --- a/src/libstd/bitflags.rs +++ b/src/libstd/bitflags.rs @@ -71,7 +71,7 @@ /// let mut flags = FLAG_A | FLAG_B; /// flags.clear(); /// assert!(flags.is_empty()); -/// assert_eq!(format!("{}", flags).as_slice(), "hi!"); +/// assert_eq!(format!("{:?}", flags).as_slice(), "hi!"); /// } /// ``` /// diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index a3fc38c34e8..2011c03c773 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -14,14 +14,14 @@ use self::Entry::*; use self::SearchResult::*; use self::VacantEntryState::*; -use borrow::{BorrowFrom, ToOwned}; +use borrow::BorrowFrom; use clone::Clone; use cmp::{max, Eq, PartialEq}; use default::Default; use fmt::{self, Show}; use hash::{Hash, Hasher, RandomSipHasher}; use iter::{self, Iterator, IteratorExt, FromIterator, Extend, Map}; -use kinds::Sized; +use marker::Sized; use mem::{self, replace}; use num::{Int, UnsignedInt}; use ops::{Deref, FnMut, Index, IndexMut}; @@ -292,7 +292,7 @@ fn test_resize_policy() { /// /// // Use derived implementation to print the status of the vikings. /// for (viking, health) in vikings.iter() { -/// println!("{} has {} hp", viking, health); +/// println!("{:?} has {} hp", viking, health); /// } /// ``` #[derive(Clone)] @@ -439,6 +439,7 @@ impl<K, V, M> SearchResult<K, V, M> { } } +#[old_impl_check] impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> { fn make_hash<X: ?Sized + Hash<S>>(&self, x: &X) -> SafeHash { table::make_hash(&self.hasher, x) @@ -517,6 +518,7 @@ impl<K: Hash + Eq, V> HashMap<K, V, RandomSipHasher> { } } +#[old_impl_check] impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> { /// Creates an empty hashmap which will use the given hasher to hash keys. /// @@ -920,16 +922,14 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> { } } - #[stable] /// Gets the given key's corresponding entry in the map for in-place manipulation. - /// Regardless of whether or not `to_owned()` has been called, the key must hash the same way. - pub fn entry<'a, Q: ?Sized>(&'a mut self, key: &'a Q) -> Entry<'a, Q, K, V> - where Q: Eq + Hash<S> + ToOwned<K> + #[unstable = "precise API still being fleshed out"] + pub fn entry<'a>(&'a mut self, key: K) -> Entry<'a, K, V> { // Gotta resize now. self.reserve(1); - let hash = self.make_hash(key); + let hash = self.make_hash(&key); search_entry_hashed(&mut self.table, hash, key) } @@ -1142,9 +1142,8 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> { } } -fn search_entry_hashed<'a, K, V, Q: ?Sized>(table: &'a mut RawTable<K,V>, hash: SafeHash, k: &'a Q) - -> Entry<'a, Q, K, V> - where Q: Eq + ToOwned<K> +fn search_entry_hashed<'a, K: Eq, V>(table: &'a mut RawTable<K,V>, hash: SafeHash, k: K) + -> Entry<'a, K, V> { // Worst case, we'll find one empty bucket among `size + 1` buckets. let size = table.size(); @@ -1167,7 +1166,7 @@ fn search_entry_hashed<'a, K, V, Q: ?Sized>(table: &'a mut RawTable<K,V>, hash: // hash matches? if bucket.hash() == hash { // key matches? - if *k == *BorrowFrom::borrow_from(bucket.read().0) { + if k == *bucket.read().0 { return Occupied(OccupiedEntry{ elem: bucket, }); @@ -1191,6 +1190,7 @@ fn search_entry_hashed<'a, K, V, Q: ?Sized>(table: &'a mut RawTable<K,V>, hash: } #[stable] +#[old_impl_check] impl<K: Eq + Hash<S>, V: PartialEq, S, H: Hasher<S>> PartialEq for HashMap<K, V, H> { fn eq(&self, other: &HashMap<K, V, H>) -> bool { if self.len() != other.len() { return false; } @@ -1202,16 +1202,18 @@ impl<K: Eq + Hash<S>, V: PartialEq, S, H: Hasher<S>> PartialEq for HashMap<K, V, } #[stable] +#[old_impl_check] impl<K: Eq + Hash<S>, V: Eq, S, H: Hasher<S>> Eq for HashMap<K, V, H> {} #[stable] +#[old_impl_check] impl<K: Eq + Hash<S> + Show, V: Show, S, H: Hasher<S>> Show for HashMap<K, V, H> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "{{")); + try!(write!(f, "HashMap {{")); for (i, (k, v)) in self.iter().enumerate() { if i != 0 { try!(write!(f, ", ")); } - try!(write!(f, "{}: {}", *k, *v)); + try!(write!(f, "{:?}: {:?}", *k, *v)); } write!(f, "}}") @@ -1219,6 +1221,7 @@ impl<K: Eq + Hash<S> + Show, V: Show, S, H: Hasher<S>> Show for HashMap<K, V, H> } #[stable] +#[old_impl_check] impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> Default for HashMap<K, V, H> { #[stable] fn default() -> HashMap<K, V, H> { @@ -1227,6 +1230,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> Default for HashMap<K, V, H> } #[stable] +#[old_impl_check] impl<K: Hash<S> + Eq, Q: ?Sized, V, S, H: Hasher<S>> Index<Q> for HashMap<K, V, H> where Q: BorrowFrom<K> + Hash<S> + Eq { @@ -1239,6 +1243,7 @@ impl<K: Hash<S> + Eq, Q: ?Sized, V, S, H: Hasher<S>> Index<Q> for HashMap<K, V, } #[stable] +#[old_impl_check] impl<K: Hash<S> + Eq, Q: ?Sized, V, S, H: Hasher<S>> IndexMut<Q> for HashMap<K, V, H> where Q: BorrowFrom<K> + Hash<S> + Eq { @@ -1323,27 +1328,27 @@ pub struct Drain<'a, K: 'a, V: 'a> { > } -#[stable] /// A view into a single occupied location in a HashMap +#[unstable = "precise API still being fleshed out"] pub struct OccupiedEntry<'a, K: 'a, V: 'a> { elem: FullBucket<K, V, &'a mut RawTable<K, V>>, } -#[stable] /// A view into a single empty location in a HashMap -pub struct VacantEntry<'a, Q: ?Sized + 'a, K: 'a, V: 'a> { +#[unstable = "precise API still being fleshed out"] +pub struct VacantEntry<'a, K: 'a, V: 'a> { hash: SafeHash, - key: &'a Q, + key: K, elem: VacantEntryState<K, V, &'a mut RawTable<K, V>>, } -#[stable] /// A view into a single location in a map, which may be vacant or occupied -pub enum Entry<'a, Q: ?Sized + 'a, K: 'a, V: 'a> { +#[unstable = "precise API still being fleshed out"] +pub enum Entry<'a, K: 'a, V: 'a> { /// An occupied Entry Occupied(OccupiedEntry<'a, K, V>), /// A vacant Entry - Vacant(VacantEntry<'a, Q, K, V>), + Vacant(VacantEntry<'a, K, V>), } /// Possible states of a VacantEntry @@ -1409,10 +1414,10 @@ impl<'a, K: 'a, V: 'a> Iterator for Drain<'a, K, V> { } } -impl<'a, Q: ?Sized, K, V> Entry<'a, Q, K, V> { - #[unstable = "matches collection reform v2 specification, waiting for dust to settle"] +#[unstable = "matches collection reform v2 specification, waiting for dust to settle"] +impl<'a, K, V> Entry<'a, K, V> { /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant - pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, Q, K, V>> { + pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, K, V>> { match self { Occupied(entry) => Ok(entry.into_mut()), Vacant(entry) => Err(entry), @@ -1420,27 +1425,24 @@ impl<'a, Q: ?Sized, K, V> Entry<'a, Q, K, V> { } } +#[unstable = "matches collection reform v2 specification, waiting for dust to settle"] impl<'a, K, V> OccupiedEntry<'a, K, V> { - #[stable] /// Gets a reference to the value in the entry pub fn get(&self) -> &V { self.elem.read().1 } - #[stable] /// Gets a mutable reference to the value in the entry pub fn get_mut(&mut self) -> &mut V { self.elem.read_mut().1 } - #[stable] /// Converts the OccupiedEntry into a mutable reference to the value in the entry /// with a lifetime bound to the map itself pub fn into_mut(self) -> &'a mut V { self.elem.into_mut_refs().1 } - #[stable] /// Sets the value of the entry, and returns the entry's old value pub fn insert(&mut self, mut value: V) -> V { let old_value = self.get_mut(); @@ -1448,30 +1450,30 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> { value } - #[stable] /// Takes the value out of the entry, and returns it pub fn remove(self) -> V { pop_internal(self.elem).1 } } -impl<'a, Q: ?Sized + 'a + ToOwned<K>, K: 'a, V: 'a> VacantEntry<'a, Q, K, V> { - #[stable] +#[unstable = "matches collection reform v2 specification, waiting for dust to settle"] +impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { /// Sets the value of the entry with the VacantEntry's key, /// and returns a mutable reference to it pub fn insert(self, value: V) -> &'a mut V { match self.elem { NeqElem(bucket, ib) => { - robin_hood(bucket, ib, self.hash, self.key.to_owned(), value) + robin_hood(bucket, ib, self.hash, self.key, value) } NoElem(bucket) => { - bucket.put(self.hash, self.key.to_owned(), value).into_mut_refs().1 + bucket.put(self.hash, self.key, value).into_mut_refs().1 } } } } #[stable] +#[old_impl_check] impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> FromIterator<(K, V)> for HashMap<K, V, H> { fn from_iter<T: Iterator<Item=(K, V)>>(iter: T) -> HashMap<K, V, H> { let lower = iter.size_hint().0; @@ -1482,6 +1484,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> FromIterator<(K, V)> for Has } #[stable] +#[old_impl_check] impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> Extend<(K, V)> for HashMap<K, V, H> { fn extend<T: Iterator<Item=(K, V)>>(&mut self, mut iter: T) { for (k, v) in iter { @@ -1497,8 +1500,6 @@ mod test_map { use super::HashMap; use super::Entry::{Occupied, Vacant}; use iter::{range_inclusive, range_step_inclusive, repeat}; - use borrow::ToOwned; - use hash; use cell::RefCell; use rand::{weak_rng, Rng}; @@ -1891,10 +1892,11 @@ mod test_map { map.insert(1i, 2i); map.insert(3i, 4i); - let map_str = format!("{}", map); + let map_str = format!("{:?}", map); - assert!(map_str == "{1: 2, 3: 4}" || map_str == "{3: 4, 1: 2}"); - assert_eq!(format!("{}", empty), "{}"); + assert!(map_str == "HashMap {1i: 2i, 3i: 4i}" || + map_str == "HashMap {3i: 4i, 1i: 2i}"); + assert_eq!(format!("{:?}", empty), "HashMap {}"); } #[test] @@ -2092,7 +2094,7 @@ mod test_map { let mut map: HashMap<int, int> = xs.iter().map(|&x| x).collect(); // Existing key (insert) - match map.entry(&1) { + match map.entry(1) { Vacant(_) => unreachable!(), Occupied(mut view) => { assert_eq!(view.get(), &10); @@ -2104,7 +2106,7 @@ mod test_map { // Existing key (update) - match map.entry(&2) { + match map.entry(2) { Vacant(_) => unreachable!(), Occupied(mut view) => { let v = view.get_mut(); @@ -2116,7 +2118,7 @@ mod test_map { assert_eq!(map.len(), 6); // Existing key (take) - match map.entry(&3) { + match map.entry(3) { Vacant(_) => unreachable!(), Occupied(view) => { assert_eq!(view.remove(), 30); @@ -2127,7 +2129,7 @@ mod test_map { // Inexistent key (insert) - match map.entry(&10) { + match map.entry(10) { Occupied(_) => unreachable!(), Vacant(view) => { assert_eq!(*view.insert(1000), 1000); @@ -2158,7 +2160,7 @@ mod test_map { for i in range(0u, 1000) { let x = rng.gen_range(-10, 10); - match m.entry(&x) { + match m.entry(x) { Vacant(_) => {}, Occupied(e) => { println!("{}: remove {}", i, x); diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 211bfe2c10e..f66e5384942 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -13,7 +13,7 @@ use borrow::BorrowFrom; use clone::Clone; use cmp::{Eq, PartialEq}; -use core::kinds::Sized; +use core::marker::Sized; use default::Default; use fmt::Show; use fmt; @@ -22,9 +22,6 @@ use iter::{Iterator, IteratorExt, FromIterator, Map, Chain, Extend}; use ops::{BitOr, BitAnd, BitXor, Sub}; use option::Option::{Some, None, self}; -// NOTE: for old macros; remove after the next snapshot -#[cfg(stage0)] use result::Result::{Ok, Err}; - use super::map::{self, HashMap, Keys, INITIAL_CAPACITY}; // Future Optimization (FIXME!) @@ -88,7 +85,7 @@ use super::map::{self, HashMap, Keys, INITIAL_CAPACITY}; /// /// // Use derived implementation to print the vikings. /// for x in vikings.iter() { -/// println!("{}", x); +/// println!("{:?}", x); /// } /// ``` #[derive(Clone)] @@ -128,6 +125,7 @@ impl<T: Hash + Eq> HashSet<T, RandomSipHasher> { } } +#[old_impl_check] impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> { /// Creates a new empty hash set which will use the given hasher to hash /// keys. @@ -571,6 +569,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> { } #[stable] +#[old_impl_check] impl<T: Eq + Hash<S>, S, H: Hasher<S>> PartialEq for HashSet<T, H> { fn eq(&self, other: &HashSet<T, H>) -> bool { if self.len() != other.len() { return false; } @@ -580,16 +579,18 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> PartialEq for HashSet<T, H> { } #[stable] +#[old_impl_check] impl<T: Eq + Hash<S>, S, H: Hasher<S>> Eq for HashSet<T, H> {} #[stable] +#[old_impl_check] impl<T: Eq + Hash<S> + fmt::Show, S, H: Hasher<S>> fmt::Show for HashSet<T, H> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "{{")); + try!(write!(f, "HashSet {{")); for (i, x) in self.iter().enumerate() { if i != 0 { try!(write!(f, ", ")); } - try!(write!(f, "{}", *x)); + try!(write!(f, "{:?}", *x)); } write!(f, "}}") @@ -597,6 +598,7 @@ impl<T: Eq + Hash<S> + fmt::Show, S, H: Hasher<S>> fmt::Show for HashSet<T, H> { } #[stable] +#[old_impl_check] impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> FromIterator<T> for HashSet<T, H> { fn from_iter<I: Iterator<Item=T>>(iter: I) -> HashSet<T, H> { let lower = iter.size_hint().0; @@ -607,6 +609,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> FromIterator<T> for HashSet<T, } #[stable] +#[old_impl_check] impl<T: Eq + Hash<S>, S, H: Hasher<S>> Extend<T> for HashSet<T, H> { fn extend<I: Iterator<Item=T>>(&mut self, mut iter: I) { for k in iter { @@ -616,6 +619,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> Extend<T> for HashSet<T, H> { } #[stable] +#[old_impl_check] impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Default for HashSet<T, H> { #[stable] fn default() -> HashSet<T, H> { @@ -624,6 +628,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Default for HashSet<T, H> { } #[stable] +#[old_impl_check] impl<'a, 'b, T: Eq + Hash<S> + Clone, S, H: Hasher<S> + Default> BitOr<&'b HashSet<T, H>> for &'a HashSet<T, H> { type Output = HashSet<T, H>; @@ -654,6 +659,7 @@ BitOr<&'b HashSet<T, H>> for &'a HashSet<T, H> { } #[stable] +#[old_impl_check] impl<'a, 'b, T: Eq + Hash<S> + Clone, S, H: Hasher<S> + Default> BitAnd<&'b HashSet<T, H>> for &'a HashSet<T, H> { type Output = HashSet<T, H>; @@ -684,6 +690,7 @@ BitAnd<&'b HashSet<T, H>> for &'a HashSet<T, H> { } #[stable] +#[old_impl_check] impl<'a, 'b, T: Eq + Hash<S> + Clone, S, H: Hasher<S> + Default> BitXor<&'b HashSet<T, H>> for &'a HashSet<T, H> { type Output = HashSet<T, H>; @@ -714,6 +721,7 @@ BitXor<&'b HashSet<T, H>> for &'a HashSet<T, H> { } #[stable] +#[old_impl_check] impl<'a, 'b, T: Eq + Hash<S> + Clone, S, H: Hasher<S> + Default> Sub<&'b HashSet<T, H>> for &'a HashSet<T, H> { type Output = HashSet<T, H>; @@ -816,6 +824,7 @@ impl<'a, K: 'a> Iterator for Drain<'a, K> { } #[stable] +#[old_impl_check] impl<'a, T, S, H> Iterator for Intersection<'a, T, H> where T: Eq + Hash<S>, H: Hasher<S> { @@ -839,6 +848,7 @@ impl<'a, T, S, H> Iterator for Intersection<'a, T, H> } #[stable] +#[old_impl_check] impl<'a, T, S, H> Iterator for Difference<'a, T, H> where T: Eq + Hash<S>, H: Hasher<S> { @@ -862,6 +872,7 @@ impl<'a, T, S, H> Iterator for Difference<'a, T, H> } #[stable] +#[old_impl_check] impl<'a, T, S, H> Iterator for SymmetricDifference<'a, T, H> where T: Eq + Hash<S>, H: Hasher<S> { @@ -872,6 +883,7 @@ impl<'a, T, S, H> Iterator for SymmetricDifference<'a, T, H> } #[stable] +#[old_impl_check] impl<'a, T, S, H> Iterator for Union<'a, T, H> where T: Eq + Hash<S>, H: Hasher<S> { @@ -1116,10 +1128,10 @@ mod test_set { set.insert(1i); set.insert(2); - let set_str = format!("{}", set); + let set_str = format!("{:?}", set); - assert!(set_str == "{1, 2}" || set_str == "{2, 1}"); - assert_eq!(format!("{}", empty), "{}"); + assert!(set_str == "HashSet {1i, 2i}" || set_str == "HashSet {2i, 1i}"); + assert_eq!(format!("{:?}", empty), "HashSet {}"); } #[test] diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index 1eb4408eedc..6eb98da4da4 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -16,7 +16,7 @@ use clone::Clone; use cmp; use hash::{Hash, Hasher}; use iter::{Iterator, count}; -use kinds::{Copy, Sized, marker}; +use marker::{Copy, Sized, self}; use mem::{min_align_of, size_of}; use mem; use num::{Int, UnsignedInt}; diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs index ef9d28bbbb2..9b2a4926bcb 100644 --- a/src/libstd/collections/mod.rs +++ b/src/libstd/collections/mod.rs @@ -255,7 +255,7 @@ //! let message = "she sells sea shells by the sea shore"; //! //! for c in message.chars() { -//! match count.entry(&c) { +//! match count.entry(c) { //! Vacant(entry) => { entry.insert(1u); }, //! Occupied(mut entry) => *entry.get_mut() += 1, //! } @@ -290,7 +290,7 @@ //! for id in orders.into_iter() { //! // If this is the first time we've seen this customer, initialize them //! // with no blood alcohol. Otherwise, just retrieve them. -//! let person = match blood_alcohol.entry(&id) { +//! let person = match blood_alcohol.entry(id) { //! Vacant(entry) => entry.insert(Person{id: id, blood_alcohol: 0.0}), //! Occupied(entry) => entry.into_mut(), //! }; diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 32e1922ae74..9963e4861b7 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -78,12 +78,15 @@ //! } //! ``` +#![stable] + use prelude::v1::*; use str::Utf8Error; use string::{FromUtf8Error, FromUtf16Error}; /// Base functionality for all errors in Rust. +#[unstable = "the exact API of this trait may change"] pub trait Error: Send { /// A short description of the error; usually a static string. fn description(&self) -> &str; @@ -96,18 +99,21 @@ pub trait Error: Send { } /// A trait for types that can be converted from a given error type `E`. +#[stable] pub trait FromError<E> { /// Perform the conversion. fn from_error(err: E) -> Self; } // Any type is convertable from itself +#[stable] impl<E> FromError<E> for E { fn from_error(err: E) -> E { err } } +#[stable] impl Error for Utf8Error { fn description(&self) -> &str { match *self { @@ -119,11 +125,13 @@ impl Error for Utf8Error { fn detail(&self) -> Option<String> { Some(self.to_string()) } } +#[stable] impl Error for FromUtf8Error { fn description(&self) -> &str { "invalid utf-8" } fn detail(&self) -> Option<String> { Some(self.to_string()) } } +#[stable] impl Error for FromUtf16Error { fn description(&self) -> &str { "invalid utf-16" } } diff --git a/src/libstd/failure.rs b/src/libstd/failure.rs index e48137047b0..50538d3e43d 100644 --- a/src/libstd/failure.rs +++ b/src/libstd/failure.rs @@ -37,7 +37,7 @@ pub fn on_fail(obj: &(Any+Send), file: &'static str, line: uint) { let msg = match obj.downcast_ref::<&'static str>() { Some(s) => *s, None => match obj.downcast_ref::<String>() { - Some(s) => s[], + Some(s) => s.index(&FullRange), None => "Box<Any>", } }; diff --git a/src/libstd/fmt.rs b/src/libstd/fmt.rs index 32f5f2d4536..14b80045a9a 100644 --- a/src/libstd/fmt.rs +++ b/src/libstd/fmt.rs @@ -31,7 +31,7 @@ //! format!("Hello"); // => "Hello" //! format!("Hello, {}!", "world"); // => "Hello, world!" //! format!("The number is {}", 1i); // => "The number is 1" -//! format!("{}", (3i, 4i)); // => "(3, 4)" +//! format!("{:?}", (3i, 4i)); // => "(3i, 4i)" //! format!("{value}", value=4i); // => "4" //! format!("{} {}", 1i, 2u); // => "1 2" //! # } @@ -87,7 +87,7 @@ //! # fn main() { //! format!("{argument}", argument = "test"); // => "test" //! format!("{name} {}", 1i, name = 2i); // => "2 1" -//! format!("{a} {c} {b}", a="a", b=(), c=3i); // => "a 3 ()" +//! format!("{a} {c} {b}", a="a", b='b', c=3i); // => "a 3 b" //! # } //! ``` //! @@ -127,7 +127,8 @@ //! This allows multiple actual types to be formatted via `{:x}` (like `i8` as //! well as `int`). The current mapping of types to traits is: //! -//! * *nothing* ⇒ `Show` +//! * *nothing* ⇒ `String` +//! * `?` ⇒ `Show` //! * `o` ⇒ `Octal` //! * `x` ⇒ `LowerHex` //! * `X` ⇒ `UpperHex` @@ -140,8 +141,7 @@ //! `std::fmt::Binary` trait can then be formatted with `{:b}`. Implementations //! are provided for these traits for a number of primitive types by the //! standard library as well. If no format is specified (as in `{}` or `{:6}`), -//! then the format trait used is the `Show` trait. This is one of the more -//! commonly implemented traits when formatting a custom type. +//! then the format trait used is the `String` trait. //! //! When implementing a format trait for your own type, you will have to //! implement a method of the signature: @@ -175,12 +175,13 @@ //! use std::f64; //! use std::num::Float; //! +//! #[deriving(Show)] //! struct Vector2D { //! x: int, //! y: int, //! } //! -//! impl fmt::Show for Vector2D { +//! impl fmt::String for Vector2D { //! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { //! // The `f` value implements the `Writer` trait, which is what the //! // write! macro is expecting. Note that this formatting ignores the @@ -209,10 +210,31 @@ //! let myvector = Vector2D { x: 3, y: 4 }; //! //! println!("{}", myvector); // => "(3, 4)" +//! println!("{:?}", myvector); // => "Vector2D {x: 3i, y:4i}" //! println!("{:10.3b}", myvector); // => " 5.000" //! } //! ``` //! +//! #### fmt::String vs fmt::Show +//! +//! These two formatting traits have distinct purposes: +//! +//! - `fmt::String` implementations assert that the type can be faithfully +//! represented as a UTF-8 string at all times. It is **not** expected that +//! all types implement the `String` trait. +//! - `fmt::Show` implementations should be implemented for **all** public types. +//! Output will typically represent the internal state as faithfully as possible. +//! The purpose of the `Show` trait is to facilitate debugging Rust code. In +//! most cases, using `#[deriving(Show)]` is sufficient and recommended. +//! +//! Some examples of the output from both traits: +//! +//! ``` +//! assert_eq!(format!("{} {:?}", 3i32, 4i32), "3 4i32"); +//! assert_eq!(format!("{} {:?}", 'a', 'b'), "a 'b'"); +//! assert_eq!(format!("{} {:?}", "foo\n", "bar\n"), "foo\n \"bar\\n\""); +//! ``` +//! //! ### Related macros //! //! There are a number of related macros in the `format!` family. The ones that @@ -393,7 +415,7 @@ use string; pub use core::fmt::{Formatter, Result, Writer, rt}; -pub use core::fmt::{Show, Octal, Binary}; +pub use core::fmt::{Show, String, Octal, Binary}; pub use core::fmt::{LowerHex, UpperHex, Pointer}; pub use core::fmt::{LowerExp, UpperExp}; pub use core::fmt::Error; diff --git a/src/libstd/hash.rs b/src/libstd/hash.rs index ac2b01e995e..69e7e429d07 100644 --- a/src/libstd/hash.rs +++ b/src/libstd/hash.rs @@ -63,7 +63,7 @@ pub use core::hash::{Hash, Hasher, Writer, hash, sip}; -use core::kinds::Sized; +use core::marker::Sized; use default::Default; use rand::Rng; use rand; diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index d590aa84194..74c503e6f2b 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -15,7 +15,7 @@ use cmp; use io::{Reader, Writer, Stream, Buffer, DEFAULT_BUF_SIZE, IoResult}; use iter::{IteratorExt, ExactSizeIterator}; -use ops::Drop; +use ops::{Drop, Index}; use option::Option; use option::Option::{Some, None}; use result::Result::Ok; @@ -23,9 +23,6 @@ use slice::{SliceExt}; use slice; use vec::Vec; -// NOTE: for old macros; remove after the next snapshot -#[cfg(stage0)] use result::Result::Err; - /// Wraps a Reader and buffers input from it /// /// It can be excessively inefficient to work directly with a `Reader`. For @@ -100,7 +97,7 @@ impl<R: Reader> Buffer for BufferedReader<R> { self.cap = try!(self.inner.read(self.buf.as_mut_slice())); self.pos = 0; } - Ok(self.buf[self.pos..self.cap]) + Ok(self.buf.index(&(self.pos..self.cap))) } fn consume(&mut self, amt: uint) { @@ -117,7 +114,7 @@ impl<R: Reader> Reader for BufferedReader<R> { let nread = { let available = try!(self.fill_buf()); let nread = cmp::min(available.len(), buf.len()); - slice::bytes::copy_memory(buf, available[..nread]); + slice::bytes::copy_memory(buf, available.index(&(0..nread))); nread }; self.pos += nread; @@ -171,7 +168,7 @@ impl<W: Writer> BufferedWriter<W> { fn flush_buf(&mut self) -> IoResult<()> { if self.pos != 0 { - let ret = self.inner.as_mut().unwrap().write(self.buf[..self.pos]); + let ret = self.inner.as_mut().unwrap().write(self.buf.index(&(0..self.pos))); self.pos = 0; ret } else { @@ -263,9 +260,9 @@ impl<W: Writer> Writer for LineBufferedWriter<W> { fn write(&mut self, buf: &[u8]) -> IoResult<()> { match buf.iter().rposition(|&b| b == b'\n') { Some(i) => { - try!(self.inner.write(buf[..i + 1])); + try!(self.inner.write(buf.index(&(0..(i + 1))))); try!(self.inner.flush()); - try!(self.inner.write(buf[i + 1..])); + try!(self.inner.write(buf.index(&((i + 1)..)))); Ok(()) } None => self.inner.write(buf), @@ -472,41 +469,37 @@ mod test { writer.write(&[0, 1]).unwrap(); let b: &[_] = &[]; - assert_eq!(writer.get_ref()[], b); + assert_eq!(&writer.get_ref()[], b); writer.write(&[2]).unwrap(); let b: &[_] = &[0, 1]; - assert_eq!(writer.get_ref()[], b); + assert_eq!(&writer.get_ref()[], b); writer.write(&[3]).unwrap(); - assert_eq!(writer.get_ref()[], b); + assert_eq!(&writer.get_ref()[], b); writer.flush().unwrap(); let a: &[_] = &[0, 1, 2, 3]; - assert_eq!(a, writer.get_ref()[]); + assert_eq!(a, &writer.get_ref()[]); writer.write(&[4]).unwrap(); writer.write(&[5]).unwrap(); - assert_eq!(a, writer.get_ref()[]); + assert_eq!(a, &writer.get_ref()[]); writer.write(&[6]).unwrap(); let a: &[_] = &[0, 1, 2, 3, 4, 5]; - assert_eq!(a, - writer.get_ref()[]); + assert_eq!(a, &writer.get_ref()[]); writer.write(&[7, 8]).unwrap(); let a: &[_] = &[0, 1, 2, 3, 4, 5, 6]; - assert_eq!(a, - writer.get_ref()[]); + assert_eq!(a, &writer.get_ref()[]); writer.write(&[9, 10, 11]).unwrap(); let a: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; - assert_eq!(a, - writer.get_ref()[]); + assert_eq!(a, &writer.get_ref()[]); writer.flush().unwrap(); - assert_eq!(a, - writer.get_ref()[]); + assert_eq!(a, &writer.get_ref()[]); } #[test] @@ -514,10 +507,10 @@ mod test { let mut w = BufferedWriter::with_capacity(3, Vec::new()); w.write(&[0, 1]).unwrap(); let a: &[_] = &[]; - assert_eq!(a, w.get_ref()[]); + assert_eq!(a, &w.get_ref()[]); let w = w.into_inner(); let a: &[_] = &[0, 1]; - assert_eq!(a, w[]); + assert_eq!(a, w.index(&FullRange)); } // This is just here to make sure that we don't infinite loop in the @@ -559,21 +552,21 @@ mod test { let mut writer = LineBufferedWriter::new(Vec::new()); writer.write(&[0]).unwrap(); let b: &[_] = &[]; - assert_eq!(writer.get_ref()[], b); + assert_eq!(&writer.get_ref()[], b); writer.write(&[1]).unwrap(); - assert_eq!(writer.get_ref()[], b); + assert_eq!(&writer.get_ref()[], b); writer.flush().unwrap(); let b: &[_] = &[0, 1]; - assert_eq!(writer.get_ref()[], b); + assert_eq!(&writer.get_ref()[], b); writer.write(&[0, b'\n', 1, b'\n', 2]).unwrap(); let b: &[_] = &[0, 1, 0, b'\n', 1, b'\n']; - assert_eq!(writer.get_ref()[], b); + assert_eq!(&writer.get_ref()[], b); writer.flush().unwrap(); let b: &[_] = &[0, 1, 0, b'\n', 1, b'\n', 2]; - assert_eq!(writer.get_ref()[], b); + assert_eq!(&writer.get_ref()[], b); writer.write(&[3, b'\n']).unwrap(); let b: &[_] = &[0, 1, 0, b'\n', 1, b'\n', 2, 3, b'\n']; - assert_eq!(writer.get_ref()[], b); + assert_eq!(&writer.get_ref()[], b); } #[test] @@ -614,14 +607,14 @@ mod test { #[test] fn read_char_buffered() { let buf = [195u8, 159u8]; - let mut reader = BufferedReader::with_capacity(1, buf[]); + let mut reader = BufferedReader::with_capacity(1, buf.index(&FullRange)); assert_eq!(reader.read_char(), Ok('ß')); } #[test] fn test_chars() { let buf = [195u8, 159u8, b'a']; - let mut reader = BufferedReader::with_capacity(1, buf[]); + let mut reader = BufferedReader::with_capacity(1, buf.index(&FullRange)); let mut it = reader.chars(); assert_eq!(it.next(), Some(Ok('ß'))); assert_eq!(it.next(), Some(Ok('a'))); diff --git a/src/libstd/io/comm_adapters.rs b/src/libstd/io/comm_adapters.rs index f47f6237b72..bce097e17ef 100644 --- a/src/libstd/io/comm_adapters.rs +++ b/src/libstd/io/comm_adapters.rs @@ -13,6 +13,7 @@ use cmp; use sync::mpsc::{Sender, Receiver}; use io; use option::Option::{None, Some}; +use ops::Index; use result::Result::{Ok, Err}; use slice::{bytes, SliceExt}; use super::{Buffer, Reader, Writer, IoResult}; @@ -90,7 +91,7 @@ impl Reader for ChanReader { Some(src) => { let dst = buf.slice_from_mut(num_read); let count = cmp::min(src.len(), dst.len()); - bytes::copy_memory(dst, src[..count]); + bytes::copy_memory(dst, src.index(&(0..count))); count }, None => 0, @@ -172,7 +173,7 @@ mod test { tx.send(vec![3u8, 4u8]).unwrap(); tx.send(vec![5u8, 6u8]).unwrap(); tx.send(vec![7u8, 8u8]).unwrap(); - }).detach(); + }); let mut reader = ChanReader::new(rx); let mut buf = [0u8; 3]; @@ -215,7 +216,7 @@ mod test { tx.send(b"rld\nhow ".to_vec()).unwrap(); tx.send(b"are you?".to_vec()).unwrap(); tx.send(b"".to_vec()).unwrap(); - }).detach(); + }); let mut reader = ChanReader::new(rx); @@ -234,7 +235,7 @@ mod test { writer.write_be_u32(42).unwrap(); let wanted = vec![0u8, 0u8, 0u8, 42u8]; - let got = match Thread::spawn(move|| { rx.recv().unwrap() }).join() { + let got = match Thread::scoped(move|| { rx.recv().unwrap() }).join() { Ok(got) => got, Err(_) => panic!(), }; diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs index 4691c06c1de..eadca8e42e5 100644 --- a/src/libstd/io/fs.rs +++ b/src/libstd/io/fs.rs @@ -156,7 +156,7 @@ impl File { }) } }).update_err("couldn't open path as file", |e| { - format!("{}; path={}; mode={}; access={}", e, path.display(), + format!("{}; path={:?}; mode={}; access={}", e, path.display(), mode_string(mode), access_string(access)) }) } @@ -211,7 +211,7 @@ impl File { pub fn fsync(&mut self) -> IoResult<()> { self.fd.fsync() .update_err("couldn't fsync file", - |e| format!("{}; path={}", e, self.path.display())) + |e| format!("{}; path={:?}", e, self.path.display())) } /// This function is similar to `fsync`, except that it may not synchronize @@ -221,7 +221,7 @@ impl File { pub fn datasync(&mut self) -> IoResult<()> { self.fd.datasync() .update_err("couldn't datasync file", - |e| format!("{}; path={}", e, self.path.display())) + |e| format!("{}; path={:?}", e, self.path.display())) } /// Either truncates or extends the underlying file, updating the size of @@ -235,7 +235,7 @@ impl File { pub fn truncate(&mut self, size: i64) -> IoResult<()> { self.fd.truncate(size) .update_err("couldn't truncate file", |e| - format!("{}; path={}; size={}", e, self.path.display(), size)) + format!("{}; path={:?}; size={:?}", e, self.path.display(), size)) } /// Returns true if the stream has reached the end of the file. @@ -255,7 +255,7 @@ impl File { pub fn stat(&self) -> IoResult<FileStat> { self.fd.fstat() .update_err("couldn't fstat file", |e| - format!("{}; path={}", e, self.path.display())) + format!("{}; path={:?}", e, self.path.display())) } } @@ -283,7 +283,7 @@ impl File { pub fn unlink(path: &Path) -> IoResult<()> { fs_imp::unlink(path) .update_err("couldn't unlink path", |e| - format!("{}; path={}", e, path.display())) + format!("{}; path={:?}", e, path.display())) } /// Given a path, query the file system to get information about a file, @@ -310,7 +310,7 @@ pub fn unlink(path: &Path) -> IoResult<()> { pub fn stat(path: &Path) -> IoResult<FileStat> { fs_imp::stat(path) .update_err("couldn't stat path", |e| - format!("{}; path={}", e, path.display())) + format!("{}; path={:?}", e, path.display())) } /// Perform the same operation as the `stat` function, except that this @@ -324,7 +324,7 @@ pub fn stat(path: &Path) -> IoResult<FileStat> { pub fn lstat(path: &Path) -> IoResult<FileStat> { fs_imp::lstat(path) .update_err("couldn't lstat path", |e| - format!("{}; path={}", e, path.display())) + format!("{}; path={:?}", e, path.display())) } /// Rename a file or directory to a new name. @@ -346,7 +346,7 @@ pub fn lstat(path: &Path) -> IoResult<FileStat> { pub fn rename(from: &Path, to: &Path) -> IoResult<()> { fs_imp::rename(from, to) .update_err("couldn't rename path", |e| - format!("{}; from={}; to={}", e, from.display(), to.display())) + format!("{}; from={:?}; to={:?}", e, from.display(), to.display())) } /// Copies the contents of one file to another. This function will also @@ -380,7 +380,7 @@ pub fn rename(from: &Path, to: &Path) -> IoResult<()> { pub fn copy(from: &Path, to: &Path) -> IoResult<()> { fn update_err<T>(result: IoResult<T>, from: &Path, to: &Path) -> IoResult<T> { result.update_err("couldn't copy path", |e| { - format!("{}; from={}; to={}", e, from.display(), to.display()) + format!("{}; from={:?}; to={:?}", e, from.display(), to.display()) }) } @@ -424,14 +424,14 @@ pub fn copy(from: &Path, to: &Path) -> IoResult<()> { pub fn chmod(path: &Path, mode: io::FilePermission) -> IoResult<()> { fs_imp::chmod(path, mode.bits() as uint) .update_err("couldn't chmod path", |e| - format!("{}; path={}; mode={}", e, path.display(), mode)) + format!("{}; path={:?}; mode={:?}", e, path.display(), mode)) } /// Change the user and group owners of a file at the specified path. pub fn chown(path: &Path, uid: int, gid: int) -> IoResult<()> { fs_imp::chown(path, uid, gid) .update_err("couldn't chown path", |e| - format!("{}; path={}; uid={}; gid={}", e, path.display(), uid, gid)) + format!("{}; path={:?}; uid={}; gid={}", e, path.display(), uid, gid)) } /// Creates a new hard link on the filesystem. The `dst` path will be a @@ -440,7 +440,7 @@ pub fn chown(path: &Path, uid: int, gid: int) -> IoResult<()> { pub fn link(src: &Path, dst: &Path) -> IoResult<()> { fs_imp::link(src, dst) .update_err("couldn't link path", |e| - format!("{}; src={}; dest={}", e, src.display(), dst.display())) + format!("{}; src={:?}; dest={:?}", e, src.display(), dst.display())) } /// Creates a new symbolic link on the filesystem. The `dst` path will be a @@ -448,7 +448,7 @@ pub fn link(src: &Path, dst: &Path) -> IoResult<()> { pub fn symlink(src: &Path, dst: &Path) -> IoResult<()> { fs_imp::symlink(src, dst) .update_err("couldn't symlink path", |e| - format!("{}; src={}; dest={}", e, src.display(), dst.display())) + format!("{}; src={:?}; dest={:?}", e, src.display(), dst.display())) } /// Reads a symlink, returning the file that the symlink points to. @@ -460,7 +460,7 @@ pub fn symlink(src: &Path, dst: &Path) -> IoResult<()> { pub fn readlink(path: &Path) -> IoResult<Path> { fs_imp::readlink(path) .update_err("couldn't resolve symlink for path", |e| - format!("{}; path={}", e, path.display())) + format!("{}; path={:?}", e, path.display())) } /// Create a new, empty directory at the provided path @@ -483,7 +483,7 @@ pub fn readlink(path: &Path) -> IoResult<Path> { pub fn mkdir(path: &Path, mode: FilePermission) -> IoResult<()> { fs_imp::mkdir(path, mode.bits() as uint) .update_err("couldn't create directory", |e| - format!("{}; path={}; mode={}", e, path.display(), mode)) + format!("{}; path={:?}; mode={:?}", e, path.display(), mode)) } /// Remove an existing, empty directory @@ -505,7 +505,7 @@ pub fn mkdir(path: &Path, mode: FilePermission) -> IoResult<()> { pub fn rmdir(path: &Path) -> IoResult<()> { fs_imp::rmdir(path) .update_err("couldn't remove directory", |e| - format!("{}; path={}", e, path.display())) + format!("{}; path={:?}", e, path.display())) } /// Retrieve a vector containing all entries within a provided directory @@ -545,7 +545,7 @@ pub fn rmdir(path: &Path) -> IoResult<()> { pub fn readdir(path: &Path) -> IoResult<Vec<Path>> { fs_imp::readdir(path) .update_err("couldn't read directory", - |e| format!("{}; path={}", e, path.display())) + |e| format!("{}; path={:?}", e, path.display())) } /// Returns an iterator that will recursively walk the directory structure @@ -555,7 +555,7 @@ pub fn readdir(path: &Path) -> IoResult<Vec<Path>> { pub fn walk_dir(path: &Path) -> IoResult<Directories> { Ok(Directories { stack: try!(readdir(path).update_err("couldn't walk directory", - |e| format!("{}; path={}", e, path.display()))) + |e| format!("{}; path={:?}", e, path.display()))) }) } @@ -605,7 +605,7 @@ pub fn mkdir_recursive(path: &Path, mode: FilePermission) -> IoResult<()> { let result = mkdir(&curpath, mode) .update_err("couldn't recursively mkdir", - |e| format!("{}; path={}", e, path.display())); + |e| format!("{}; path={:?}", e, path.display())); match result { Err(mkdir_err) => { @@ -632,7 +632,7 @@ pub fn rmdir_recursive(path: &Path) -> IoResult<()> { rm_stack.push(path.clone()); fn rmdir_failed(err: &IoError, path: &Path) -> String { - format!("rmdir_recursive failed; path={}; cause={}", + format!("rmdir_recursive failed; path={:?}; cause={}", path.display(), err) } @@ -692,14 +692,14 @@ pub fn rmdir_recursive(path: &Path) -> IoResult<()> { pub fn change_file_times(path: &Path, atime: u64, mtime: u64) -> IoResult<()> { fs_imp::utime(path, atime, mtime) .update_err("couldn't change_file_times", |e| - format!("{}; path={}", e, path.display())) + format!("{}; path={:?}", e, path.display())) } impl Reader for File { fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { fn update_err<T>(result: IoResult<T>, file: &File) -> IoResult<T> { result.update_err("couldn't read file", - |e| format!("{}; path={}", + |e| format!("{}; path={:?}", e, file.path.display())) } @@ -722,7 +722,7 @@ impl Writer for File { fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.fd.write(buf) .update_err("couldn't write to file", - |e| format!("{}; path={}", e, self.path.display())) + |e| format!("{}; path={:?}", e, self.path.display())) } } @@ -730,7 +730,7 @@ impl Seek for File { fn tell(&self) -> IoResult<u64> { self.fd.tell() .update_err("couldn't retrieve file cursor (`tell`)", - |e| format!("{}; path={}", e, self.path.display())) + |e| format!("{}; path={:?}", e, self.path.display())) } fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> { @@ -743,7 +743,7 @@ impl Seek for File { Err(e) => Err(e), }; err.update_err("couldn't seek in file", - |e| format!("{}; path={}", e, self.path.display())) + |e| format!("{}; path={:?}", e, self.path.display())) } } @@ -832,13 +832,13 @@ mod test { macro_rules! check { ($e:expr) => ( match $e { Ok(t) => t, - Err(e) => panic!("{} failed with: {}", stringify!($e), e), + Err(e) => panic!("{} failed with: {:?}", stringify!($e), e), } ) } macro_rules! error { ($e:expr, $s:expr) => ( match $e { - Ok(_) => panic!("Unexpected success. Should've been: {}", $s), + Ok(_) => panic!("Unexpected success. Should've been: {:?}", $s), Err(ref err) => assert!(err.to_string().contains($s.as_slice()), format!("`{}` did not contain `{}`", err, $s)) } @@ -889,7 +889,7 @@ mod test { let mut read_buf = [0; 1028]; let read_str = match check!(read_stream.read(&mut read_buf)) { -1|0 => panic!("shouldn't happen"), - n => str::from_utf8(read_buf[..n]).unwrap().to_string() + n => str::from_utf8(read_buf.index(&(0..n))).unwrap().to_string() }; assert_eq!(read_str.as_slice(), message); } @@ -906,7 +906,7 @@ mod test { if cfg!(unix) { error!(result, "no such file or directory"); } - error!(result, format!("path={}; mode=open; access=read", filename.display())); + error!(result, format!("path={:?}; mode=open; access=read", filename.display())); } #[test] @@ -920,7 +920,7 @@ mod test { if cfg!(unix) { error!(result, "no such file or directory"); } - error!(result, format!("path={}", filename.display())); + error!(result, format!("path={:?}", filename.display())); } #[test] @@ -1188,7 +1188,7 @@ mod test { error!(result, "couldn't recursively mkdir"); error!(result, "couldn't create directory"); error!(result, "mode=0700"); - error!(result, format!("path={}", file.display())); + error!(result, format!("path={:?}", file.display())); } #[test] @@ -1255,7 +1255,7 @@ mod test { error!(copy(&from, &to), format!("couldn't copy path (the source path is not an \ - existing file; from={}; to={})", + existing file; from={:?}; to={:?})", from.display(), to.display())); match copy(&from, &to) { diff --git a/src/libstd/io/mem.rs b/src/libstd/io/mem.rs index 5c17644a1ac..9a6ad04fdbc 100644 --- a/src/libstd/io/mem.rs +++ b/src/libstd/io/mem.rs @@ -13,6 +13,7 @@ //! Readers and Writers for in-memory buffers use cmp::min; +use ops::Index; use option::Option::None; use result::Result::{Err, Ok}; use io; @@ -159,7 +160,7 @@ impl Reader for MemReader { let write_len = min(buf.len(), self.buf.len() - self.pos); { - let input = self.buf[self.pos.. self.pos + write_len]; + let input = self.buf.index(&(self.pos.. (self.pos + write_len))); let output = buf.slice_to_mut(write_len); assert_eq!(input.len(), output.len()); slice::bytes::copy_memory(output, input); @@ -187,7 +188,7 @@ impl Buffer for MemReader { #[inline] fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]> { if self.pos < self.buf.len() { - Ok(self.buf[self.pos..]) + Ok(self.buf.index(&(self.pos..))) } else { Err(io::standard_error(io::EndOfFile)) } @@ -204,7 +205,7 @@ impl<'a> Reader for &'a [u8] { let write_len = min(buf.len(), self.len()); { - let input = self[..write_len]; + let input = self.index(&(0..write_len)); let output = buf.slice_to_mut(write_len); slice::bytes::copy_memory(output, input); } @@ -227,7 +228,7 @@ impl<'a> Buffer for &'a [u8] { #[inline] fn consume(&mut self, amt: uint) { - *self = self[amt..]; + *self = self.index(&(amt..)); } } @@ -286,7 +287,7 @@ impl<'a> Writer for BufWriter<'a> { Ok(()) } else { - slice::bytes::copy_memory(dst, src[..dst_len]); + slice::bytes::copy_memory(dst, src.index(&(0..dst_len))); self.pos += dst_len; @@ -349,7 +350,7 @@ impl<'a> Reader for BufReader<'a> { let write_len = min(buf.len(), self.buf.len() - self.pos); { - let input = self.buf[self.pos.. self.pos + write_len]; + let input = self.buf.index(&(self.pos.. (self.pos + write_len))); let output = buf.slice_to_mut(write_len); assert_eq!(input.len(), output.len()); slice::bytes::copy_memory(output, input); @@ -377,7 +378,7 @@ impl<'a> Buffer for BufReader<'a> { #[inline] fn fill_buf(&mut self) -> IoResult<&[u8]> { if self.pos < self.buf.len() { - Ok(self.buf[self.pos..]) + Ok(self.buf.index(&(self.pos..))) } else { Err(io::standard_error(io::EndOfFile)) } @@ -390,9 +391,9 @@ impl<'a> Buffer for BufReader<'a> { #[cfg(test)] mod test { extern crate "test" as test_crate; - use prelude::v1::*; - - use io::{SeekSet, SeekCur, SeekEnd}; + use io::{SeekSet, SeekCur, SeekEnd, Reader, Writer, Seek}; + use prelude::v1::{Ok, Err, range, Vec, Buffer, AsSlice, SliceExt}; + use prelude::v1::{IteratorExt, Index}; use io; use iter::repeat; use self::test_crate::Bencher; @@ -498,7 +499,7 @@ mod test { assert_eq!(buf, b); assert_eq!(reader.read(&mut buf), Ok(3)); let b: &[_] = &[5, 6, 7]; - assert_eq!(buf[0..3], b); + assert_eq!(buf.index(&(0..3)), b); assert!(reader.read(&mut buf).is_err()); let mut reader = MemReader::new(vec!(0, 1, 2, 3, 4, 5, 6, 7)); assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3)); @@ -524,7 +525,7 @@ mod test { assert_eq!(buf.as_slice(), b); assert_eq!(reader.read(&mut buf), Ok(3)); let b: &[_] = &[5, 6, 7]; - assert_eq!(buf[0..3], b); + assert_eq!(buf.index(&(0..3)), b); assert!(reader.read(&mut buf).is_err()); let mut reader = &mut in_buf.as_slice(); assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3)); @@ -551,7 +552,7 @@ mod test { assert_eq!(buf, b); assert_eq!(reader.read(&mut buf), Ok(3)); let b: &[_] = &[5, 6, 7]; - assert_eq!(buf[0..3], b); + assert_eq!(buf.index(&(0..3)), b); assert!(reader.read(&mut buf).is_err()); let mut reader = BufReader::new(in_buf.as_slice()); assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3)); diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 5bef473db99..9ef9081bc3c 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -120,10 +120,12 @@ //! for stream in acceptor.incoming() { //! match stream { //! Err(e) => { /* connection failed */ } -//! Ok(stream) => Thread::spawn(move|| { -//! // connection succeeded -//! handle_client(stream) -//! }).detach() +//! Ok(stream) => { +//! Thread::spawn(move|| { +//! // connection succeeded +//! handle_client(stream) +//! }); +//! } //! } //! } //! @@ -232,9 +234,9 @@ use error::{FromError, Error}; use fmt; use int; use iter::{Iterator, IteratorExt}; -use kinds::Sized; +use marker::Sized; use mem::transmute; -use ops::FnOnce; +use ops::{FnOnce, Index}; use option::Option; use option::Option::{Some, None}; use os; @@ -285,8 +287,7 @@ pub mod stdio; pub mod timer; pub mod util; -#[cfg_attr(stage0, macro_escape)] -#[cfg_attr(not(stage0), macro_use)] +#[macro_use] pub mod test; /// The default buffer size for various I/O operations @@ -302,7 +303,7 @@ pub type IoResult<T> = Result<T, IoError>; /// # FIXME /// /// Is something like this sufficient? It's kind of archaic -#[derive(PartialEq, Eq, Clone)] +#[derive(PartialEq, Eq, Clone, Show)] pub struct IoError { /// An enumeration which can be matched against for determining the flavor /// of error. @@ -339,7 +340,7 @@ impl IoError { } } -impl fmt::Show for IoError { +impl fmt::String for IoError { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match *self { IoError { kind: OtherIoError, desc: "unknown error", detail: Some(ref detail) } => @@ -1068,7 +1069,7 @@ pub trait Writer { fn write_char(&mut self, c: char) -> IoResult<()> { let mut buf = [0u8; 4]; let n = c.encode_utf8(buf.as_mut_slice()).unwrap_or(0); - self.write(buf[..n]) + self.write(buf.index(&(0..n))) } /// Write the result of passing n through `int::to_str_bytes`. @@ -1453,7 +1454,7 @@ pub trait Buffer: Reader { }; match available.iter().position(|&b| b == byte) { Some(i) => { - res.push_all(available[..i + 1]); + res.push_all(available.index(&(0..(i + 1)))); used = i + 1; break } @@ -1492,7 +1493,7 @@ pub trait Buffer: Reader { } } } - match str::from_utf8(buf[..width]).ok() { + match str::from_utf8(buf.index(&(0..width))).ok() { Some(s) => Ok(s.char_at(0)), None => Err(standard_error(InvalidInput)) } @@ -1604,6 +1605,7 @@ pub struct IncomingConnections<'a, A: ?Sized +'a> { inc: &'a mut A, } +#[old_impl_check] impl<'a, T, A: ?Sized + Acceptor<T>> Iterator for IncomingConnections<'a, A> { type Item = IoResult<T>; @@ -1656,7 +1658,7 @@ pub fn standard_error(kind: IoErrorKind) -> IoError { /// A mode specifies how a file should be opened or created. These modes are /// passed to `File::open_mode` and are used to control where the file is /// positioned when it is initially opened. -#[derive(Copy, Clone, PartialEq, Eq)] +#[derive(Copy, Clone, PartialEq, Eq, Show)] pub enum FileMode { /// Opens a file positioned at the beginning. Open, @@ -1668,7 +1670,7 @@ pub enum FileMode { /// Access permissions with which the file should be opened. `File`s /// opened with `Read` will return an error if written to. -#[derive(Copy, Clone, PartialEq, Eq)] +#[derive(Copy, Clone, PartialEq, Eq, Show)] pub enum FileAccess { /// Read-only access, requests to write will result in an error Read, @@ -1780,9 +1782,11 @@ pub struct UnstableFileStat { pub gen: u64, } + +// NOTE(stage0): change this one last #[doc=..] to /// after the next snapshot bitflags! { - #[doc = "A set of permissions for a file or directory is represented"] - #[doc = "by a set of flags which are or'd together."] + #[doc = "A set of permissions for a file or directory is represented by a set of"] + /// flags which are or'd together. flags FilePermission: u32 { const USER_READ = 0o400, const USER_WRITE = 0o200, @@ -1798,20 +1802,20 @@ bitflags! { const GROUP_RWX = GROUP_READ.bits | GROUP_WRITE.bits | GROUP_EXECUTE.bits, const OTHER_RWX = OTHER_READ.bits | OTHER_WRITE.bits | OTHER_EXECUTE.bits, - #[doc = "Permissions for user owned files, equivalent to 0644 on"] - #[doc = "unix-like systems."] + /// Permissions for user owned files, equivalent to 0644 on unix-like + /// systems. const USER_FILE = USER_READ.bits | USER_WRITE.bits | GROUP_READ.bits | OTHER_READ.bits, - #[doc = "Permissions for user owned directories, equivalent to 0755 on"] - #[doc = "unix-like systems."] + /// Permissions for user owned directories, equivalent to 0755 on + /// unix-like systems. const USER_DIR = USER_RWX.bits | GROUP_READ.bits | GROUP_EXECUTE.bits | OTHER_READ.bits | OTHER_EXECUTE.bits, - #[doc = "Permissions for user owned executables, equivalent to 0755"] - #[doc = "on unix-like systems."] + /// Permissions for user owned executables, equivalent to 0755 + /// on unix-like systems. const USER_EXEC = USER_DIR.bits, - #[doc = "All possible permissions enabled."] + /// All possible permissions enabled. const ALL_PERMISSIONS = USER_RWX.bits | GROUP_RWX.bits | OTHER_RWX.bits, } } @@ -1826,6 +1830,12 @@ impl Default for FilePermission { impl fmt::Show for FilePermission { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::String::fmt(self, f) + } +} + +impl fmt::String for FilePermission { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:04o}", self.bits) } } diff --git a/src/libstd/io/net/addrinfo.rs b/src/libstd/io/net/addrinfo.rs index 24d45dcd652..7825a4e16e1 100644 --- a/src/libstd/io/net/addrinfo.rs +++ b/src/libstd/io/net/addrinfo.rs @@ -29,7 +29,7 @@ use sys; use vec::Vec; /// Hints to the types of sockets that are desired when looking up hosts -#[derive(Copy)] +#[derive(Copy, Show)] pub enum SocketType { Stream, Datagram, Raw } @@ -38,7 +38,7 @@ pub enum SocketType { /// to manipulate how a query is performed. /// /// The meaning of each of these flags can be found with `man -s 3 getaddrinfo` -#[derive(Copy)] +#[derive(Copy, Show)] pub enum Flag { AddrConfig, All, @@ -51,7 +51,7 @@ pub enum Flag { /// A transport protocol associated with either a hint or a return value of /// `lookup` -#[derive(Copy)] +#[derive(Copy, Show)] pub enum Protocol { TCP, UDP } @@ -61,7 +61,7 @@ pub enum Protocol { /// /// For details on these fields, see their corresponding definitions via /// `man -s 3 getaddrinfo` -#[derive(Copy)] +#[derive(Copy, Show)] pub struct Hint { pub family: uint, pub socktype: Option<SocketType>, @@ -69,7 +69,7 @@ pub struct Hint { pub flags: uint, } -#[derive(Copy)] +#[derive(Copy, Show)] pub struct Info { pub address: SocketAddr, pub family: uint, diff --git a/src/libstd/io/net/ip.rs b/src/libstd/io/net/ip.rs index d398b61fe64..b9f653f86c2 100644 --- a/src/libstd/io/net/ip.rs +++ b/src/libstd/io/net/ip.rs @@ -22,7 +22,7 @@ use fmt; use io::{self, IoResult, IoError}; use io::net; use iter::{Iterator, IteratorExt}; -use ops::{FnOnce, FnMut}; +use ops::{FnOnce, FnMut, Index}; use option::Option; use option::Option::{None, Some}; use result::Result::{Ok, Err}; @@ -32,13 +32,13 @@ use vec::Vec; pub type Port = u16; -#[derive(Copy, PartialEq, Eq, Clone, Hash)] +#[derive(Copy, PartialEq, Eq, Clone, Hash, Show)] pub enum IpAddr { Ipv4Addr(u8, u8, u8, u8), Ipv6Addr(u16, u16, u16, u16, u16, u16, u16, u16) } -impl fmt::Show for IpAddr { +impl fmt::String for IpAddr { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match *self { Ipv4Addr(a, b, c, d) => @@ -63,13 +63,13 @@ impl fmt::Show for IpAddr { } } -#[derive(Copy, PartialEq, Eq, Clone, Hash)] +#[derive(Copy, PartialEq, Eq, Clone, Hash, Show)] pub struct SocketAddr { pub ip: IpAddr, pub port: Port, } -impl fmt::Show for SocketAddr { +impl fmt::String for SocketAddr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.ip { Ipv4Addr(..) => write!(f, "{}:{}", self.ip, self.port), @@ -313,7 +313,7 @@ impl<'a> Parser<'a> { let mut tail = [0u16; 8]; let (tail_size, _) = read_groups(self, &mut tail, 8 - head_size); - Some(ipv6_addr_from_head_tail(head[..head_size], tail[..tail_size])) + Some(ipv6_addr_from_head_tail(head.index(&(0..head_size)), tail.index(&(0..tail_size)))) } fn read_ipv6_addr(&mut self) -> Option<IpAddr> { diff --git a/src/libstd/io/net/pipe.rs b/src/libstd/io/net/pipe.rs index 738c70412f7..29295b5751c 100644 --- a/src/libstd/io/net/pipe.rs +++ b/src/libstd/io/net/pipe.rs @@ -608,7 +608,7 @@ mod tests { let mut a = a; let _s = a.accept().unwrap(); let _ = rx.recv(); - }).detach(); + }); let mut b = [0]; let mut s = UnixStream::connect(&addr).unwrap(); @@ -645,7 +645,7 @@ mod tests { let mut a = a; let _s = a.accept().unwrap(); let _ = rx.recv(); - }).detach(); + }); let mut s = UnixStream::connect(&addr).unwrap(); let s2 = s.clone(); @@ -672,7 +672,7 @@ mod tests { rx.recv().unwrap(); assert!(s.write(&[0]).is_ok()); let _ = rx.recv(); - }).detach(); + }); let mut s = a.accept().unwrap(); s.set_timeout(Some(20)); @@ -716,7 +716,7 @@ mod tests { } } let _ = rx.recv(); - }).detach(); + }); let mut s = a.accept().unwrap(); s.set_read_timeout(Some(20)); @@ -739,7 +739,7 @@ mod tests { rx.recv().unwrap(); assert!(s.write(&[0]).is_ok()); let _ = rx.recv(); - }).detach(); + }); let mut s = a.accept().unwrap(); s.set_write_timeout(Some(20)); @@ -766,7 +766,7 @@ mod tests { rx.recv().unwrap(); assert!(s.write(&[0]).is_ok()); let _ = rx.recv(); - }).detach(); + }); let mut s = a.accept().unwrap(); let s2 = s.clone(); diff --git a/src/libstd/io/net/tcp.rs b/src/libstd/io/net/tcp.rs index 3e59aaa05ef..7a376b50cd7 100644 --- a/src/libstd/io/net/tcp.rs +++ b/src/libstd/io/net/tcp.rs @@ -146,7 +146,7 @@ impl TcpStream { /// timer::sleep(Duration::seconds(1)); /// let mut stream = stream2; /// stream.close_read(); - /// }).detach(); + /// }); /// /// // wait for some data, will get canceled after one second /// let mut buf = [0]; @@ -295,10 +295,12 @@ impl sys_common::AsInner<TcpStreamImp> for TcpStream { /// for stream in acceptor.incoming() { /// match stream { /// Err(e) => { /* connection failed */ } -/// Ok(stream) => Thread::spawn(move|| { -/// // connection succeeded -/// handle_client(stream) -/// }).detach() +/// Ok(stream) => { +/// Thread::spawn(move|| { +/// // connection succeeded +/// handle_client(stream) +/// }); +/// } /// } /// } /// @@ -432,7 +434,7 @@ impl TcpAcceptor { /// Err(e) => panic!("unexpected error: {}", e), /// } /// } - /// }).detach(); + /// }); /// /// # fn wait_for_sigint() {} /// // Now that our accept loop is running, wait for the program to be @@ -660,7 +662,7 @@ mod test { Ok(..) => panic!(), Err(ref e) => { assert!(e.kind == NotConnected || e.kind == EndOfFile, - "unknown kind: {}", e.kind); + "unknown kind: {:?}", e.kind); } } } @@ -684,7 +686,7 @@ mod test { Ok(..) => panic!(), Err(ref e) => { assert!(e.kind == NotConnected || e.kind == EndOfFile, - "unknown kind: {}", e.kind); + "unknown kind: {:?}", e.kind); } } } @@ -997,7 +999,7 @@ mod test { Ok(..) => panic!(), Err(e) => { assert!(e.kind == ConnectionRefused || e.kind == OtherIoError, - "unknown error: {} {}", e, e.kind); + "unknown error: {} {:?}", e, e.kind); } } } @@ -1186,7 +1188,7 @@ mod test { let mut a = a; let _s = a.accept().unwrap(); let _ = rx.recv().unwrap(); - }).detach(); + }); let mut b = [0]; let mut s = TcpStream::connect(addr).unwrap(); @@ -1223,7 +1225,7 @@ mod test { let mut a = a; let _s = a.accept().unwrap(); let _ = rx.recv().unwrap(); - }).detach(); + }); let mut s = TcpStream::connect(addr).unwrap(); let s2 = s.clone(); @@ -1250,7 +1252,7 @@ mod test { rx.recv().unwrap(); assert!(s.write(&[0]).is_ok()); let _ = rx.recv(); - }).detach(); + }); let mut s = a.accept().unwrap(); s.set_timeout(Some(20)); @@ -1289,7 +1291,7 @@ mod test { } } let _ = rx.recv(); - }).detach(); + }); let mut s = a.accept().unwrap(); s.set_read_timeout(Some(20)); @@ -1312,7 +1314,7 @@ mod test { rx.recv().unwrap(); assert!(s.write(&[0]).is_ok()); let _ = rx.recv(); - }).detach(); + }); let mut s = a.accept().unwrap(); s.set_write_timeout(Some(20)); @@ -1340,7 +1342,7 @@ mod test { rx.recv().unwrap(); assert_eq!(s.write(&[0]), Ok(())); let _ = rx.recv(); - }).detach(); + }); let mut s = a.accept().unwrap(); let s2 = s.clone(); diff --git a/src/libstd/io/process.rs b/src/libstd/io/process.rs index ea232ad0c3f..55df6330dd3 100644 --- a/src/libstd/io/process.rs +++ b/src/libstd/io/process.rs @@ -395,7 +395,14 @@ impl Command { } } +#[cfg(stage0)] impl fmt::Show for Command { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::String::fmt(self, f) + } +} + +impl fmt::String for Command { /// Format the program and arguments of a Command for display. Any /// non-utf8 data is lossily converted using the utf8 replacement /// character. @@ -506,6 +513,14 @@ pub enum ProcessExit { impl fmt::Show for ProcessExit { /// Format a ProcessExit enum, to nicely present the information. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::String::fmt(self, f) + } +} + + +impl fmt::String for ProcessExit { + /// Format a ProcessExit enum, to nicely present the information. + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { ExitStatus(code) => write!(f, "exit code: {}", code), ExitSignal(code) => write!(f, "signal: {}", code), @@ -705,7 +720,7 @@ impl Process { Thread::spawn(move |:| { let mut stream = stream; tx.send(stream.read_to_end()).unwrap(); - }).detach(); + }); } None => tx.send(Ok(Vec::new())).unwrap() } @@ -752,12 +767,12 @@ impl Drop for Process { #[cfg(test)] mod tests { - use prelude::v1::*; - + use io::{Truncate, Write, TimedOut, timer, process, FileNotFound}; + use prelude::v1::{Ok, Err, range, drop, Some, None, Vec}; + use prelude::v1::{Path, String, Reader, Writer, Clone}; + use prelude::v1::{SliceExt, Str, StrExt, AsSlice, ToString, GenericPath}; use io::fs::PathExtensions; - use io::process; use io::timer::*; - use io::{Truncate, Write, TimedOut, timer, FileNotFound}; use rt::running_on_valgrind; use str; use super::{CreatePipe}; diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index f571bed3ba2..9ee2f5705b8 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -34,7 +34,7 @@ use failure::LOCAL_STDERR; use fmt; use io::{Reader, Writer, IoResult, IoError, OtherIoError, Buffer, standard_error, EndOfFile, LineBufferedWriter, BufferedReader}; -use kinds::{Sync, Send}; +use marker::{Sync, Send}; use libc; use mem; use option::Option; @@ -349,7 +349,7 @@ fn with_task_stdout<F>(f: F) where F: FnOnce(&mut Writer) -> IoResult<()> { }); match result { Ok(()) => {} - Err(e) => panic!("failed printing to stdout: {}", e), + Err(e) => panic!("failed printing to stdout: {:?}", e), } } diff --git a/src/libstd/io/timer.rs b/src/libstd/io/timer.rs index e073f76af82..8a0445be471 100644 --- a/src/libstd/io/timer.rs +++ b/src/libstd/io/timer.rs @@ -358,7 +358,7 @@ mod test { Thread::spawn(move|| { let _ = timer_rx.recv(); - }).detach(); + }); // when we drop the TimerWatcher we're going to destroy the channel, // which must wake up the task on the other end @@ -372,7 +372,7 @@ mod test { Thread::spawn(move|| { let _ = timer_rx.recv(); - }).detach(); + }); timer.oneshot(Duration::milliseconds(1)); } @@ -385,7 +385,7 @@ mod test { Thread::spawn(move|| { let _ = timer_rx.recv(); - }).detach(); + }); timer.sleep(Duration::milliseconds(1)); } diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index 86fa68d63ac..c0254a3e7a2 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -59,7 +59,7 @@ impl<R: Reader> Reader for LimitReader<R> { impl<R: Buffer> Buffer for LimitReader<R> { fn fill_buf<'a>(&'a mut self) -> io::IoResult<&'a [u8]> { let amt = try!(self.inner.fill_buf()); - let buf = amt[..cmp::min(amt.len(), self.limit)]; + let buf = amt.index(&(0..cmp::min(amt.len(), self.limit))); if buf.len() == 0 { Err(io::standard_error(io::EndOfFile)) } else { @@ -220,7 +220,7 @@ impl<R: Reader, W: Writer> TeeReader<R, W> { impl<R: Reader, W: Writer> Reader for TeeReader<R, W> { fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> { self.reader.read(buf).and_then(|len| { - self.writer.write(buf[mut ..len]).map(|()| len) + self.writer.write(buf.index_mut(&(0..len))).map(|()| len) }) } } @@ -234,7 +234,7 @@ pub fn copy<R: Reader, W: Writer>(r: &mut R, w: &mut W) -> io::IoResult<()> { Err(ref e) if e.kind == io::EndOfFile => return Ok(()), Err(e) => return Err(e), }; - try!(w.write(buf[..len])); + try!(w.write(buf.index(&(0..len)))); } } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index b9f226c5aca..eef5bdb60ee 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -18,7 +18,7 @@ //! //! The [`ptr`](ptr/index.html) and [`mem`](mem/index.html) //! modules deal with unsafe pointers and memory manipulation. -//! [`kinds`](kinds/index.html) defines the special built-in traits, +//! [`markers`](markers/index.html) defines the special built-in traits, //! and [`raw`](raw/index.html) the runtime representation of Rust types. //! These are some of the lowest-level building blocks in Rust. //! @@ -104,42 +104,26 @@ html_playground_url = "http://play.rust-lang.org/")] #![allow(unknown_features)] -#![feature(macro_rules, globs, linkage, thread_local, asm)] -#![feature(default_type_params, phase, lang_items, unsafe_destructor)] +#![feature(linkage, thread_local, asm)] +#![feature(lang_items, unsafe_destructor)] #![feature(slicing_syntax, unboxed_closures)] -#![feature(old_orphan_check)] -#![feature(associated_types)] +#![feature(old_impl_check)] +#![cfg_attr(stage0, allow(unused_attributes))] // Don't link to std. We are std. #![no_std] #![deny(missing_docs)] -#![reexport_test_harness_main = "test_main"] - -#[cfg(all(test, stage0))] -#[phase(plugin, link)] -extern crate log; - -#[cfg(all(test, not(stage0)))] +#[cfg(test)] #[macro_use] extern crate log; -#[cfg(stage0)] -#[phase(plugin, link)] -extern crate core; - -#[cfg(not(stage0))] #[macro_use] #[macro_reexport(assert, assert_eq, debug_assert, debug_assert_eq, - unreachable, unimplemented, write, writeln)] + unreachable, unimplemented, write, writeln)] extern crate core; -#[cfg(stage0)] -#[phase(plugin, link)] -extern crate "collections" as core_collections; - -#[cfg(not(stage0))] #[macro_use] #[macro_reexport(vec)] extern crate "collections" as core_collections; @@ -151,7 +135,7 @@ extern crate libc; // Make std testable by not duplicating lang items. See #2912 #[cfg(test)] extern crate "std" as realstd; -#[cfg(test)] pub use realstd::kinds; +#[cfg(test)] pub use realstd::marker; #[cfg(test)] pub use realstd::ops; #[cfg(test)] pub use realstd::cmp; #[cfg(test)] pub use realstd::boxed; @@ -168,7 +152,8 @@ pub use core::default; pub use core::finally; pub use core::intrinsics; pub use core::iter; -#[cfg(not(test))] pub use core::kinds; +#[cfg(stage0)] #[cfg(not(test))] pub use core::marker as kinds; +#[cfg(not(test))] pub use core::marker; pub use core::mem; #[cfg(not(test))] pub use core::ops; pub use core::ptr; @@ -190,18 +175,10 @@ pub use unicode::char; /* Exported macros */ -#[cfg(stage0)] -#[cfg_attr(stage0, macro_escape)] -#[cfg_attr(not(stage0), macro_use)] -pub mod macros_stage0; - -#[cfg(not(stage0))] -#[cfg_attr(stage0, macro_escape)] -#[cfg_attr(not(stage0), macro_use)] +#[macro_use] pub mod macros; -#[cfg_attr(stage0, macro_escape)] -#[cfg_attr(not(stage0), macro_use)] +#[macro_use] pub mod bitflags; mod rtdeps; @@ -214,18 +191,15 @@ pub mod prelude; /* Primitive types */ #[path = "num/float_macros.rs"] -#[cfg_attr(stage0, macro_escape)] -#[cfg_attr(not(stage0), macro_use)] +#[macro_use] mod float_macros; #[path = "num/int_macros.rs"] -#[cfg_attr(stage0, macro_escape)] -#[cfg_attr(not(stage0), macro_use)] +#[macro_use] mod int_macros; #[path = "num/uint_macros.rs"] -#[cfg_attr(stage0, macro_escape)] -#[cfg_attr(not(stage0), macro_use)] +#[macro_use] mod uint_macros; #[path = "num/int.rs"] pub mod int; @@ -253,8 +227,7 @@ pub mod num; /* Runtime and platform support */ -#[cfg_attr(stage0, macro_escape)] -#[cfg_attr(not(stage0), macro_use)] +#[macro_use] pub mod thread_local; pub mod dynamic_lib; @@ -311,7 +284,9 @@ mod std { pub use vec; // used for vec![] pub use cell; // used for tls! pub use thread_local; // used for thread_local! - pub use kinds; // used for tls! + #[cfg(stage0)] + pub use marker as kinds; + pub use marker; // used for tls! pub use ops; // used for bitflags! // The test runner calls ::std::os::args() but really wants realstd diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index d96441e09a8..befdc156094 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -111,7 +111,7 @@ macro_rules! assert_eq { if !((*left_val == *right_val) && (*right_val == *left_val)) { panic!("assertion failed: `(left == right) && (right == left)` \ - (left: `{}`, right: `{}`)", *left_val, *right_val) + (left: `{:?}`, right: `{:?}`)", *left_val, *right_val) } } } @@ -303,8 +303,8 @@ macro_rules! try { /// # fn long_running_task() {} /// # fn calculate_the_answer() -> int { 42i } /// -/// Thread::spawn(move|| { long_running_task(); tx1.send(()) }).detach(); -/// Thread::spawn(move|| { tx2.send(calculate_the_answer()) }).detach(); +/// Thread::spawn(move|| { long_running_task(); tx1.send(()).unwrap(); }); +/// Thread::spawn(move|| { tx2.send(calculate_the_answer()).unwrap(); }); /// /// select! ( /// _ = rx1.recv() => println!("the long running task finished first"), @@ -371,7 +371,7 @@ pub mod builtin { /// /// ``` #[macro_export] - macro_rules! format_args { ($fmt:expr $($args:tt)*) => ({ + macro_rules! format_args { ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) } @@ -407,7 +407,7 @@ pub mod builtin { /// /// ```rust /// let key: Option<&'static str> = option_env!("SECRET_KEY"); - /// println!("the secret key might be: {}", key); + /// println!("the secret key might be: {:?}", key); /// ``` #[macro_export] macro_rules! option_env { ($name:expr) => ({ /* compiler built-in */ }) } diff --git a/src/libstd/macros_stage0.rs b/src/libstd/macros_stage0.rs deleted file mode 100644 index 48d62e73e13..00000000000 --- a/src/libstd/macros_stage0.rs +++ /dev/null @@ -1,648 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Standard library macros -//! -//! This modules contains a set of macros which are exported from the standard -//! library. Each macro is available for use when linking against the standard -//! library. - -#![experimental] - -/// The entry point for panic of Rust tasks. -/// -/// This macro is used to inject panic into a Rust task, causing the task to -/// unwind and panic entirely. Each task's panic can be reaped as the -/// `Box<Any>` type, and the single-argument form of the `panic!` macro will be -/// the value which is transmitted. -/// -/// The multi-argument form of this macro panics with a string and has the -/// `format!` syntax for building a string. -/// -/// # Example -/// -/// ```should_fail -/// # #![allow(unreachable_code)] -/// panic!(); -/// panic!("this is a terrible mistake!"); -/// panic!(4i); // panic with the value of 4 to be collected elsewhere -/// panic!("this is a {} {message}", "fancy", message = "message"); -/// ``` -#[macro_export] -macro_rules! panic { - () => ({ - panic!("explicit panic") - }); - ($msg:expr) => ({ - // static requires less code at runtime, more constant data - static _FILE_LINE: (&'static str, uint) = (file!(), line!()); - ::std::rt::begin_unwind($msg, &_FILE_LINE) - }); - ($fmt:expr, $($arg:tt)*) => ({ - // The leading _'s are to avoid dead code warnings if this is - // used inside a dead function. Just `#[allow(dead_code)]` is - // insufficient, since the user may have - // `#[forbid(dead_code)]` and which cannot be overridden. - static _FILE_LINE: (&'static str, uint) = (file!(), line!()); - ::std::rt::begin_unwind_fmt(format_args!($fmt, $($arg)*), &_FILE_LINE) - - }); -} - -/// Ensure that a boolean expression is `true` at runtime. -/// -/// This will invoke the `panic!` macro if the provided expression cannot be -/// evaluated to `true` at runtime. -/// -/// # Example -/// -/// ``` -/// // the panic message for these assertions is the stringified value of the -/// // expression given. -/// assert!(true); -/// # fn some_computation() -> bool { true } -/// assert!(some_computation()); -/// -/// // assert with a custom message -/// # let x = true; -/// assert!(x, "x wasn't true!"); -/// # let a = 3i; let b = 27i; -/// assert!(a + b == 30, "a = {}, b = {}", a, b); -/// ``` -#[macro_export] -macro_rules! assert { - ($cond:expr) => ( - if !$cond { - panic!(concat!("assertion failed: ", stringify!($cond))) - } - ); - ($cond:expr, $($arg:expr),+) => ( - if !$cond { - panic!($($arg),+) - } - ); -} - -/// Asserts that two expressions are equal to each other, testing equality in -/// both directions. -/// -/// On panic, this macro will print the values of the expressions. -/// -/// # Example -/// -/// ``` -/// let a = 3i; -/// let b = 1i + 2i; -/// assert_eq!(a, b); -/// ``` -#[macro_export] -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)` \ - (left: `{}`, right: `{}`)", *left_val, *right_val) - } - } - } - }) -} - -/// Ensure that a boolean expression is `true` at runtime. -/// -/// This will invoke the `panic!` macro if the provided expression cannot be -/// evaluated to `true` at runtime. -/// -/// Unlike `assert!`, `debug_assert!` statements can be disabled by passing -/// `--cfg ndebug` to the compiler. This makes `debug_assert!` useful for -/// checks that are too expensive to be present in a release build but may be -/// helpful during development. -/// -/// # Example -/// -/// ``` -/// // the panic message for these assertions is the stringified value of the -/// // expression given. -/// debug_assert!(true); -/// # fn some_expensive_computation() -> bool { true } -/// debug_assert!(some_expensive_computation()); -/// -/// // assert with a custom message -/// # let x = true; -/// debug_assert!(x, "x wasn't true!"); -/// # let a = 3i; let b = 27i; -/// debug_assert!(a + b == 30, "a = {}, b = {}", a, b); -/// ``` -#[macro_export] -macro_rules! debug_assert { - ($($arg:tt)*) => (if cfg!(not(ndebug)) { assert!($($arg)*); }) -} - -/// Asserts that two expressions are equal to each other, testing equality in -/// both directions. -/// -/// On panic, this macro will print the values of the expressions. -/// -/// Unlike `assert_eq!`, `debug_assert_eq!` statements can be disabled by -/// passing `--cfg ndebug` to the compiler. This makes `debug_assert_eq!` -/// useful for checks that are too expensive to be present in a release build -/// but may be helpful during development. -/// -/// # Example -/// -/// ``` -/// let a = 3i; -/// let b = 1i + 2i; -/// debug_assert_eq!(a, b); -/// ``` -#[macro_export] -macro_rules! debug_assert_eq { - ($($arg:tt)*) => (if cfg!(not(ndebug)) { assert_eq!($($arg)*); }) -} - -/// A utility macro for indicating unreachable code. -/// -/// This is useful any time that the compiler can't determine that some code is unreachable. For -/// example: -/// -/// * Match arms with guard conditions. -/// * Loops that dynamically terminate. -/// * Iterators that dynamically terminate. -/// -/// # Panics -/// -/// This will always panic. -/// -/// # Examples -/// -/// Match arms: -/// -/// ```rust -/// fn foo(x: Option<int>) { -/// match x { -/// Some(n) if n >= 0 => println!("Some(Non-negative)"), -/// Some(n) if n < 0 => println!("Some(Negative)"), -/// Some(_) => unreachable!(), // compile error if commented out -/// None => println!("None") -/// } -/// } -/// ``` -/// -/// Iterators: -/// -/// ```rust -/// fn divide_by_three(x: u32) -> u32 { // one of the poorest implementations of x/3 -/// for i in std::iter::count(0_u32, 1) { -/// if 3*i < i { panic!("u32 overflow"); } -/// if x < 3*i { return i-1; } -/// } -/// unreachable!(); -/// } -/// ``` -#[macro_export] -macro_rules! unreachable { - () => ({ - panic!("internal error: entered unreachable code") - }); - ($msg:expr) => ({ - unreachable!("{}", $msg) - }); - ($fmt:expr, $($arg:tt)*) => ({ - panic!(concat!("internal error: entered unreachable code: ", $fmt), $($arg)*) - }); -} - -/// A standardised placeholder for marking unfinished code. It panics with the -/// message `"not yet implemented"` when executed. -#[macro_export] -macro_rules! unimplemented { - () => (panic!("not yet implemented")) -} - -/// Use the syntax described in `std::fmt` to create a value of type `String`. -/// See `std::fmt` for more information. -/// -/// # Example -/// -/// ``` -/// format!("test"); -/// format!("hello {}", "world!"); -/// format!("x = {}, y = {y}", 10i, y = 30i); -/// ``` -#[macro_export] -#[stable] -macro_rules! format { - ($($arg:tt)*) => (::std::fmt::format(format_args!($($arg)*))) -} - -/// Use the `format!` syntax to write data into a buffer of type `&mut Writer`. -/// See `std::fmt` for more information. -/// -/// # Example -/// -/// ``` -/// # #![allow(unused_must_use)] -/// -/// let mut w = Vec::new(); -/// write!(&mut w, "test"); -/// write!(&mut w, "formatted {}", "arguments"); -/// ``` -#[macro_export] -#[stable] -macro_rules! write { - ($dst:expr, $($arg:tt)*) => ((&mut *$dst).write_fmt(format_args!($($arg)*))) -} - -/// Equivalent to the `write!` macro, except that a newline is appended after -/// the message is written. -#[macro_export] -#[stable] -macro_rules! writeln { - ($dst:expr, $fmt:expr $($arg:tt)*) => ( - write!($dst, concat!($fmt, "\n") $($arg)*) - ) -} - -/// Equivalent to the `println!` macro except that a newline is not printed at -/// the end of the message. -#[macro_export] -#[stable] -macro_rules! print { - ($($arg:tt)*) => (::std::io::stdio::print_args(format_args!($($arg)*))) -} - -/// Macro for printing to a task's stdout handle. -/// -/// Each task can override its stdout handle via `std::io::stdio::set_stdout`. -/// The syntax of this macro is the same as that used for `format!`. For more -/// information, see `std::fmt` and `std::io::stdio`. -/// -/// # Example -/// -/// ``` -/// println!("hello there!"); -/// println!("format {} arguments", "some"); -/// ``` -#[macro_export] -#[stable] -macro_rules! println { - ($($arg:tt)*) => (::std::io::stdio::println_args(format_args!($($arg)*))) -} - -/// Helper macro for unwrapping `Result` values while returning early with an -/// error if the value of the expression is `Err`. For more information, see -/// `std::io`. -#[macro_export] -macro_rules! try { - ($expr:expr) => ({ - match $expr { - Ok(val) => val, - Err(err) => return Err(::std::error::FromError::from_error(err)) - } - }) -} - -/// Create a `std::vec::Vec` containing the arguments. -#[macro_export] -macro_rules! vec { - ($($x:expr),*) => ({ - let xs: ::std::boxed::Box<[_]> = box [$($x),*]; - ::std::slice::SliceExt::into_vec(xs) - }); - ($($x:expr,)*) => (vec![$($x),*]) -} - -/// A macro to select an event from a number of receivers. -/// -/// This macro is used to wait for the first event to occur on a number of -/// receivers. It places no restrictions on the types of receivers given to -/// this macro, this can be viewed as a heterogeneous select. -/// -/// # Example -/// -/// ``` -/// use std::thread::Thread; -/// use std::sync::mpsc::channel; -/// -/// let (tx1, rx1) = channel(); -/// let (tx2, rx2) = channel(); -/// # fn long_running_task() {} -/// # fn calculate_the_answer() -> int { 42i } -/// -/// Thread::spawn(move|| { long_running_task(); tx1.send(()) }).detach(); -/// Thread::spawn(move|| { tx2.send(calculate_the_answer()) }).detach(); -/// -/// select! ( -/// _ = rx1.recv() => println!("the long running task finished first"), -/// answer = rx2.recv() => { -/// println!("the answer was: {}", answer.unwrap()); -/// } -/// ) -/// ``` -/// -/// For more information about select, see the `std::sync::mpsc::Select` structure. -#[macro_export] -#[experimental] -macro_rules! select { - ( - $($name:pat = $rx:ident.$meth:ident() => $code:expr),+ - ) => ({ - use std::sync::mpsc::Select; - let sel = Select::new(); - $( let mut $rx = sel.handle(&$rx); )+ - unsafe { - $( $rx.add(); )+ - } - let ret = sel.wait(); - $( if ret == $rx.id() { let $name = $rx.$meth(); $code } else )+ - { unreachable!() } - }) -} - -// When testing the standard library, we link to the liblog crate to get the -// logging macros. In doing so, the liblog crate was linked against the real -// version of libstd, and uses a different std::fmt module than the test crate -// uses. To get around this difference, we redefine the log!() macro here to be -// just a dumb version of what it should be. -#[cfg(test)] -macro_rules! log { - ($lvl:expr, $($args:tt)*) => ( - if log_enabled!($lvl) { println!($($args)*) } - ) -} - -/// Built-in macros to the compiler itself. -/// -/// These macros do not have any corresponding definition with a `macro_rules!` -/// macro, but are documented here. Their implementations can be found hardcoded -/// into libsyntax itself. -#[cfg(dox)] -pub mod builtin { - /// The core macro for formatted string creation & output. - /// - /// This macro produces a value of type `fmt::Arguments`. This value can be - /// passed to the functions in `std::fmt` for performing useful functions. - /// All other formatting macros (`format!`, `write!`, `println!`, etc) are - /// proxied through this one. - /// - /// For more information, see the documentation in `std::fmt`. - /// - /// # Example - /// - /// ```rust - /// use std::fmt; - /// - /// let s = fmt::format(format_args!("hello {}", "world")); - /// assert_eq!(s, format!("hello {}", "world")); - /// - /// ``` - #[macro_export] - macro_rules! format_args { ($fmt:expr $($args:tt)*) => ({ - /* compiler built-in */ - }) } - - /// Inspect an environment variable at compile time. - /// - /// This macro will expand to the value of the named environment variable at - /// compile time, yielding an expression of type `&'static str`. - /// - /// If the environment variable is not defined, then a compilation error - /// will be emitted. To not emit a compile error, use the `option_env!` - /// macro instead. - /// - /// # Example - /// - /// ```rust - /// let path: &'static str = env!("PATH"); - /// println!("the $PATH variable at the time of compiling was: {}", path); - /// ``` - #[macro_export] - macro_rules! env { ($name:expr) => ({ /* compiler built-in */ }) } - - /// Optionally inspect an environment variable at compile time. - /// - /// If the named environment variable is present at compile time, this will - /// expand into an expression of type `Option<&'static str>` whose value is - /// `Some` of the value of the environment variable. If the environment - /// variable is not present, then this will expand to `None`. - /// - /// A compile time error is never emitted when using this macro regardless - /// of whether the environment variable is present or not. - /// - /// # Example - /// - /// ```rust - /// let key: Option<&'static str> = option_env!("SECRET_KEY"); - /// println!("the secret key might be: {}", key); - /// ``` - #[macro_export] - macro_rules! option_env { ($name:expr) => ({ /* compiler built-in */ }) } - - /// Concatenate literals into a static byte slice. - /// - /// This macro takes any number of comma-separated literal expressions, - /// yielding an expression of type `&'static [u8]` which is the - /// concatenation (left to right) of all the literals in their byte format. - /// - /// This extension currently only supports string literals, character - /// literals, and integers less than 256. The byte slice returned is the - /// utf8-encoding of strings and characters. - /// - /// # Example - /// - /// ``` - /// let rust = bytes!("r", 'u', "st", 255); - /// assert_eq!(rust[1], b'u'); - /// assert_eq!(rust[4], 255); - /// ``` - #[macro_export] - macro_rules! bytes { ($($e:expr),*) => ({ /* compiler built-in */ }) } - - /// Concatenate identifiers into one identifier. - /// - /// This macro takes any number of comma-separated identifiers, and - /// concatenates them all into one, yielding an expression which is a new - /// identifier. Note that hygiene makes it such that this macro cannot - /// capture local variables, and macros are only allowed in item, - /// statement or expression position, meaning this macro may be difficult to - /// use in some situations. - /// - /// # Example - /// - /// ``` - /// #![feature(concat_idents)] - /// - /// # fn main() { - /// fn foobar() -> int { 23 } - /// - /// let f = concat_idents!(foo, bar); - /// println!("{}", f()); - /// # } - /// ``` - #[macro_export] - macro_rules! concat_idents { - ($($e:ident),*) => ({ /* compiler built-in */ }) - } - - /// Concatenates literals into a static string slice. - /// - /// This macro takes any number of comma-separated literals, yielding an - /// expression of type `&'static str` which represents all of the literals - /// concatenated left-to-right. - /// - /// Integer and floating point literals are stringified in order to be - /// concatenated. - /// - /// # Example - /// - /// ``` - /// let s = concat!("test", 10i, 'b', true); - /// assert_eq!(s, "test10btrue"); - /// ``` - #[macro_export] - macro_rules! concat { ($($e:expr),*) => ({ /* compiler built-in */ }) } - - /// A macro which expands to the line number on which it was invoked. - /// - /// The expanded expression has type `uint`, and the returned line is not - /// the invocation of the `line!()` macro itself, but rather the first macro - /// invocation leading up to the invocation of the `line!()` macro. - /// - /// # Example - /// - /// ``` - /// let current_line = line!(); - /// println!("defined on line: {}", current_line); - /// ``` - #[macro_export] - macro_rules! line { () => ({ /* compiler built-in */ }) } - - /// A macro which expands to the column number on which it was invoked. - /// - /// The expanded expression has type `uint`, and the returned column is not - /// the invocation of the `column!()` macro itself, but rather the first macro - /// invocation leading up to the invocation of the `column!()` macro. - /// - /// # Example - /// - /// ``` - /// let current_col = column!(); - /// println!("defined on column: {}", current_col); - /// ``` - #[macro_export] - macro_rules! column { () => ({ /* compiler built-in */ }) } - - /// A macro which expands to the file name from which it was invoked. - /// - /// The expanded expression has type `&'static str`, and the returned file - /// is not the invocation of the `file!()` macro itself, but rather the - /// first macro invocation leading up to the invocation of the `file!()` - /// macro. - /// - /// # Example - /// - /// ``` - /// let this_file = file!(); - /// println!("defined in file: {}", this_file); - /// ``` - #[macro_export] - macro_rules! file { () => ({ /* compiler built-in */ }) } - - /// A macro which stringifies its argument. - /// - /// This macro will yield an expression of type `&'static str` which is the - /// stringification of all the tokens passed to the macro. No restrictions - /// are placed on the syntax of the macro invocation itself. - /// - /// # Example - /// - /// ``` - /// let one_plus_one = stringify!(1 + 1); - /// assert_eq!(one_plus_one, "1 + 1"); - /// ``` - #[macro_export] - macro_rules! stringify { ($t:tt) => ({ /* compiler built-in */ }) } - - /// Includes a utf8-encoded file as a string. - /// - /// This macro will yield an expression of type `&'static str` which is the - /// contents of the filename specified. The file is located relative to the - /// current file (similarly to how modules are found), - /// - /// # Example - /// - /// ```rust,ignore - /// let secret_key = include_str!("secret-key.ascii"); - /// ``` - #[macro_export] - macro_rules! include_str { ($file:expr) => ({ /* compiler built-in */ }) } - - /// Includes a file as a byte slice. - /// - /// This macro will yield an expression of type `&'static [u8]` which is - /// the contents of the filename specified. The file is located relative to - /// the current file (similarly to how modules are found), - /// - /// # Example - /// - /// ```rust,ignore - /// let secret_key = include_bytes!("secret-key.bin"); - /// ``` - #[macro_export] - macro_rules! include_bytes { ($file:expr) => ({ /* compiler built-in */ }) } - - /// Deprecated alias for `include_bytes!()`. - #[macro_export] - macro_rules! include_bin { ($file:expr) => ({ /* compiler built-in */}) } - - /// Expands to a string that represents the current module path. - /// - /// The current module path can be thought of as the hierarchy of modules - /// leading back up to the crate root. The first component of the path - /// returned is the name of the crate currently being compiled. - /// - /// # Example - /// - /// ```rust - /// mod test { - /// pub fn foo() { - /// assert!(module_path!().ends_with("test")); - /// } - /// } - /// - /// test::foo(); - /// ``` - #[macro_export] - macro_rules! module_path { () => ({ /* compiler built-in */ }) } - - /// Boolean evaluation of configuration flags. - /// - /// In addition to the `#[cfg]` attribute, this macro is provided to allow - /// boolean expression evaluation of configuration flags. This frequently - /// leads to less duplicated code. - /// - /// The syntax given to this macro is the same syntax as the `cfg` - /// attribute. - /// - /// # Example - /// - /// ```rust - /// let my_directory = if cfg!(windows) { - /// "windows-specific-directory" - /// } else { - /// "unix-directory" - /// }; - /// ``` - #[macro_export] - macro_rules! cfg { ($cfg:tt) => ({ /* compiler built-in */ }) } -} diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index e3402984ae5..f433cd1e664 100644 --- a/src/libstd/num/mod.rs +++ b/src/libstd/num/mod.rs @@ -19,7 +19,7 @@ #[cfg(test)] use fmt::Show; use ops::{Add, Sub, Mul, Div, Rem, Neg}; -use kinds::Copy; +use marker::Copy; use clone::Clone; use cmp::{PartialOrd, PartialEq}; diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 72ad16e0a5d..cef85c260a7 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -37,7 +37,7 @@ use error::{FromError, Error}; use fmt; use io::{IoResult, IoError}; use iter::{Iterator, IteratorExt}; -use kinds::Copy; +use marker::Copy; use libc::{c_void, c_int, c_char}; use libc; use boxed::Box; @@ -93,7 +93,7 @@ pub const TMPBUF_SZ : uint = 1000u; /// /// // 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()); +/// println!("The current directory is {:?}", current_working_directory.display()); /// ``` pub fn getcwd() -> IoResult<Path> { sys::os::getcwd() @@ -934,7 +934,7 @@ impl fmt::Show for MapError { impl Error for MapError { fn description(&self) -> &str { "memory map error" } - fn detail(&self) -> Option<String> { Some(self.to_string()) } + fn detail(&self) -> Option<String> { Some(format!("{:?}", self)) } } impl FromError<MapError> for Box<Error> { @@ -1622,7 +1622,7 @@ mod tests { os::MapOption::MapWritable ]) { Ok(chunk) => chunk, - Err(msg) => panic!("{}", msg) + Err(msg) => panic!("{:?}", msg) }; assert!(chunk.len >= 16); diff --git a/src/libstd/path/mod.rs b/src/libstd/path/mod.rs index b020164158c..581969e98fb 100644 --- a/src/libstd/path/mod.rs +++ b/src/libstd/path/mod.rs @@ -61,13 +61,14 @@ #![experimental] -use core::kinds::Sized; +use core::marker::Sized; use ffi::CString; use clone::Clone; use fmt; use iter::IteratorExt; use option::Option; use option::Option::{None, Some}; +use ops::{FullRange, Index}; use str; use str::StrExt; use string::{String, CowString}; @@ -351,7 +352,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe { match name.rposition_elem(&dot) { None | Some(0) => name, Some(1) if name == b".." => name, - Some(pos) => name[..pos] + Some(pos) => name.index(&(0..pos)) } }) } @@ -398,7 +399,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe { match name.rposition_elem(&dot) { None | Some(0) => None, Some(1) if name == b".." => None, - Some(pos) => Some(name[pos+1..]) + Some(pos) => Some(name.index(&((pos+1)..))) } } } @@ -459,7 +460,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// # #[cfg(unix)] fn foo() { /// let mut p = Path::new("abc/def.txt"); /// p.set_extension("csv"); - /// assert!(p == Path::new("abc/def.csv")); + /// assert_eq!(p, Path::new("abc/def.csv")); /// # } /// ``` /// @@ -474,7 +475,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe { let extlen = extension.container_as_bytes().len(); match (name.rposition_elem(&dot), extlen) { (None, 0) | (Some(0), 0) => None, - (Some(idx), 0) => Some(name[..idx].to_vec()), + (Some(idx), 0) => Some(name.index(&(0..idx)).to_vec()), (idx, extlen) => { let idx = match idx { None | Some(0) => name.len(), @@ -483,7 +484,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe { let mut v; v = Vec::with_capacity(idx + extlen + 1); - v.push_all(name[..idx]); + v.push_all(name.index(&(0..idx))); v.push(dot); v.push_all(extension.container_as_bytes()); Some(v) @@ -508,7 +509,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { /// let mut p = Path::new("abc/def.txt"); - /// assert!(p.with_filename("foo.dat") == Path::new("abc/foo.dat")); + /// assert_eq!(p.with_filename("foo.dat"), Path::new("abc/foo.dat")); /// # } /// ``` /// @@ -533,7 +534,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { /// let mut p = Path::new("abc/def.txt"); - /// assert!(p.with_extension("csv") == Path::new("abc/def.csv")); + /// assert_eq!(p.with_extension("csv"), Path::new("abc/def.csv")); /// # } /// ``` /// @@ -557,7 +558,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { /// let p = Path::new("abc/def/ghi"); - /// assert!(p.dir_path() == Path::new("abc/def")); + /// assert_eq!(p.dir_path(), Path::new("abc/def")); /// # } /// ``` fn dir_path(&self) -> Self { @@ -575,8 +576,8 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { - /// assert!(Path::new("abc/def").root_path() == None); - /// assert!(Path::new("/abc/def").root_path() == Some(Path::new("/"))); + /// assert_eq!(Path::new("abc/def").root_path(), None); + /// assert_eq!(Path::new("/abc/def").root_path(), Some(Path::new("/"))); /// # } /// ``` fn root_path(&self) -> Option<Self>; @@ -592,7 +593,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// # #[cfg(unix)] fn foo() { /// let mut p = Path::new("foo/bar"); /// p.push("baz.txt"); - /// assert!(p == Path::new("foo/bar/baz.txt")); + /// assert_eq!(p, Path::new("foo/bar/baz.txt")); /// # } /// ``` /// @@ -616,7 +617,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// # #[cfg(unix)] fn foo() { /// let mut p = Path::new("foo"); /// p.push_many(&["bar", "baz.txt"]); - /// assert!(p == Path::new("foo/bar/baz.txt")); + /// assert_eq!(p, Path::new("foo/bar/baz.txt")); /// # } /// ``` #[inline] @@ -645,7 +646,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// # #[cfg(unix)] fn foo() { /// let mut p = Path::new("foo/bar/baz.txt"); /// p.pop(); - /// assert!(p == Path::new("foo/bar")); + /// assert_eq!(p, Path::new("foo/bar")); /// # } /// ``` fn pop(&mut self) -> bool; @@ -661,7 +662,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { /// let p = Path::new("/foo"); - /// assert!(p.join("bar.txt") == Path::new("/foo/bar.txt")); + /// assert_eq!(p.join("bar.txt"), Path::new("/foo/bar.txt")); /// # } /// ``` /// @@ -687,7 +688,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// # #[cfg(unix)] fn foo() { /// let p = Path::new("foo"); /// let fbbq = Path::new("foo/bar/baz/quux.txt"); - /// assert!(p.join_many(&["bar", "baz", "quux.txt"]) == fbbq); + /// assert_eq!(p.join_many(&["bar", "baz", "quux.txt"]), fbbq); /// # } /// ``` #[inline] @@ -764,7 +765,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// let p = Path::new("foo/bar/baz/quux.txt"); /// let fb = Path::new("foo/bar"); /// let bq = Path::new("baz/quux.txt"); - /// assert!(p.path_relative_from(&fb) == Some(bq)); + /// assert_eq!(p.path_relative_from(&fb), Some(bq)); /// # } /// ``` fn path_relative_from(&self, base: &Self) -> Option<Self>; @@ -822,8 +823,15 @@ pub struct Display<'a, P:'a> { filename: bool } +//NOTE(stage0): replace with deriving(Show) after snapshot impl<'a, P: GenericPath> fmt::Show for Display<'a, P> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::String::fmt(self, f) + } +} + +impl<'a, P: GenericPath> fmt::String for Display<'a, P> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.as_cow().fmt(f) } } @@ -869,7 +877,7 @@ impl BytesContainer for String { } #[inline] fn container_as_str(&self) -> Option<&str> { - Some(self[]) + Some(self.index(&FullRange)) } #[inline] fn is_str(_: Option<&String>) -> bool { true } @@ -885,7 +893,7 @@ impl BytesContainer for [u8] { impl BytesContainer for Vec<u8> { #[inline] fn container_as_bytes(&self) -> &[u8] { - self[] + self.index(&FullRange) } } diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs index d9981ace030..0b7dc19fcab 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -12,11 +12,13 @@ use clone::Clone; use cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd}; +use fmt; use hash; use io::Writer; use iter::{AdditiveIterator, Extend}; use iter::{Iterator, IteratorExt, Map}; -use kinds::Sized; +use ops::Index; +use marker::Sized; use option::Option::{self, Some, None}; use slice::{AsSlice, Split, SliceExt, SliceConcatExt}; use str::{self, FromStr, StrExt}; @@ -56,6 +58,12 @@ pub fn is_sep(c: char) -> bool { c == SEP } +impl fmt::Show for Path { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Path {{ {} }}", self.display()) + } +} + impl PartialEq for Path { #[inline] fn eq(&self, other: &Path) -> bool { @@ -119,7 +127,7 @@ impl GenericPathUnsafe for Path { None => { self.repr = Path::normalize(filename); } - Some(idx) if self.repr[idx+1..] == b".." => { + Some(idx) if self.repr.index(&((idx+1)..)) == b".." => { let mut v = Vec::with_capacity(self.repr.len() + 1 + filename.len()); v.push_all(self.repr.as_slice()); v.push(SEP_BYTE); @@ -129,7 +137,7 @@ impl GenericPathUnsafe for Path { } Some(idx) => { let mut v = Vec::with_capacity(idx + 1 + filename.len()); - v.push_all(self.repr[..idx+1]); + v.push_all(self.repr.index(&(0..(idx+1)))); v.push_all(filename); // FIXME: this is slow self.repr = Path::normalize(v.as_slice()); @@ -170,9 +178,9 @@ impl GenericPath for Path { match self.sepidx { None if b".." == self.repr => self.repr.as_slice(), None => dot_static, - Some(0) => self.repr[..1], - Some(idx) if self.repr[idx+1..] == b".." => self.repr.as_slice(), - Some(idx) => self.repr[..idx] + Some(0) => self.repr.index(&(0..1)), + Some(idx) if self.repr.index(&((idx+1)..)) == b".." => self.repr.as_slice(), + Some(idx) => self.repr.index(&(0..idx)) } } @@ -181,9 +189,9 @@ impl GenericPath for Path { None if b"." == self.repr || b".." == self.repr => None, None => Some(self.repr.as_slice()), - Some(idx) if self.repr[idx+1..] == b".." => None, - Some(0) if self.repr[1..].is_empty() => None, - Some(idx) => Some(self.repr[idx+1..]) + Some(idx) if self.repr.index(&((idx+1)..)) == b".." => None, + Some(0) if self.repr.index(&(1..)).is_empty() => None, + Some(idx) => Some(self.repr.index(&((idx+1)..))) } } @@ -325,7 +333,7 @@ impl Path { // 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 v_ = if is_abs { v.as_slice().index(&(1..)) } else { v.as_slice() }; let comps = normalize_helper(v_, is_abs); match comps { None => None, @@ -364,7 +372,7 @@ impl Path { /// A path of "/" yields no components. A path of "." yields one component. pub fn components<'a>(&'a self) -> Components<'a> { let v = if self.repr[0] == SEP_BYTE { - self.repr[1..] + self.repr.index(&(1..)) } else { self.repr.as_slice() }; let is_sep_byte: fn(&u8) -> bool = is_sep_byte; // coerce to fn ptr let mut ret = v.split(is_sep_byte); @@ -438,13 +446,13 @@ mod tests { (s: $path:expr, $exp:expr) => ( { let path = $path; - assert!(path.as_str() == Some($exp)); + assert_eq!(path.as_str(), Some($exp)); } ); (v: $path:expr, $exp:expr) => ( { let path = $path; - assert!(path.as_vec() == $exp); + assert_eq!(path.as_vec(), $exp); } ) } @@ -458,7 +466,7 @@ mod tests { t!(v: Path::new(b"a/b/c\xFF"), b"a/b/c\xFF"); t!(v: Path::new(b"\xFF/../foo\x80"), b"foo\x80"); let p = Path::new(b"a/b/c\xFF"); - assert!(p.as_str() == None); + assert!(p.as_str().is_none()); t!(s: Path::new(""), "."); t!(s: Path::new("/"), "/"); @@ -488,31 +496,31 @@ mod tests { b"/bar"); let p = Path::new(b"foo/bar\x80"); - assert!(p.as_str() == None); + assert!(p.as_str().is_none()); } #[test] fn test_opt_paths() { - assert!(Path::new_opt(b"foo/bar\0") == None); + assert!(Path::new_opt(b"foo/bar\0").is_none()); t!(v: Path::new_opt(b"foo/bar").unwrap(), b"foo/bar"); - assert!(Path::new_opt("foo/bar\0") == None); + assert!(Path::new_opt("foo/bar\0").is_none()); t!(s: Path::new_opt("foo/bar").unwrap(), "foo/bar"); } #[test] fn test_null_byte() { use thread::Thread; - let result = Thread::spawn(move|| { + let result = Thread::scoped(move|| { Path::new(b"foo/bar\0") }).join(); assert!(result.is_err()); - let result = Thread::spawn(move|| { + let result = Thread::scoped(move|| { Path::new("test").set_filename(b"f\0o") }).join(); assert!(result.is_err()); - let result = Thread::spawn(move|| { + let result = Thread::scoped(move|| { Path::new("test").push(b"f\0o"); }).join(); assert!(result.is_err()); @@ -524,7 +532,7 @@ mod tests { ($path:expr, $disp:ident, $exp:expr) => ( { let path = Path::new($path); - assert!(path.$disp().to_string() == $exp); + assert_eq!(path.$disp().to_string(), $exp); } ) } @@ -540,14 +548,14 @@ mod tests { { let path = Path::new($path); let mo = path.display().as_cow(); - assert!(mo.as_slice() == $exp); + assert_eq!(mo.as_slice(), $exp); } ); ($path:expr, $exp:expr, filename) => ( { let path = Path::new($path); let mo = path.filename_display().as_cow(); - assert!(mo.as_slice() == $exp); + assert_eq!(mo.as_slice(), $exp); } ) } @@ -567,9 +575,9 @@ mod tests { { let path = Path::new($path); let f = format!("{}", path.display()); - assert!(f == $exp); + assert_eq!(f, $exp); let f = format!("{}", path.filename_display()); - assert!(f == $expf); + assert_eq!(f, $expf); } ) } @@ -589,21 +597,21 @@ mod tests { (s: $path:expr, $op:ident, $exp:expr) => ( { let path = Path::new($path); - assert!(path.$op() == ($exp).as_bytes()); + assert_eq!(path.$op(), ($exp).as_bytes()); } ); (s: $path:expr, $op:ident, $exp:expr, opt) => ( { let path = Path::new($path); let left = path.$op().map(|x| str::from_utf8(x).unwrap()); - assert!(left == $exp); + assert_eq!(left, $exp); } ); (v: $path:expr, $op:ident, $exp:expr) => ( { let arg = $path; let path = Path::new(arg); - assert!(path.$op() == $exp); + assert_eq!(path.$op(), $exp); } ); } @@ -677,7 +685,7 @@ mod tests { let mut p1 = Path::new(path); let p2 = p1.clone(); p1.push(join); - assert!(p1 == p2.join(join)); + assert_eq!(p1, p2.join(join)); } ) } @@ -696,7 +704,7 @@ mod tests { let mut p = Path::new($path); let push = Path::new($push); p.push(&push); - assert!(p.as_str() == Some($exp)); + assert_eq!(p.as_str(), Some($exp)); } ) } @@ -716,14 +724,14 @@ mod tests { { let mut p = Path::new($path); p.push_many(&$push); - assert!(p.as_str() == Some($exp)); + assert_eq!(p.as_str(), Some($exp)); } ); (v: $path:expr, $push:expr, $exp:expr) => ( { let mut p = Path::new($path); p.push_many(&$push); - assert!(p.as_vec() == $exp); + assert_eq!(p.as_vec(), $exp); } ) } @@ -744,16 +752,16 @@ mod tests { { let mut p = Path::new($path); let result = p.pop(); - assert!(p.as_str() == Some($left)); - assert!(result == $right); + assert_eq!(p.as_str(), Some($left)); + assert_eq!(result, $right); } ); (b: $path:expr, $left:expr, $right:expr) => ( { let mut p = Path::new($path); let result = p.pop(); - assert!(p.as_vec() == $left); - assert!(result == $right); + assert_eq!(p.as_vec(), $left); + assert_eq!(result, $right); } ) } @@ -776,8 +784,8 @@ mod tests { #[test] fn test_root_path() { - assert!(Path::new(b"a/b/c").root_path() == None); - assert!(Path::new(b"/a/b/c").root_path() == Some(Path::new("/"))); + assert_eq!(Path::new(b"a/b/c").root_path(), None); + assert_eq!(Path::new(b"/a/b/c").root_path(), Some(Path::new("/"))); } #[test] @@ -801,7 +809,7 @@ mod tests { let path = Path::new($path); let join = Path::new($join); let res = path.join(&join); - assert!(res.as_str() == Some($exp)); + assert_eq!(res.as_str(), Some($exp)); } ) } @@ -821,14 +829,14 @@ mod tests { { let path = Path::new($path); let res = path.join_many(&$join); - assert!(res.as_str() == Some($exp)); + assert_eq!(res.as_str(), Some($exp)); } ); (v: $path:expr, $join:expr, $exp:expr) => ( { let path = Path::new($path); let res = path.join_many(&$join); - assert!(res.as_vec() == $exp); + assert_eq!(res.as_vec(), $exp); } ) } @@ -902,7 +910,7 @@ mod tests { let mut p1 = Path::new(path); p1.$set(arg); let p2 = Path::new(path); - assert!(p1 == p2.$with(arg)); + assert_eq!(p1, p2.$with(arg)); } ); (v: $path:expr, $set:ident, $with:ident, $arg:expr) => ( @@ -912,7 +920,7 @@ mod tests { let mut p1 = Path::new(path); p1.$set(arg); let p2 = Path::new(path); - assert!(p1 == p2.$with(arg)); + assert_eq!(p1, p2.$with(arg)); } ) } @@ -942,31 +950,19 @@ mod tests { (s: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => ( { let path = $path; - let filename = $filename; - assert!(path.filename_str() == filename, - "{}.filename_str(): Expected `{}`, found {}", - path.as_str().unwrap(), filename, path.filename_str()); - let dirname = $dirname; - assert!(path.dirname_str() == dirname, - "`{}`.dirname_str(): Expected `{}`, found `{}`", - path.as_str().unwrap(), dirname, path.dirname_str()); - let filestem = $filestem; - assert!(path.filestem_str() == filestem, - "`{}`.filestem_str(): Expected `{}`, found `{}`", - path.as_str().unwrap(), filestem, path.filestem_str()); - let ext = $ext; - assert!(path.extension_str() == ext, - "`{}`.extension_str(): Expected `{}`, found `{}`", - path.as_str().unwrap(), ext, path.extension_str()); - } + assert_eq!(path.filename_str(), $filename); + assert_eq!(path.dirname_str(), $dirname); + assert_eq!(path.filestem_str(), $filestem); + assert_eq!(path.extension_str(), $ext); + } ); (v: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => ( { let path = $path; - assert!(path.filename() == $filename); - assert!(path.dirname() == $dirname); - assert!(path.filestem() == $filestem); - assert!(path.extension() == $ext); + assert_eq!(path.filename(), $filename); + assert_eq!(path.dirname(), $dirname); + assert_eq!(path.filestem(), $filestem); + assert_eq!(path.extension(), $ext); } ) } @@ -1154,12 +1150,10 @@ mod tests { let comps = path.components().collect::<Vec<&[u8]>>(); let exp: &[&str] = &$exp; let exps = exp.iter().map(|x| x.as_bytes()).collect::<Vec<&[u8]>>(); - assert!(comps == exps, "components: Expected {}, found {}", - comps, exps); + assert_eq!(comps, exps); let comps = path.components().rev().collect::<Vec<&[u8]>>(); let exps = exps.into_iter().rev().collect::<Vec<&[u8]>>(); - assert!(comps == exps, "rev_components: Expected {}, found {}", - comps, exps); + assert_eq!(comps, exps); } ); (b: $arg:expr, [$($exp:expr),*]) => ( diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index 4b5d793355b..5c4e7aa9ac2 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -18,12 +18,14 @@ use ascii::AsciiExt; use char::CharExt; use clone::Clone; use cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd}; +use fmt; use hash; use io::Writer; use iter::{AdditiveIterator, Extend}; use iter::{Iterator, IteratorExt, Map, repeat}; use mem; use option::Option::{self, Some, None}; +use ops::{FullRange, Index}; use slice::{SliceExt, SliceConcatExt}; use str::{SplitTerminator, FromStr, StrExt}; use string::{String, ToString}; @@ -83,6 +85,12 @@ pub struct Path { sepidx: Option<uint> // index of the final separator in the non-prefix portion of repr } +impl fmt::Show for Path { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Path {{ {} }}", self.display()) + } +} + impl PartialEq for Path { #[inline] fn eq(&self, other: &Path) -> bool { @@ -165,30 +173,30 @@ impl GenericPathUnsafe for Path { s.push_str(".."); s.push(SEP); s.push_str(filename); - self.update_normalized(s[]); + self.update_normalized(s.index(&FullRange)); } None => { self.update_normalized(filename); } - Some((_,idxa,end)) if self.repr[idxa..end] == ".." => { + Some((_,idxa,end)) if self.repr.index(&(idxa..end)) == ".." => { let mut s = String::with_capacity(end + 1 + filename.len()); - s.push_str(self.repr[0..end]); + s.push_str(self.repr.index(&(0..end))); s.push(SEP); s.push_str(filename); - self.update_normalized(s[]); + self.update_normalized(s.index(&FullRange)); } Some((idxb,idxa,_)) if self.prefix == Some(DiskPrefix) && idxa == self.prefix_len() => { let mut s = String::with_capacity(idxb + filename.len()); - s.push_str(self.repr[0..idxb]); + s.push_str(self.repr.index(&(0..idxb))); s.push_str(filename); - self.update_normalized(s[]); + self.update_normalized(s.index(&FullRange)); } Some((idxb,_,_)) => { let mut s = String::with_capacity(idxb + 1 + filename.len()); - s.push_str(self.repr[0..idxb]); + s.push_str(self.repr.index(&(0..idxb))); s.push(SEP); s.push_str(filename); - self.update_normalized(s[]); + self.update_normalized(s.index(&FullRange)); } } } @@ -207,12 +215,12 @@ impl GenericPathUnsafe for Path { let path = path.container_as_str().unwrap(); fn is_vol_abs(path: &str, prefix: Option<PathPrefix>) -> bool { // assume prefix is Some(DiskPrefix) - let rest = path[prefix_len(prefix)..]; + let rest = path.index(&(prefix_len(prefix)..)); !rest.is_empty() && rest.as_bytes()[0].is_ascii() && is_sep(rest.as_bytes()[0] as char) } fn shares_volume(me: &Path, path: &str) -> bool { // path is assumed to have a prefix of Some(DiskPrefix) - let repr = me.repr[]; + let repr = me.repr.index(&FullRange); match me.prefix { Some(DiskPrefix) => { repr.as_bytes()[0] == path.as_bytes()[0].to_ascii_uppercase() @@ -244,7 +252,7 @@ impl GenericPathUnsafe for Path { else { None }; let pathlen = path_.as_ref().map_or(path.len(), |p| p.len()); let mut s = String::with_capacity(me.repr.len() + 1 + pathlen); - s.push_str(me.repr[]); + s.push_str(me.repr.index(&FullRange)); let plen = me.prefix_len(); // if me is "C:" we don't want to add a path separator match me.prefix { @@ -256,9 +264,9 @@ impl GenericPathUnsafe for Path { } match path_ { None => s.push_str(path), - Some(p) => s.push_str(p[]), + Some(p) => s.push_str(p.index(&FullRange)), }; - me.update_normalized(s[]) + me.update_normalized(s.index(&FullRange)) } if !path.is_empty() { @@ -266,7 +274,7 @@ impl GenericPathUnsafe for Path { match prefix { Some(DiskPrefix) if !is_vol_abs(path, prefix) && shares_volume(self, path) => { // cwd-relative path, self is on the same volume - append_path(self, path[prefix_len(prefix)..]); + append_path(self, path.index(&(prefix_len(prefix)..))); } Some(_) => { // absolute path, or cwd-relative and self is not same volume @@ -312,7 +320,7 @@ impl GenericPath for Path { /// Always returns a `Some` value. #[inline] fn as_str<'a>(&'a self) -> Option<&'a str> { - Some(self.repr[]) + Some(self.repr.index(&FullRange)) } #[inline] @@ -334,17 +342,21 @@ impl GenericPath for Path { /// Always returns a `Some` value. fn dirname_str<'a>(&'a self) -> Option<&'a str> { Some(match self.sepidx_or_prefix_len() { - None if ".." == self.repr => self.repr[], + None if ".." == self.repr => self.repr.index(&FullRange), None => ".", - Some((_,idxa,end)) if self.repr[idxa..end] == ".." => self.repr[], - Some((idxb,_,end)) if self.repr[idxb..end] == "\\" => self.repr[], - Some((0,idxa,_)) => self.repr[0..idxa], + Some((_,idxa,end)) if self.repr.index(&(idxa..end)) == ".." => { + self.repr.index(&FullRange) + } + Some((idxb,_,end)) if self.repr.index(&(idxb..end)) == "\\" => { + self.repr.index(&FullRange) + } + Some((0,idxa,_)) => self.repr.index(&(0..idxa)), Some((idxb,idxa,_)) => { match self.prefix { Some(DiskPrefix) | Some(VerbatimDiskPrefix) if idxb == self.prefix_len() => { - self.repr[0..idxa] + self.repr.index(&(0..idxa)) } - _ => self.repr[0..idxb] + _ => self.repr.index(&(0..idxb)) } } }) @@ -358,13 +370,13 @@ impl GenericPath for Path { /// See `GenericPath::filename_str` for info. /// Always returns a `Some` value if `filename` returns a `Some` value. fn filename_str<'a>(&'a self) -> Option<&'a str> { - let repr = self.repr[]; + let repr = self.repr.index(&FullRange); match self.sepidx_or_prefix_len() { None if "." == repr || ".." == repr => None, None => Some(repr), - Some((_,idxa,end)) if repr[idxa..end] == ".." => None, + Some((_,idxa,end)) if repr.index(&(idxa..end)) == ".." => None, Some((_,idxa,end)) if idxa == end => None, - Some((_,idxa,end)) => Some(repr[idxa..end]) + Some((_,idxa,end)) => Some(repr.index(&(idxa..end))) } } @@ -396,7 +408,7 @@ impl GenericPath for Path { true } Some((idxb,idxa,end)) if idxb == idxa && idxb == end => false, - Some((idxb,_,end)) if self.repr[idxb..end] == "\\" => false, + Some((idxb,_,end)) if self.repr.index(&(idxb..end)) == "\\" => false, Some((idxb,idxa,_)) => { let trunc = match self.prefix { Some(DiskPrefix) | Some(VerbatimDiskPrefix) | None => { @@ -416,15 +428,15 @@ impl GenericPath for Path { if self.prefix.is_some() { Some(Path::new(match self.prefix { Some(DiskPrefix) if self.is_absolute() => { - self.repr[0..self.prefix_len()+1] + self.repr.index(&(0..(self.prefix_len()+1))) } Some(VerbatimDiskPrefix) => { - self.repr[0..self.prefix_len()+1] + self.repr.index(&(0..(self.prefix_len()+1))) } - _ => self.repr[0..self.prefix_len()] + _ => self.repr.index(&(0..self.prefix_len())) })) } else if is_vol_relative(self) { - Some(Path::new(self.repr[0..1])) + Some(Path::new(self.repr.index(&(0..1)))) } else { None } @@ -443,7 +455,7 @@ impl GenericPath for Path { fn is_absolute(&self) -> bool { match self.prefix { Some(DiskPrefix) => { - let rest = self.repr[self.prefix_len()..]; + let rest = self.repr.index(&(self.prefix_len()..)); rest.len() > 0 && rest.as_bytes()[0] == SEP_BYTE } Some(_) => true, @@ -618,15 +630,15 @@ impl Path { /// Does not distinguish between absolute and cwd-relative paths, e.g. /// C:\foo and C:foo. pub fn str_components<'a>(&'a self) -> StrComponents<'a> { - let repr = self.repr[]; + let repr = self.repr.index(&FullRange); let s = match self.prefix { Some(_) => { let plen = self.prefix_len(); if repr.len() > plen && repr.as_bytes()[plen] == SEP_BYTE { - repr[plen+1..] - } else { repr[plen..] } + repr.index(&((plen+1)..)) + } else { repr.index(&(plen..)) } } - None if repr.as_bytes()[0] == SEP_BYTE => repr[1..], + None if repr.as_bytes()[0] == SEP_BYTE => repr.index(&(1..)), None => repr }; let some: fn(&'a str) -> Option<&'a str> = Some; // coerce to fn ptr @@ -646,8 +658,8 @@ impl Path { } fn equiv_prefix(&self, other: &Path) -> bool { - let s_repr = self.repr[]; - let o_repr = other.repr[]; + let s_repr = self.repr.index(&FullRange); + let o_repr = other.repr.index(&FullRange); match (self.prefix, other.prefix) { (Some(DiskPrefix), Some(VerbatimDiskPrefix)) => { self.is_absolute() && @@ -664,14 +676,14 @@ impl Path { o_repr.as_bytes()[4].to_ascii_lowercase() } (Some(UNCPrefix(_,_)), Some(VerbatimUNCPrefix(_,_))) => { - s_repr[2..self.prefix_len()] == o_repr[8..other.prefix_len()] + s_repr.index(&(2..self.prefix_len())) == o_repr.index(&(8..other.prefix_len())) } (Some(VerbatimUNCPrefix(_,_)), Some(UNCPrefix(_,_))) => { - s_repr[8..self.prefix_len()] == o_repr[2..other.prefix_len()] + s_repr.index(&(8..self.prefix_len())) == o_repr.index(&(2..other.prefix_len())) } (None, None) => true, (a, b) if a == b => { - s_repr[0..self.prefix_len()] == o_repr[0..other.prefix_len()] + s_repr.index(&(0..self.prefix_len())) == o_repr.index(&(0..other.prefix_len())) } _ => false } @@ -725,7 +737,7 @@ impl Path { match prefix.unwrap() { DiskPrefix => { let len = prefix_len(prefix) + is_abs as uint; - let mut s = String::from_str(s[0..len]); + let mut s = String::from_str(s.index(&(0..len))); unsafe { let v = s.as_mut_vec(); v[0] = (*v)[0].to_ascii_uppercase(); @@ -740,7 +752,7 @@ impl Path { } VerbatimDiskPrefix => { let len = prefix_len(prefix) + is_abs as uint; - let mut s = String::from_str(s[0..len]); + let mut s = String::from_str(s.index(&(0..len))); unsafe { let v = s.as_mut_vec(); v[4] = (*v)[4].to_ascii_uppercase(); @@ -750,14 +762,14 @@ impl Path { _ => { let plen = prefix_len(prefix); if s.len() > plen { - Some(String::from_str(s[0..plen])) + Some(String::from_str(s.index(&(0..plen)))) } else { None } } } } else if is_abs && comps.is_empty() { Some(repeat(SEP).take(1).collect()) } else { - let prefix_ = s[0..prefix_len(prefix)]; + let prefix_ = s.index(&(0..prefix_len(prefix))); let n = prefix_.len() + if is_abs { comps.len() } else { comps.len() - 1} + comps.iter().map(|v| v.len()).sum(); @@ -768,15 +780,15 @@ impl Path { s.push(':'); } Some(VerbatimDiskPrefix) => { - s.push_str(prefix_[0..4]); + s.push_str(prefix_.index(&(0..4))); s.push(prefix_.as_bytes()[4].to_ascii_uppercase() as char); - s.push_str(prefix_[5..]); + s.push_str(prefix_.index(&(5..))); } Some(UNCPrefix(a,b)) => { s.push_str("\\\\"); - s.push_str(prefix_[2..a+2]); + s.push_str(prefix_.index(&(2..(a+2)))); s.push(SEP); - s.push_str(prefix_[3+a..3+a+b]); + s.push_str(prefix_.index(&((3+a)..(3+a+b)))); } Some(_) => s.push_str(prefix_), None => () @@ -801,8 +813,8 @@ impl Path { fn update_sepidx(&mut self) { let s = if self.has_nonsemantic_trailing_slash() { - self.repr[0..self.repr.len()-1] - } else { self.repr[] }; + self.repr.index(&(0..(self.repr.len()-1))) + } else { self.repr.index(&FullRange) }; let sep_test: fn(char) -> bool = if !prefix_is_verbatim(self.prefix) { is_sep } else { @@ -881,17 +893,17 @@ pub fn is_verbatim(path: &Path) -> bool { /// non-verbatim, the non-verbatim version is returned. /// Otherwise, None is returned. pub fn make_non_verbatim(path: &Path) -> Option<Path> { - let repr = path.repr[]; + let repr = path.repr.index(&FullRange); let new_path = match path.prefix { Some(VerbatimPrefix(_)) | Some(DeviceNSPrefix(_)) => return None, Some(UNCPrefix(_,_)) | Some(DiskPrefix) | None => return Some(path.clone()), Some(VerbatimDiskPrefix) => { // \\?\D:\ - Path::new(repr[4..]) + Path::new(repr.index(&(4..))) } Some(VerbatimUNCPrefix(_,_)) => { // \\?\UNC\server\share - Path::new(format!(r"\{}", repr[7..])) + Path::new(format!(r"\{}", repr.index(&(7..)))) } }; if new_path.prefix.is_none() { @@ -900,8 +912,8 @@ pub fn make_non_verbatim(path: &Path) -> Option<Path> { return None; } // now ensure normalization didn't change anything - if repr[path.prefix_len()..] == - new_path.repr[new_path.prefix_len()..] { + if repr.index(&(path.prefix_len()..)) == + new_path.repr.index(&(new_path.prefix_len()..)) { Some(new_path) } else { None @@ -966,13 +978,13 @@ pub enum PathPrefix { fn parse_prefix<'a>(mut path: &'a str) -> Option<PathPrefix> { if path.starts_with("\\\\") { // \\ - path = path[2..]; + path = path.index(&(2..)); if path.starts_with("?\\") { // \\?\ - path = path[2..]; + path = path.index(&(2..)); if path.starts_with("UNC\\") { // \\?\UNC\server\share - path = path[4..]; + path = path.index(&(4..)); let (idx_a, idx_b) = match parse_two_comps(path, is_sep_verbatim) { Some(x) => x, None => (path.len(), 0) @@ -993,7 +1005,7 @@ fn parse_prefix<'a>(mut path: &'a str) -> Option<PathPrefix> { } } else if path.starts_with(".\\") { // \\.\path - path = path[2..]; + path = path.index(&(2..)); let idx = path.find('\\').unwrap_or(path.len()); return Some(DeviceNSPrefix(idx)); } @@ -1018,7 +1030,7 @@ fn parse_prefix<'a>(mut path: &'a str) -> Option<PathPrefix> { None => return None, Some(x) => x }; - path = path[idx_a+1..]; + path = path.index(&((idx_a+1)..)); let idx_b = path.find(f).unwrap_or(path.len()); Some((idx_a, idx_b)) } @@ -1032,8 +1044,8 @@ fn normalize_helper<'a>(s: &'a str, prefix: Option<PathPrefix>) -> (bool, Option is_sep_verbatim }; let is_abs = s.len() > prefix_len(prefix) && f(s.char_at(prefix_len(prefix))); - let s_ = s[prefix_len(prefix)..]; - let s_ = if is_abs { s_[1..] } else { s_ }; + let s_ = s.index(&(prefix_len(prefix)..)); + let s_ = if is_abs { s_.index(&(1..)) } else { s_ }; if is_abs && s_.is_empty() { return (is_abs, match prefix { @@ -1114,13 +1126,13 @@ mod tests { (s: $path:expr, $exp:expr) => ( { let path = $path; - assert!(path.as_str() == Some($exp)); + assert_eq!(path.as_str(), Some($exp)); } ); (v: $path:expr, $exp:expr) => ( { let path = $path; - assert!(path.as_vec() == $exp); + assert_eq!(path.as_vec(), $exp); } ) } @@ -1133,8 +1145,7 @@ mod tests { let path = $path; let exp = $exp; let res = parse_prefix(path); - assert!(res == exp, - "parse_prefix(\"{}\"): expected {}, found {}", path, exp, res); + assert_eq!(res, exp); } ) } @@ -1287,17 +1298,17 @@ mod tests { #[test] fn test_null_byte() { use thread::Thread; - let result = Thread::spawn(move|| { + let result = Thread::scoped(move|| { Path::new(b"foo/bar\0") }).join(); assert!(result.is_err()); - let result = Thread::spawn(move|| { + let result = Thread::scoped(move|| { Path::new("test").set_filename(b"f\0o") }).join(); assert!(result.is_err()); - let result = Thread::spawn(move || { + let result = Thread::scoped(move || { Path::new("test").push(b"f\0o"); }).join(); assert!(result.is_err()); @@ -1350,7 +1361,7 @@ mod tests { { let path = $path; let path = Path::new(path); - assert!(path.$op() == Some($exp)); + assert_eq!(path.$op(), Some($exp)); } ); (s: $path:expr, $op:ident, $exp:expr, opt) => ( @@ -1358,14 +1369,14 @@ mod tests { let path = $path; let path = Path::new(path); let left = path.$op(); - assert!(left == $exp); + assert_eq!(left, $exp); } ); (v: $path:expr, $op:ident, $exp:expr) => ( { let path = $path; let path = Path::new(path); - assert!(path.$op() == $exp); + assert_eq!(path.$op(), $exp); } ) } @@ -1476,7 +1487,7 @@ mod tests { let mut p1 = Path::new(path); let p2 = p1.clone(); p1.push(join); - assert!(p1 == p2.join(join)); + assert_eq!(p1, p2.join(join)); } ) } @@ -1490,9 +1501,9 @@ mod tests { // we do want to check one odd case though to ensure the prefix is re-parsed let mut p = Path::new("\\\\?\\C:"); - assert!(prefix(&p) == Some(VerbatimPrefix(2))); + assert_eq!(prefix(&p), Some(VerbatimPrefix(2))); p.push("foo"); - assert!(prefix(&p) == Some(VerbatimDiskPrefix)); + assert_eq!(prefix(&p), Some(VerbatimDiskPrefix)); assert_eq!(p.as_str(), Some("\\\\?\\C:\\foo")); // and another with verbatim non-normalized paths @@ -1591,10 +1602,8 @@ mod tests { let mut p = Path::new(pstr); let result = p.pop(); let left = $left; - assert!(p.as_str() == Some(left), - "`{}`.pop() failed; expected remainder `{}`, found `{}`", - pstr, left, p.as_str().unwrap()); - assert!(result == $right); + assert_eq!(p.as_str(), Some(left)); + assert_eq!(result, $right); } ); (b: $path:expr, $left:expr, $right:expr) => ( @@ -1602,7 +1611,7 @@ mod tests { let mut p = Path::new($path); let result = p.pop(); assert_eq!(p.as_vec(), $left); - assert!(result == $right); + assert_eq!(result, $right); } ) } @@ -1645,16 +1654,16 @@ mod tests { #[test] fn test_root_path() { - assert!(Path::new("a\\b\\c").root_path() == None); - assert!(Path::new("\\a\\b\\c").root_path() == Some(Path::new("\\"))); - assert!(Path::new("C:a").root_path() == Some(Path::new("C:"))); - assert!(Path::new("C:\\a").root_path() == Some(Path::new("C:\\"))); - assert!(Path::new("\\\\a\\b\\c").root_path() == Some(Path::new("\\\\a\\b"))); - assert!(Path::new("\\\\?\\a\\b").root_path() == Some(Path::new("\\\\?\\a"))); - assert!(Path::new("\\\\?\\C:\\a").root_path() == Some(Path::new("\\\\?\\C:\\"))); - assert!(Path::new("\\\\?\\UNC\\a\\b\\c").root_path() == + assert_eq!(Path::new("a\\b\\c").root_path(), None); + assert_eq!(Path::new("\\a\\b\\c").root_path(), Some(Path::new("\\"))); + assert_eq!(Path::new("C:a").root_path(), Some(Path::new("C:"))); + assert_eq!(Path::new("C:\\a").root_path(), Some(Path::new("C:\\"))); + assert_eq!(Path::new("\\\\a\\b\\c").root_path(), Some(Path::new("\\\\a\\b"))); + assert_eq!(Path::new("\\\\?\\a\\b").root_path(), Some(Path::new("\\\\?\\a"))); + assert_eq!(Path::new("\\\\?\\C:\\a").root_path(), Some(Path::new("\\\\?\\C:\\"))); + assert_eq!(Path::new("\\\\?\\UNC\\a\\b\\c").root_path(), Some(Path::new("\\\\?\\UNC\\a\\b"))); - assert!(Path::new("\\\\.\\a\\b").root_path() == Some(Path::new("\\\\.\\a"))); + assert_eq!(Path::new("\\\\.\\a\\b").root_path(), Some(Path::new("\\\\.\\a"))); } #[test] @@ -1731,10 +1740,8 @@ mod tests { let path = Path::new(pstr); let arg = $arg; let res = path.$op(arg); - let exp = $res; - assert!(res.as_str() == Some(exp), - "`{}`.{}(\"{}\"): Expected `{}`, found `{}`", - pstr, stringify!($op), arg, exp, res.as_str().unwrap()); + let exp = Path::new($res); + assert_eq!(res, exp); } ) } @@ -1817,7 +1824,7 @@ mod tests { let mut p1 = Path::new(path); p1.$set(arg); let p2 = Path::new(path); - assert!(p1 == p2.$with(arg)); + assert_eq!(p1, p2.$with(arg)); } ); (v: $path:expr, $set:ident, $with:ident, $arg:expr) => ( @@ -1827,7 +1834,7 @@ mod tests { let mut p1 = Path::new(path); p1.$set(arg); let p2 = Path::new(path); - assert!(p1 == p2.$with(arg)); + assert_eq!(p1, p2.$with(arg)); } ) } @@ -1858,31 +1865,19 @@ mod tests { (s: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => ( { let path = $path; - let filename = $filename; - assert!(path.filename_str() == filename, - "`{}`.filename_str(): Expected `{}`, found `{}`", - path.as_str().unwrap(), filename, path.filename_str()); - let dirname = $dirname; - assert!(path.dirname_str() == dirname, - "`{}`.dirname_str(): Expected `{}`, found `{}`", - path.as_str().unwrap(), dirname, path.dirname_str()); - let filestem = $filestem; - assert!(path.filestem_str() == filestem, - "`{}`.filestem_str(): Expected `{}`, found `{}`", - path.as_str().unwrap(), filestem, path.filestem_str()); - let ext = $ext; - assert!(path.extension_str() == ext, - "`{}`.extension_str(): Expected `{}`, found `{}`", - path.as_str().unwrap(), ext, path.extension_str()); + assert_eq!(path.filename_str(), $filename); + assert_eq!(path.dirname_str(), $dirname); + assert_eq!(path.filestem_str(), $filestem); + assert_eq!(path.extension_str(), $ext); } ); (v: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => ( { let path = $path; - assert!(path.filename() == $filename); - assert!(path.dirname() == $dirname); - assert!(path.filestem() == $filestem); - assert!(path.extension() == $ext); + assert_eq!(path.filename(), $filename); + assert_eq!(path.dirname(), $dirname); + assert_eq!(path.filestem(), $filestem); + assert_eq!(path.extension(), $ext); } ) } @@ -1925,18 +1920,10 @@ mod tests { { let path = Path::new($path); let (abs, vol, cwd, rel) = ($abs, $vol, $cwd, $rel); - let b = path.is_absolute(); - assert!(b == abs, "Path '{}'.is_absolute(): expected {}, found {}", - path.as_str().unwrap(), abs, b); - let b = is_vol_relative(&path); - assert!(b == vol, "is_vol_relative('{}'): expected {}, found {}", - path.as_str().unwrap(), vol, b); - let b = is_cwd_relative(&path); - assert!(b == cwd, "is_cwd_relative('{}'): expected {}, found {}", - path.as_str().unwrap(), cwd, b); - let b = path.is_relative(); - assert!(b == rel, "Path '{}'.is_relativf(): expected {}, found {}", - path.as_str().unwrap(), rel, b); + assert_eq!(path.is_absolute(), abs); + assert_eq!(is_vol_relative(&path), vol); + assert_eq!(is_cwd_relative(&path), cwd); + assert_eq!(path.is_relative(), rel); } ) } @@ -1967,9 +1954,7 @@ mod tests { let dest = Path::new($dest); let exp = $exp; let res = path.is_ancestor_of(&dest); - assert!(res == exp, - "`{}`.is_ancestor_of(`{}`): Expected {}, found {}", - path.as_str().unwrap(), dest.as_str().unwrap(), exp, res); + assert_eq!(res, exp); } ) } @@ -2098,14 +2083,8 @@ mod tests { macro_rules! t { (s: $path:expr, $other:expr, $exp:expr) => ( { - let path = Path::new($path); - let other = Path::new($other); - let res = path.path_relative_from(&other); - let exp = $exp; - assert!(res.as_ref().and_then(|x| x.as_str()) == exp, - "`{}`.path_relative_from(`{}`): Expected {}, got {}", - path.as_str().unwrap(), other.as_str().unwrap(), exp, - res.as_ref().and_then(|x| x.as_str())); + assert_eq!(Path::new($path).path_relative_from(&Path::new($other)) + .as_ref().and_then(|x| x.as_str()), $exp); } ) } @@ -2314,7 +2293,7 @@ mod tests { let path = Path::new($path); let exp: Option<&str> = $exp; let exp = exp.map(|s| Path::new(s)); - assert!(make_non_verbatim(&path) == exp); + assert_eq!(make_non_verbatim(&path), exp); } ) } diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs index 9e9a483e1a5..dcb342b9ca2 100644 --- a/src/libstd/prelude/v1.rs +++ b/src/libstd/prelude/v1.rs @@ -13,9 +13,12 @@ #![stable] // Reexported core operators -#[stable] #[doc(no_inline)] pub use kinds::{Copy, Send, Sized, Sync}; +#[stable] #[doc(no_inline)] pub use marker::{Copy, Send, Sized, Sync}; #[stable] #[doc(no_inline)] pub use ops::{Drop, Fn, FnMut, FnOnce}; +// TEMPORARY +#[unstable] #[doc(no_inline)] pub use ops::{Index, IndexMut, FullRange}; + // Reexported functions #[stable] #[doc(no_inline)] pub use mem::drop; diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs index 8855a7e5293..d3e6cd166ec 100644 --- a/src/libstd/rand/mod.rs +++ b/src/libstd/rand/mod.rs @@ -71,7 +71,7 @@ //! use std::rand; //! //! let tuple = rand::random::<(f64, char)>(); -//! println!("{}", tuple) +//! println!("{:?}", tuple) //! ``` //! //! ## Monte Carlo estimation of π @@ -303,7 +303,7 @@ impl<'a> SeedableRng<&'a [uint]> for StdRng { pub fn weak_rng() -> XorShiftRng { match OsRng::new() { Ok(mut r) => r.gen(), - Err(e) => panic!("weak_rng: failed to create seeded RNG: {}", e) + Err(e) => panic!("weak_rng: failed to create seeded RNG: {:?}", e) } } @@ -490,7 +490,7 @@ mod test { let mut r = thread_rng(); let a = r.gen::<f64>(); let b = r.gen::<f64>(); - debug!("{}", (a, b)); + debug!("{:?}", (a, b)); } #[test] diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs index a79a6e35ebc..18d40ecd3eb 100644 --- a/src/libstd/rand/os.rs +++ b/src/libstd/rand/os.rs @@ -28,9 +28,6 @@ mod imp { use mem; use os::errno; - // NOTE: for old macros; remove after the next snapshot - #[cfg(stage0)] use result::Result::Err; - #[cfg(all(target_os = "linux", any(target_arch = "x86_64", target_arch = "x86", @@ -185,7 +182,7 @@ mod imp { extern crate libc; use io::{IoResult}; - use kinds::Sync; + use marker::Sync; use mem; use os; use rand::Rng; @@ -397,7 +394,7 @@ mod test { r.fill_bytes(&mut v); Thread::yield_now(); } - }).detach(); + }); } // start all the tasks diff --git a/src/libstd/rand/reader.rs b/src/libstd/rand/reader.rs index 48d7f2e7854..177b7380831 100644 --- a/src/libstd/rand/reader.rs +++ b/src/libstd/rand/reader.rs @@ -67,7 +67,7 @@ impl<R: Reader> Rng for ReaderRng<R> { if v.len() == 0 { return } match self.reader.read_at_least(v.len(), v) { Ok(_) => {} - Err(e) => panic!("ReaderRng.fill_bytes error: {}", e) + Err(e) => panic!("ReaderRng.fill_bytes error: {:?}", e) } } } diff --git a/src/libstd/rt/macros.rs b/src/libstd/rt/macros.rs index bbc96d0b19f..1e3ab6d34da 100644 --- a/src/libstd/rt/macros.rs +++ b/src/libstd/rt/macros.rs @@ -14,16 +14,24 @@ //! they aren't defined anywhere outside of the `rt` module. macro_rules! rterrln { - ($fmt:expr $($arg:tt)*) => ( { - ::rt::util::dumb_print(format_args!(concat!($fmt, "\n") $($arg)*)) + ($fmt:expr) => ( { + ::rt::util::dumb_print(format_args!(concat!($fmt, "\n"))) + } ); + ($fmt:expr, $($arg:expr),*) => ( { + ::rt::util::dumb_print(format_args!(concat!($fmt, "\n"), $($arg)*)) } ) } // Some basic logging. Enabled by passing `--cfg rtdebug` to the libstd build. macro_rules! rtdebug { - ($($arg:tt)*) => ( { + ($arg:expr) => ( { if cfg!(rtdebug) { - rterrln!($($arg)*) + rterrln!($arg) + } + } ); + ($str:expr, $($arg:expr),*) => ( { + if cfg!(rtdebug) { + rterrln!($str, $($arg)*) } }) } diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index e556888a470..5ef55f5b487 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -23,7 +23,7 @@ #![allow(dead_code)] -use kinds::Send; +use marker::Send; use ops::FnOnce; use sys; use thunk::Thunk; @@ -39,8 +39,7 @@ pub use alloc::heap; pub mod backtrace; // Internals -#[cfg_attr(stage0, macro_escape)] -#[cfg_attr(not(stage0), macro_use)] +#[macro_use] mod macros; // These should be refactored/moved/made private over time diff --git a/src/libstd/rt/unwind.rs b/src/libstd/rt/unwind.rs index 71169386c18..fd84f220942 100644 --- a/src/libstd/rt/unwind.rs +++ b/src/libstd/rt/unwind.rs @@ -544,7 +544,7 @@ fn begin_unwind_inner(msg: Box<Any + Send>, file_line: &(&'static str, uint)) -> // MAX_CALLBACKS, so we're sure to clamp it as necessary. let callbacks = { let amt = CALLBACK_CNT.load(Ordering::SeqCst); - CALLBACKS[..cmp::min(amt, MAX_CALLBACKS)] + CALLBACKS.index(&(0..cmp::min(amt, MAX_CALLBACKS))) }; for cb in callbacks.iter() { match cb.load(Ordering::SeqCst) { diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs index bc01ce926f8..59f654a95ca 100644 --- a/src/libstd/rt/util.rs +++ b/src/libstd/rt/util.rs @@ -131,7 +131,7 @@ pub fn abort(args: fmt::Arguments) -> ! { impl<'a> fmt::Writer for BufWriter<'a> { fn write_str(&mut self, bytes: &str) -> fmt::Result { let left = self.buf.slice_from_mut(self.pos); - let to_write = bytes.as_bytes()[..cmp::min(bytes.len(), left.len())]; + let to_write = bytes.as_bytes().index(&(0..cmp::min(bytes.len(), left.len()))); slice::bytes::copy_memory(left, to_write); self.pos += to_write.len(); Ok(()) @@ -142,7 +142,7 @@ pub fn abort(args: fmt::Arguments) -> ! { let mut msg = [0u8; 512]; let mut w = BufWriter { buf: &mut msg, pos: 0 }; let _ = write!(&mut w, "{}", args); - let msg = str::from_utf8(w.buf[mut ..w.pos]).unwrap_or("aborted"); + let msg = str::from_utf8(w.buf.index_mut(&(0..w.pos))).unwrap_or("aborted"); let msg = if msg.is_empty() {"aborted"} else {msg}; // Give some context to the message diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs index bf5da3e7cba..70939879400 100644 --- a/src/libstd/sync/barrier.rs +++ b/src/libstd/sync/barrier.rs @@ -26,7 +26,7 @@ use sync::{Mutex, Condvar}; /// println!("before wait"); /// c.wait(); /// println!("after wait"); -/// }).detach(); +/// }); /// } /// ``` #[stable] @@ -126,7 +126,7 @@ mod tests { let tx = tx.clone(); Thread::spawn(move|| { tx.send(c.wait().is_leader()).unwrap(); - }).detach(); + }); } // At this point, all spawned tasks should be blocked, diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index e97be51fdbc..3c0ae71255d 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -48,7 +48,7 @@ use sync::{mutex, MutexGuard}; /// let mut started = lock.lock().unwrap(); /// *started = true; /// cvar.notify_one(); -/// }).detach(); +/// }); /// /// // wait for the thread to start up /// let &(ref lock, ref cvar) = &*pair; @@ -338,7 +338,7 @@ mod tests { cnt = cond.wait(cnt).unwrap(); } tx.send(()).unwrap(); - }).detach(); + }); } drop(tx); diff --git a/src/libstd/sync/future.rs b/src/libstd/sync/future.rs index 4c6adcc04f6..568c24446e7 100644 --- a/src/libstd/sync/future.rs +++ b/src/libstd/sync/future.rs @@ -141,7 +141,7 @@ impl<A:Send> Future<A> { Thread::spawn(move |:| { // Don't panic if the other end has hung up let _ = tx.send(blk()); - }).detach(); + }); Future::from_receiver(rx) } diff --git a/src/libstd/sync/mpsc/blocking.rs b/src/libstd/sync/mpsc/blocking.rs index faff5f09f81..f174771a3e0 100644 --- a/src/libstd/sync/mpsc/blocking.rs +++ b/src/libstd/sync/mpsc/blocking.rs @@ -13,8 +13,8 @@ use thread::Thread; use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering}; use sync::Arc; -use kinds::{Sync, Send}; -use kinds::marker::{NoSend, NoSync}; +use marker::{Sync, Send}; +use marker::{NoSend, NoSync}; use mem; use clone::Clone; diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 7c18b8a43fa..eca7d3155b1 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -60,7 +60,7 @@ //! let (tx, rx) = channel(); //! Thread::spawn(move|| { //! tx.send(10i).unwrap(); -//! }).detach(); +//! }); //! assert_eq!(rx.recv().unwrap(), 10i); //! ``` //! @@ -78,7 +78,7 @@ //! let tx = tx.clone(); //! Thread::spawn(move|| { //! tx.send(i).unwrap(); -//! }).detach() +//! }); //! } //! //! for _ in range(0i, 10i) { @@ -109,7 +109,7 @@ //! Thread::spawn(move|| { //! // This will wait for the parent task to start receiving //! tx.send(53).unwrap(); -//! }).detach(); +//! }); //! rx.recv().unwrap(); //! ``` //! @@ -319,7 +319,7 @@ use prelude::v1::*; use sync::Arc; use fmt; -use kinds::marker; +use marker; use mem; use cell::UnsafeCell; @@ -476,12 +476,12 @@ impl<T> UnsafeFlavor<T> for Receiver<T> { /// Thread::spawn(move|| { /// # fn expensive_computation() {} /// tx.send(expensive_computation()).unwrap(); -/// }).detach(); +/// }); /// /// // Do some useful work for awhile /// /// // Let's see what that answer was -/// println!("{}", rx.recv().unwrap()); +/// println!("{:?}", rx.recv().unwrap()); /// ``` #[stable] pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) { @@ -518,7 +518,7 @@ pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) { /// Thread::spawn(move|| { /// // this will block until the previous message has been received /// tx.send(2i).unwrap(); -/// }).detach(); +/// }); /// /// assert_eq!(rx.recv().unwrap(), 1i); /// assert_eq!(rx.recv().unwrap(), 2i); @@ -1144,7 +1144,7 @@ mod test { #[test] fn stress() { let (tx, rx) = channel::<int>(); - let t = Thread::spawn(move|| { + let t = Thread::scoped(move|| { for _ in range(0u, 10000) { tx.send(1i).unwrap(); } }); for _ in range(0u, 10000) { @@ -1159,7 +1159,7 @@ mod test { static NTHREADS: uint = 8; let (tx, rx) = channel::<int>(); - let t = Thread::spawn(move|| { + let t = Thread::scoped(move|| { for _ in range(0, AMT * NTHREADS) { assert_eq!(rx.recv().unwrap(), 1); } @@ -1173,7 +1173,7 @@ mod test { let tx = tx.clone(); Thread::spawn(move|| { for _ in range(0, AMT) { tx.send(1).unwrap(); } - }).detach(); + }); } drop(tx); t.join().ok().unwrap(); @@ -1183,14 +1183,14 @@ mod test { fn send_from_outside_runtime() { let (tx1, rx1) = channel::<()>(); let (tx2, rx2) = channel::<int>(); - let t1 = Thread::spawn(move|| { + let t1 = Thread::scoped(move|| { tx1.send(()).unwrap(); for _ in range(0i, 40) { assert_eq!(rx2.recv().unwrap(), 1); } }); rx1.recv().unwrap(); - let t2 = Thread::spawn(move|| { + let t2 = Thread::scoped(move|| { for _ in range(0i, 40) { tx2.send(1).unwrap(); } @@ -1202,7 +1202,7 @@ mod test { #[test] fn recv_from_outside_runtime() { let (tx, rx) = channel::<int>(); - let t = Thread::spawn(move|| { + let t = Thread::scoped(move|| { for _ in range(0i, 40) { assert_eq!(rx.recv().unwrap(), 1); } @@ -1217,11 +1217,11 @@ mod test { fn no_runtime() { let (tx1, rx1) = channel::<int>(); let (tx2, rx2) = channel::<int>(); - let t1 = Thread::spawn(move|| { + let t1 = Thread::scoped(move|| { assert_eq!(rx1.recv().unwrap(), 1); tx2.send(2).unwrap(); }); - let t2 = Thread::spawn(move|| { + let t2 = Thread::scoped(move|| { tx1.send(1).unwrap(); assert_eq!(rx2.recv().unwrap(), 2); }); @@ -1254,7 +1254,7 @@ mod test { #[test] fn oneshot_single_thread_recv_chan_close() { // Receiving on a closed chan will panic - let res = Thread::spawn(move|| { + let res = Thread::scoped(move|| { let (tx, rx) = channel::<int>(); drop(tx); rx.recv().unwrap(); @@ -1336,7 +1336,7 @@ mod test { let _t = Thread::spawn(move|| { drop(tx); }); - let res = Thread::spawn(move|| { + let res = Thread::scoped(move|| { assert!(rx.recv().unwrap() == box 10); }).join(); assert!(res.is_err()); @@ -1360,7 +1360,7 @@ mod test { let _t = Thread::spawn(move|| { drop(rx); }); - let _ = Thread::spawn(move|| { + let _ = Thread::scoped(move|| { tx.send(1).unwrap(); }).join(); } @@ -1371,15 +1371,15 @@ mod test { for _ in range(0, stress_factor()) { let (tx, rx) = channel::<int>(); Thread::spawn(move|| { - let res = Thread::spawn(move|| { + let res = Thread::scoped(move|| { rx.recv().unwrap(); }).join(); assert!(res.is_err()); - }).detach(); + }); let _t = Thread::spawn(move|| { Thread::spawn(move|| { drop(tx); - }).detach(); + }); }); } } @@ -1409,7 +1409,7 @@ mod test { Thread::spawn(move|| { tx.send(box i).unwrap(); send(tx, i + 1); - }).detach(); + }); } fn recv(rx: Receiver<Box<int>>, i: int) { @@ -1418,7 +1418,7 @@ mod test { Thread::spawn(move|| { assert!(rx.recv().unwrap() == box i); recv(rx, i + 1); - }).detach(); + }); } } } @@ -1439,7 +1439,7 @@ mod test { let tx = tx.clone(); Thread::spawn(move|| { tx.send(()).unwrap(); - }).detach(); + }); } for _ in range(0, total) { @@ -1644,7 +1644,7 @@ mod sync_tests { Thread::spawn(move|| { tx.send(1).unwrap(); tx.send(1).unwrap(); - }).detach(); + }); while rx.recv().is_ok() {} } @@ -1653,7 +1653,7 @@ mod sync_tests { let (tx, rx) = sync_channel::<int>(0); Thread::spawn(move|| { for _ in range(0u, 10000) { tx.send(1).unwrap(); } - }).detach(); + }); for _ in range(0u, 10000) { assert_eq!(rx.recv().unwrap(), 1); } @@ -1675,13 +1675,13 @@ mod sync_tests { _ => {} } dtx.send(()).unwrap(); - }).detach(); + }); for _ in range(0, NTHREADS) { let tx = tx.clone(); Thread::spawn(move|| { for _ in range(0, AMT) { tx.send(1).unwrap(); } - }).detach(); + }); } drop(tx); drx.recv().unwrap(); @@ -1712,7 +1712,7 @@ mod sync_tests { #[test] fn oneshot_single_thread_recv_chan_close() { // Receiving on a closed chan will panic - let res = Thread::spawn(move|| { + let res = Thread::scoped(move|| { let (tx, rx) = sync_channel::<int>(0); drop(tx); rx.recv().unwrap(); @@ -1800,7 +1800,7 @@ mod sync_tests { let _t = Thread::spawn(move|| { drop(tx); }); - let res = Thread::spawn(move|| { + let res = Thread::scoped(move|| { assert!(rx.recv().unwrap() == box 10); }).join(); assert!(res.is_err()); @@ -1824,7 +1824,7 @@ mod sync_tests { let _t = Thread::spawn(move|| { drop(rx); }); - let _ = Thread::spawn(move || { + let _ = Thread::scoped(move || { tx.send(1).unwrap(); }).join(); } @@ -1835,7 +1835,7 @@ mod sync_tests { for _ in range(0, stress_factor()) { let (tx, rx) = sync_channel::<int>(0); let _t = Thread::spawn(move|| { - let res = Thread::spawn(move|| { + let res = Thread::scoped(move|| { rx.recv().unwrap(); }).join(); assert!(res.is_err()); @@ -1843,7 +1843,7 @@ mod sync_tests { let _t = Thread::spawn(move|| { Thread::spawn(move|| { drop(tx); - }).detach(); + }); }); } } @@ -1873,7 +1873,7 @@ mod sync_tests { Thread::spawn(move|| { tx.send(box i).unwrap(); send(tx, i + 1); - }).detach(); + }); } fn recv(rx: Receiver<Box<int>>, i: int) { @@ -1882,7 +1882,7 @@ mod sync_tests { Thread::spawn(move|| { assert!(rx.recv().unwrap() == box i); recv(rx, i + 1); - }).detach(); + }); } } } @@ -1903,7 +1903,7 @@ mod sync_tests { let tx = tx.clone(); Thread::spawn(move|| { tx.send(()).unwrap(); - }).detach(); + }); } for _ in range(0, total) { diff --git a/src/libstd/sync/mpsc/mpsc_queue.rs b/src/libstd/sync/mpsc/mpsc_queue.rs index 9ad24a5a11e..f8eae1322bf 100644 --- a/src/libstd/sync/mpsc/mpsc_queue.rs +++ b/src/libstd/sync/mpsc/mpsc_queue.rs @@ -188,7 +188,7 @@ mod tests { q.push(i); } tx.send(()).unwrap(); - }).detach(); + }); } let mut i = 0u; diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs index 16adbf5aa4f..b7bb22b3ef3 100644 --- a/src/libstd/sync/mpsc/select.rs +++ b/src/libstd/sync/mpsc/select.rs @@ -57,7 +57,7 @@ use core::prelude::*; use core::cell::Cell; -use core::kinds::marker; +use core::marker; use core::mem; use core::uint; diff --git a/src/libstd/sync/mpsc/sync.rs b/src/libstd/sync/mpsc/sync.rs index 6836888e67e..b2cc807eb11 100644 --- a/src/libstd/sync/mpsc/sync.rs +++ b/src/libstd/sync/mpsc/sync.rs @@ -437,7 +437,8 @@ impl<T> Buffer<T> { let start = self.start; self.size -= 1; self.start = (self.start + 1) % self.buf.len(); - self.buf[start].take().unwrap() + let result = &mut self.buf[start]; + result.take().unwrap() } fn size(&self) -> uint { self.size } diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 6b3dd89f33b..c1b55c6ff78 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -11,7 +11,7 @@ use prelude::v1::*; use cell::UnsafeCell; -use kinds::marker; +use marker; use ops::{Deref, DerefMut}; use sync::poison::{self, TryLockError, TryLockResult, LockResult}; use sys_common::mutex as sys; @@ -75,7 +75,7 @@ use sys_common::mutex as sys; /// tx.send(()).unwrap(); /// } /// // the lock is unlocked here when `data` goes out of scope. -/// }).detach(); +/// }); /// } /// /// rx.recv().unwrap(); @@ -90,7 +90,7 @@ use sys_common::mutex as sys; /// let lock = Arc::new(Mutex::new(0u)); /// let lock2 = lock.clone(); /// -/// let _ = Thread::spawn(move || -> () { +/// let _ = Thread::scoped(move || -> () { /// // This thread will acquire the mutex first, unwrapping the result of /// // `lock` because the lock has not been poisoned. /// let _lock = lock2.lock().unwrap(); @@ -376,9 +376,9 @@ mod test { let (tx, rx) = channel(); for _ in range(0, K) { let tx2 = tx.clone(); - Thread::spawn(move|| { inc(); tx2.send(()).unwrap(); }).detach(); + Thread::spawn(move|| { inc(); tx2.send(()).unwrap(); }); let tx2 = tx.clone(); - Thread::spawn(move|| { inc(); tx2.send(()).unwrap(); }).detach(); + Thread::spawn(move|| { inc(); tx2.send(()).unwrap(); }); } drop(tx); @@ -453,7 +453,7 @@ mod test { fn test_mutex_arc_poison() { let arc = Arc::new(Mutex::new(1i)); let arc2 = arc.clone(); - let _ = Thread::spawn(move|| { + let _ = Thread::scoped(move|| { let lock = arc2.lock().unwrap(); assert_eq!(*lock, 2); }).join(); @@ -480,7 +480,7 @@ mod test { fn test_mutex_arc_access_in_unwind() { let arc = Arc::new(Mutex::new(1i)); let arc2 = arc.clone(); - let _ = Thread::spawn(move|| -> () { + let _ = Thread::scoped(move|| -> () { struct Unwinder { i: Arc<Mutex<int>>, } diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index aa2d957a3eb..3bf2ae277e0 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -14,7 +14,7 @@ //! example use case would be for initializing an FFI library. use int; -use kinds::Sync; +use marker::Sync; use mem::drop; use ops::FnOnce; use sync::atomic::{AtomicInt, Ordering, ATOMIC_INT_INIT}; @@ -159,7 +159,7 @@ mod test { assert!(run); } tx.send(()).unwrap(); - }).detach(); + }); } unsafe { diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index 4afd5bb63f4..7db2111cc46 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -11,7 +11,7 @@ use prelude::v1::*; use cell::UnsafeCell; -use kinds::marker; +use marker; use ops::{Deref, DerefMut}; use sync::poison::{self, LockResult, TryLockError, TryLockResult}; use sys_common::rwlock as sys; @@ -411,7 +411,7 @@ mod tests { } } drop(tx); - }).detach(); + }); } drop(tx); let _ = rx.recv(); @@ -422,7 +422,7 @@ mod tests { fn test_rw_arc_poison_wr() { let arc = Arc::new(RwLock::new(1i)); let arc2 = arc.clone(); - let _: Result<uint, _> = Thread::spawn(move|| { + let _: Result<uint, _> = Thread::scoped(move|| { let _lock = arc2.write().unwrap(); panic!(); }).join(); @@ -433,7 +433,7 @@ mod tests { fn test_rw_arc_poison_ww() { let arc = Arc::new(RwLock::new(1i)); let arc2 = arc.clone(); - let _: Result<uint, _> = Thread::spawn(move|| { + let _: Result<uint, _> = Thread::scoped(move|| { let _lock = arc2.write().unwrap(); panic!(); }).join(); @@ -444,7 +444,7 @@ mod tests { fn test_rw_arc_no_poison_rr() { let arc = Arc::new(RwLock::new(1i)); let arc2 = arc.clone(); - let _: Result<uint, _> = Thread::spawn(move|| { + let _: Result<uint, _> = Thread::scoped(move|| { let _lock = arc2.read().unwrap(); panic!(); }).join(); @@ -455,7 +455,7 @@ mod tests { fn test_rw_arc_no_poison_rw() { let arc = Arc::new(RwLock::new(1i)); let arc2 = arc.clone(); - let _: Result<uint, _> = Thread::spawn(move|| { + let _: Result<uint, _> = Thread::scoped(move|| { let _lock = arc2.read().unwrap(); panic!() }).join(); @@ -478,13 +478,13 @@ mod tests { *lock = tmp + 1; } tx.send(()).unwrap(); - }).detach(); + }); // Readers try to catch the writer in the act let mut children = Vec::new(); for _ in range(0u, 5) { let arc3 = arc.clone(); - children.push(Thread::spawn(move|| { + children.push(Thread::scoped(move|| { let lock = arc3.read().unwrap(); assert!(*lock >= 0); })); @@ -505,7 +505,7 @@ mod tests { fn test_rw_arc_access_in_unwind() { let arc = Arc::new(RwLock::new(1i)); let arc2 = arc.clone(); - let _ = Thread::spawn(move|| -> () { + let _ = Thread::scoped(move|| -> () { struct Unwinder { i: Arc<RwLock<int>>, } diff --git a/src/libstd/sync/semaphore.rs b/src/libstd/sync/semaphore.rs index 505819fbf8a..8d44084671a 100644 --- a/src/libstd/sync/semaphore.rs +++ b/src/libstd/sync/semaphore.rs @@ -193,7 +193,7 @@ mod tests { tx.send(()).unwrap(); drop(s2.access()); tx.send(()).unwrap(); - }).detach(); + }); rx.recv().unwrap(); // wait for child to come alive } rx.recv().unwrap(); // wait for child to be done diff --git a/src/libstd/sync/task_pool.rs b/src/libstd/sync/task_pool.rs index 088827dc084..278528bdb38 100644 --- a/src/libstd/sync/task_pool.rs +++ b/src/libstd/sync/task_pool.rs @@ -132,7 +132,7 @@ fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk>>>) { } sentinel.cancel(); - }).detach(); + }); } #[cfg(test)] diff --git a/src/libstd/sys/common/backtrace.rs b/src/libstd/sys/common/backtrace.rs index d4039fd96ff..be44aa99f49 100644 --- a/src/libstd/sys/common/backtrace.rs +++ b/src/libstd/sys/common/backtrace.rs @@ -88,7 +88,7 @@ pub fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> { while rest.len() > 0 { if rest.starts_with("$") { macro_rules! demangle { - ($($pat:expr => $demangled:expr),*) => ({ + ($($pat:expr, => $demangled:expr),*) => ({ $(if rest.starts_with($pat) { try!(writer.write_str($demangled)); rest = rest.slice_from($pat.len()); @@ -103,22 +103,22 @@ pub fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> { // see src/librustc/back/link.rs for these mappings demangle! ( - "$SP$" => "@", - "$UP$" => "Box", - "$RP$" => "*", - "$BP$" => "&", - "$LT$" => "<", - "$GT$" => ">", - "$LP$" => "(", - "$RP$" => ")", - "$C$" => ",", + "$SP$", => "@", + "$UP$", => "Box", + "$RP$", => "*", + "$BP$", => "&", + "$LT$", => "<", + "$GT$", => ">", + "$LP$", => "(", + "$RP$", => ")", + "$C$", => ",", // in theory we can demangle any Unicode code point, but // for simplicity we just catch the common ones. - "$u{20}" => " ", - "$u{27}" => "'", - "$u{5b}" => "[", - "$u{5d}" => "]" + "$u{20}", => " ", + "$u{27}", => "'", + "$u{5b}", => "[", + "$u{5d}", => "]" ) } else { let idx = match rest.find('$') { diff --git a/src/libstd/sys/common/helper_thread.rs b/src/libstd/sys/common/helper_thread.rs index bdf1bf3dfd0..f940b6ed368 100644 --- a/src/libstd/sys/common/helper_thread.rs +++ b/src/libstd/sys/common/helper_thread.rs @@ -99,7 +99,7 @@ impl<M: Send> Helper<M> { let _g = self.lock.lock().unwrap(); *self.shutdown.get() = true; self.cond.notify_one() - }).detach(); + }); rt::at_exit(move|:| { self.shutdown() }); *self.initialized.get() = true; diff --git a/src/libstd/sys/common/mutex.rs b/src/libstd/sys/common/mutex.rs index 567c26956ef..9aea0fb3b31 100644 --- a/src/libstd/sys/common/mutex.rs +++ b/src/libstd/sys/common/mutex.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use kinds::Sync; +use marker::Sync; use sys::mutex as imp; /// An OS-based mutual exclusion lock. diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs index 4cf891ac498..902942d7244 100644 --- a/src/libstd/sys/common/net.rs +++ b/src/libstd/sys/common/net.rs @@ -469,7 +469,7 @@ pub fn write<T, L, W>(fd: sock_t, // Also as with read(), we use MSG_DONTWAIT to guard ourselves // against unforeseen circumstances. let _guard = lock(); - let ptr = buf[written..].as_ptr(); + let ptr = buf.index(&(written..)).as_ptr(); let len = buf.len() - written; match retry(|| write(deadline.is_some(), ptr, len)) { -1 if wouldblock() => {} diff --git a/src/libstd/sys/unix/backtrace.rs b/src/libstd/sys/unix/backtrace.rs index ca268a8f27f..7164931c55a 100644 --- a/src/libstd/sys/unix/backtrace.rs +++ b/src/libstd/sys/unix/backtrace.rs @@ -370,7 +370,7 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> { // Finally, after all that work above, we can emit a symbol. fn output(w: &mut Writer, idx: int, addr: *mut libc::c_void, s: Option<&[u8]>) -> IoResult<()> { - try!(write!(w, " {:2}: {:2$} - ", idx, addr, HEX_WIDTH)); + try!(write!(w, " {:2}: {:2$?} - ", idx, addr, HEX_WIDTH)); match s.and_then(|s| str::from_utf8(s).ok()) { Some(string) => try!(demangle(w, string)), None => try!(write!(w, "<unknown>")), diff --git a/src/libstd/sys/unix/c.rs b/src/libstd/sys/unix/c.rs index ca419d1c7f4..cc661877bc0 100644 --- a/src/libstd/sys/unix/c.rs +++ b/src/libstd/sys/unix/c.rs @@ -165,8 +165,8 @@ mod signal { sa_restorer: *mut libc::c_void, } - unsafe impl ::kinds::Send for sigaction { } - unsafe impl ::kinds::Sync for sigaction { } + unsafe impl ::marker::Send for sigaction { } + unsafe impl ::marker::Sync for sigaction { } #[repr(C)] #[cfg(target_word_size = "32")] @@ -217,8 +217,8 @@ mod signal { sa_resv: [libc::c_int; 1], } - unsafe impl ::kinds::Send for sigaction { } - unsafe impl ::kinds::Sync for sigaction { } + unsafe impl ::marker::Send for sigaction { } + unsafe impl ::marker::Sync for sigaction { } #[repr(C)] pub struct sigset_t { diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 1ad775517bb..c53f9d22790 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -381,7 +381,7 @@ mod tests { assert_eq!(buf[2], 's' as u8); assert_eq!(buf[3], 't' as u8); } - r => panic!("invalid read: {}", r), + r => panic!("invalid read: {:?}", r), } assert!(writer.read(&mut buf).is_err()); diff --git a/src/libstd/sys/unix/mutex.rs b/src/libstd/sys/unix/mutex.rs index 81f8659d6ae..ada8a7f2349 100644 --- a/src/libstd/sys/unix/mutex.rs +++ b/src/libstd/sys/unix/mutex.rs @@ -9,7 +9,7 @@ // except according to those terms. use cell::UnsafeCell; -use kinds::Sync; +use marker::Sync; use sys::sync as ffi; use sys_common::mutex; diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs index 5bc6b0c703b..1357bbdd5a3 100644 --- a/src/libstd/sys/unix/process.rs +++ b/src/libstd/sys/unix/process.rs @@ -125,7 +125,7 @@ impl Process { return match input.read(&mut bytes) { Ok(8) => { assert!(combine(CLOEXEC_MSG_FOOTER) == combine(bytes.slice(4, 8)), - "Validation on the CLOEXEC pipe failed: {}", bytes); + "Validation on the CLOEXEC pipe failed: {:?}", bytes); let errno = combine(bytes.slice(0, 4)); assert!(p.wait(0).is_ok(), "wait(0) should either return Ok or panic"); Err(super::decode_error(errno)) @@ -133,7 +133,7 @@ impl Process { Err(ref e) if e.kind == EndOfFile => Ok(p), Err(e) => { assert!(p.wait(0).is_ok(), "wait(0) should either return Ok or panic"); - panic!("the CLOEXEC pipe failed: {}", e) + panic!("the CLOEXEC pipe failed: {:?}", e) }, Ok(..) => { // pipe I/O up to PIPE_BUF bytes should be atomic assert!(p.wait(0).is_ok(), "wait(0) should either return Ok or panic"); @@ -285,7 +285,7 @@ impl Process { let mut status = 0 as c_int; if deadline == 0 { return match retry(|| unsafe { c::waitpid(self.pid, &mut status, 0) }) { - -1 => panic!("unknown waitpid error: {}", super::last_error()), + -1 => panic!("unknown waitpid error: {:?}", super::last_error()), _ => Ok(translate_status(status)), } } @@ -410,7 +410,7 @@ impl Process { continue } - n => panic!("error in select {} ({})", os::errno(), n), + n => panic!("error in select {:?} ({:?})", os::errno(), n), } // Process any pending messages @@ -491,7 +491,7 @@ 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 {:?} ({:?})", os::last_os_error(), n), } } } @@ -514,7 +514,7 @@ impl Process { } { 1 => {} -1 if wouldblock() => {} // see above comments - n => panic!("bad error on write fd: {} {}", n, os::errno()), + n => panic!("bad error on write fd: {:?} {:?}", n, os::errno()), } } } @@ -526,7 +526,7 @@ impl Process { }) { n if n == self.pid => Some(translate_status(status)), 0 => None, - n => panic!("unknown waitpid error `{}`: {}", n, + n => panic!("unknown waitpid error `{:?}`: {:?}", n, super::last_error()), } } diff --git a/src/libstd/sys/unix/thread_local.rs b/src/libstd/sys/unix/thread_local.rs index e507377a8fc..ea1e9c261fe 100644 --- a/src/libstd/sys/unix/thread_local.rs +++ b/src/libstd/sys/unix/thread_local.rs @@ -37,10 +37,18 @@ pub unsafe fn destroy(key: Key) { debug_assert_eq!(r, 0); } -#[cfg(target_os = "macos")] +#[cfg(any(target_os = "macos", + target_os = "ios"))] type pthread_key_t = ::libc::c_ulong; -#[cfg(not(target_os = "macos"))] +#[cfg(any(target_os = "freebsd", + target_os = "dragonfly"))] +type pthread_key_t = ::libc::c_int; + +#[cfg(not(any(target_os = "macos", + target_os = "ios", + target_os = "freebsd", + target_os = "dragonfly")))] type pthread_key_t = ::libc::c_uint; extern { diff --git a/src/libstd/sys/windows/backtrace.rs b/src/libstd/sys/windows/backtrace.rs index 4ccecfd1f5f..eb76f13afe7 100644 --- a/src/libstd/sys/windows/backtrace.rs +++ b/src/libstd/sys/windows/backtrace.rs @@ -23,6 +23,7 @@ use dynamic_lib::DynamicLibrary; use ffi; +use core::ops::Index; use intrinsics; use io::{IoResult, Writer}; use libc; @@ -361,7 +362,7 @@ pub fn write(w: &mut Writer) -> IoResult<()> { let bytes = unsafe { ffi::c_str_to_bytes(&ptr) }; match str::from_utf8(bytes) { Ok(s) => try!(demangle(w, s)), - Err(..) => try!(w.write(bytes[..bytes.len()-1])), + Err(..) => try!(w.write(bytes.index(&(..(bytes.len()-1))))), } } try!(w.write(&['\n' as u8])); diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 945c2e8e7d1..37ed32fa367 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -84,6 +84,32 @@ pub fn fd_set(set: &mut fd_set, s: libc::SOCKET) { set.fd_count += 1; } +pub type SHORT = libc::c_short; + +#[repr(C)] +pub struct COORD { + pub X: SHORT, + pub Y: SHORT, +} + +#[repr(C)] +pub struct SMALL_RECT { + pub Left: SHORT, + pub Top: SHORT, + pub Right: SHORT, + pub Bottom: SHORT, +} + +#[repr(C)] +pub struct CONSOLE_SCREEN_BUFFER_INFO { + pub dwSize: COORD, + pub dwCursorPosition: COORD, + pub wAttributes: libc::WORD, + pub srWindow: SMALL_RECT, + pub dwMaximumWindowSize: COORD, +} +pub type PCONSOLE_SCREEN_BUFFER_INFO = *mut CONSOLE_SCREEN_BUFFER_INFO; + #[link(name = "ws2_32")] extern "system" { pub fn WSAStartup(wVersionRequested: libc::WORD, @@ -170,7 +196,7 @@ pub mod compat { /// they are used to be passed to the real function if available. macro_rules! compat_fn { ($module:ident::$symbol:ident($($argname:ident: $argtype:ty),*) - -> $rettype:ty $fallback:block) => ( + -> $rettype:ty { $fallback:expr }) => ( #[inline(always)] pub unsafe fn $symbol($($argname: $argtype),*) -> $rettype { static mut ptr: extern "system" fn($($argname: $argtype),*) -> $rettype = thunk; @@ -185,14 +211,11 @@ pub mod compat { } } - extern "system" fn fallback($($argname: $argtype),*) -> $rettype $fallback + extern "system" fn fallback($($argname: $argtype),*) + -> $rettype { $fallback } ::intrinsics::atomic_load_relaxed(&ptr)($($argname),*) } - ); - - ($module:ident::$symbol:ident($($argname:ident: $argtype:ty),*) $fallback:block) => ( - compat_fn!($module::$symbol($($argname: $argtype),*) -> () $fallback) ) } @@ -210,20 +233,22 @@ pub mod compat { fn SetLastError(dwErrCode: DWORD); } - compat_fn! { kernel32::CreateSymbolicLinkW(_lpSymlinkFileName: LPCWSTR, - _lpTargetFileName: LPCWSTR, - _dwFlags: DWORD) -> BOOLEAN { - unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); } - 0 - } } - - compat_fn! { kernel32::GetFinalPathNameByHandleW(_hFile: HANDLE, - _lpszFilePath: LPCWSTR, - _cchFilePath: DWORD, - _dwFlags: DWORD) -> DWORD { - unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); } - 0 - } } + compat_fn! { + kernel32::CreateSymbolicLinkW(_lpSymlinkFileName: LPCWSTR, + _lpTargetFileName: LPCWSTR, + _dwFlags: DWORD) -> BOOLEAN { + unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0 } + } + } + + compat_fn! { + kernel32::GetFinalPathNameByHandleW(_hFile: HANDLE, + _lpszFilePath: LPCWSTR, + _cchFilePath: DWORD, + _dwFlags: DWORD) -> DWORD { + unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0 } + } + } } } @@ -246,4 +271,8 @@ extern "system" { pub fn SetConsoleMode(hConsoleHandle: libc::HANDLE, lpMode: libc::DWORD) -> libc::BOOL; + pub fn GetConsoleScreenBufferInfo( + hConsoleOutput: libc::HANDLE, + lpConsoleScreenBufferInfo: PCONSOLE_SCREEN_BUFFER_INFO, + ) -> libc::BOOL; } diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index dfdee0e0385..fcde5c01080 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -36,7 +36,7 @@ const BUF_BYTES : uint = 2048u; pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] { match v.iter().position(|c| *c == 0) { // don't include the 0 - Some(i) => v[..i], + Some(i) => v.index(&(0..i)), None => v } } diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs index 9996909f2f5..016757ef63e 100644 --- a/src/libstd/sys/windows/pipe.rs +++ b/src/libstd/sys/windows/pipe.rs @@ -453,7 +453,7 @@ impl UnixStream { } let ret = unsafe { libc::WriteFile(self.handle(), - buf[offset..].as_ptr() as libc::LPVOID, + buf.index(&(offset..)).as_ptr() as libc::LPVOID, (buf.len() - offset) as libc::DWORD, &mut bytes_written, &mut overlapped) diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index 7b667416b17..8e1f169b5cd 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -25,6 +25,8 @@ use path::BytesContainer; use ptr; use str; use sys::fs::FileDesc; +use sync::{StaticMutex, MUTEX_INIT}; + use sys::fs; use sys::{self, retry, c, wouldblock, set_nonblocking, ms_to_timeval, timer}; use sys_common::helper_thread::Helper; @@ -32,6 +34,10 @@ use sys_common::{AsInner, mkerr_libc, timeout}; pub use sys_common::ProcessConfig; +// `CreateProcess` is racy! +// http://support.microsoft.com/kb/315939 +static CREATE_PROCESS_LOCK: StaticMutex = MUTEX_INIT; + /// A value representing a child process. /// /// The lifetime of this value is linked to the lifetime of the actual @@ -224,6 +230,7 @@ impl Process { with_dirp(cfg.cwd(), |dirp| { let mut cmd_str: Vec<u16> = cmd_str.utf16_units().collect(); cmd_str.push(0); + let _lock = CREATE_PROCESS_LOCK.lock().unwrap(); let created = CreateProcessW(ptr::null(), cmd_str.as_mut_ptr(), ptr::null_mut(), diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index 4498f56c00a..30707488b30 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -62,7 +62,7 @@ pub unsafe fn create(stack: uint, p: Thunk) -> rust_thread { if ret as uint == 0 { // be sure to not leak the closure let _p: Box<Thunk> = mem::transmute(arg); - panic!("failed to spawn native thread: {}", ret); + panic!("failed to spawn native thread: {:?}", ret); } return ret; } diff --git a/src/libstd/sys/windows/tty.rs b/src/libstd/sys/windows/tty.rs index 4305f7743b5..f9e1f0d3ed0 100644 --- a/src/libstd/sys/windows/tty.rs +++ b/src/libstd/sys/windows/tty.rs @@ -32,13 +32,15 @@ use iter::repeat; use libc::types::os::arch::extra::LPCVOID; use libc::{c_int, HANDLE, LPDWORD, DWORD, LPVOID}; use libc::{get_osfhandle, CloseHandle}; +use mem; use ptr; use str::from_utf8; use super::c::{ENABLE_ECHO_INPUT, ENABLE_EXTENDED_FLAGS}; use super::c::{ENABLE_INSERT_MODE, ENABLE_LINE_INPUT}; use super::c::{ENABLE_PROCESSED_INPUT, ENABLE_QUICK_EDIT_MODE}; -use super::c::{ERROR_ILLEGAL_CHARACTER}; +use super::c::{ERROR_ILLEGAL_CHARACTER, CONSOLE_SCREEN_BUFFER_INFO}; use super::c::{ReadConsoleW, WriteConsoleW, GetConsoleMode, SetConsoleMode}; +use super::c::{GetConsoleScreenBufferInfo}; fn invalid_encoding() -> IoError { IoError { @@ -146,12 +148,12 @@ impl TTY { } pub fn get_winsize(&mut self) -> IoResult<(int, int)> { - // FIXME - // Get console buffer via CreateFile with CONOUT$ - // Make a CONSOLE_SCREEN_BUFFER_INFO - // Call GetConsoleScreenBufferInfo - // Maybe call GetLargestConsoleWindowSize instead? - Err(super::unimpl()) + let mut info: CONSOLE_SCREEN_BUFFER_INFO = unsafe { mem::zeroed() }; + match unsafe { GetConsoleScreenBufferInfo(self.handle, &mut info as *mut _) } { + 0 => Err(super::last_error()), + _ => Ok(((info.srWindow.Right + 1 - info.srWindow.Left) as int, + (info.srWindow.Bottom + 1 - info.srWindow.Top) as int)), + } } // Let us magically declare this as a TTY diff --git a/src/libstd/thread.rs b/src/libstd/thread.rs index cc82d38ae2a..71321ed3b71 100644 --- a/src/libstd/thread.rs +++ b/src/libstd/thread.rs @@ -16,7 +16,7 @@ //! each with their own stack and local state. //! //! Communication between threads can be done through -//! [channels](../../std/comm/index.html), Rust's message-passing +//! [channels](../../std/sync/mpsc/index.html), Rust's message-passing //! types, along with [other forms of thread //! synchronization](../../std/sync/index.html) and shared-memory data //! structures. In particular, types that are guaranteed to be @@ -58,25 +58,45 @@ //! ```rust //! use std::thread::Thread; //! -//! let guard = Thread::spawn(move || { +//! let thread = Thread::spawn(move || { //! println!("Hello, World!"); //! // some computation here //! }); -//! let result = guard.join(); //! ``` //! -//! The `spawn` function doesn't return a `Thread` directly; instead, it returns -//! a *join guard* from which a `Thread` can be extracted. The join guard is an -//! RAII-style guard that will automatically join the child thread (block until -//! it terminates) when it is dropped. You can join the child thread in advance -//! by calling the `join` method on the guard, which will also return the result -//! produced by the thread. +//! The spawned thread is "detached" from the current thread, meaning that it +//! can outlive the thread that spawned it. (Note, however, that when the main +//! thread terminates all detached threads are terminated as well.) The returned +//! `Thread` handle can be used for low-level synchronization as described below. +//! +//! ## Scoped threads //! -//! If you instead wish to *detach* the child thread, allowing it to outlive its -//! parent, you can use the `detach` method on the guard, +//! Often a parent thread uses a child thread to perform some particular task, +//! and at some point must wait for the child to complete before continuing. +//! For this scenario, use the `scoped` constructor: //! -//! A handle to the thread itself is available via the `thread` method on the -//! join guard. +//! ```rust +//! use std::thread::Thread; +//! +//! let guard = Thread::scoped(move || { +//! println!("Hello, World!"); +//! // some computation here +//! }); +//! // do some other work in the meantime +//! let result = guard.join(); +//! ``` +//! +//! The `scoped` function doesn't return a `Thread` directly; instead, it +//! returns a *join guard* from which a `Thread` can be extracted. The join +//! guard is an RAII-style guard that will automatically join the child thread +//! (block until it terminates) when it is dropped. You can join the child +//! thread in advance by calling the `join` method on the guard, which will also +//! return the result produced by the thread. A handle to the thread itself is +//! available via the `thread` method on the join guard. +//! +//! (Note: eventually, the `scoped` constructor will allow the parent and child +//! threads to data that lives on the parent thread's stack, but some language +//! changes are needed before this is possible.) //! //! ## Configuring threads //! @@ -89,7 +109,7 @@ //! //! thread::Builder::new().name("child1".to_string()).spawn(move || { //! println!("Hello, world!") -//! }).detach(); +//! }); //! ``` //! //! ## Blocking support: park and unpark @@ -124,11 +144,13 @@ //! //! * It can be implemented highly efficiently on many platforms. +#![stable] + use any::Any; use boxed::Box; use cell::UnsafeCell; use clone::Clone; -use kinds::{Send, Sync}; +use marker::{Send, Sync}; use ops::{Drop, FnOnce}; use option::Option::{self, Some, None}; use result::Result::{Err, Ok}; @@ -144,6 +166,7 @@ use sys_common::{stack, thread_info}; /// Thread configuation. Provides detailed control over the properties /// and behavior of new threads. +#[stable] pub struct Builder { // A name for the thread-to-be, for identification in panic messages name: Option<String>, @@ -158,6 +181,7 @@ pub struct Builder { impl Builder { /// Generate the base configuration for spawning a thread, from which /// configuration methods can be chained. + #[stable] pub fn new() -> Builder { Builder { name: None, @@ -169,12 +193,14 @@ impl Builder { /// Name the thread-to-be. Currently the name is used for identification /// only in panic messages. + #[stable] pub fn name(mut self, name: String) -> Builder { self.name = Some(name); self } /// Set the size of the stack for the new thread. + #[stable] pub fn stack_size(mut self, size: uint) -> Builder { self.stack_size = Some(size); self @@ -194,19 +220,41 @@ impl Builder { self } - /// Spawn a new joinable thread, and return a JoinGuard guard for it. + /// Spawn a new detached thread, and return a handle to it. /// /// See `Thead::spawn` and the module doc for more details. - pub fn spawn<T, F>(self, f: F) -> JoinGuard<T> where - T: Send, F: FnOnce() -> T, F: Send - { - self.spawn_inner(Thunk::new(f)) + #[unstable = "may change with specifics of new Send semantics"] + pub fn spawn<F>(self, f: F) -> Thread where F: FnOnce(), F: Send + 'static { + let (native, thread) = self.spawn_inner(Thunk::new(f), Thunk::with_arg(|_| {})); + unsafe { imp::detach(native) }; + thread } - fn spawn_inner<T: Send>(self, f: Thunk<(), T>) -> JoinGuard<T> { + /// Spawn a new child thread that must be joined within a given + /// scope, and return a `JoinGuard`. + /// + /// See `Thead::scoped` and the module doc for more details. + #[unstable = "may change with specifics of new Send semantics"] + pub fn scoped<'a, T, F>(self, f: F) -> JoinGuard<'a, T> where + T: Send + 'a, F: FnOnce() -> T, F: Send + 'a + { let my_packet = Packet(Arc::new(UnsafeCell::new(None))); let their_packet = Packet(my_packet.0.clone()); + let (native, thread) = self.spawn_inner(Thunk::new(f), Thunk::with_arg(move |: ret| unsafe { + *their_packet.0.get() = Some(ret); + })); + JoinGuard { + native: native, + joined: false, + packet: my_packet, + thread: thread, + } + } + + fn spawn_inner<T: Send>(self, f: Thunk<(), T>, finish: Thunk<Result<T>, ()>) + -> (imp::rust_thread, Thread) + { let Builder { name, stack_size, stdout, stderr } = self; let stack_size = stack_size.unwrap_or(rt::min_stack()); @@ -258,21 +306,14 @@ impl Builder { unwind::try(move || *ptr = Some(f.invoke(()))) } }; - unsafe { - *their_packet.0.get() = Some(match (output, try_result) { - (Some(data), Ok(_)) => Ok(data), - (None, Err(cause)) => Err(cause), - _ => unreachable!() - }); - } + finish.invoke(match (output, try_result) { + (Some(data), Ok(_)) => Ok(data), + (None, Err(cause)) => Err(cause), + _ => unreachable!() + }); }; - JoinGuard { - native: unsafe { imp::create(stack_size, Thunk::new(main)) }, - joined: false, - packet: my_packet, - thread: my_thread, - } + (unsafe { imp::create(stack_size, Thunk::new(main)) }, my_thread) } } @@ -285,13 +326,12 @@ struct Inner { unsafe impl Sync for Inner {} #[derive(Clone)] +#[stable] /// A handle to a thread. pub struct Thread { inner: Arc<Inner>, } -unsafe impl Sync for Thread {} - impl Thread { // Used only internally to construct a thread object without spawning fn new(name: Option<String>) -> Thread { @@ -304,30 +344,47 @@ impl Thread { } } - /// Spawn a new joinable thread, returning a `JoinGuard` for it. + /// Spawn a new detached thread, returning a handle to it. + /// + /// The child thread may outlive the parent (unless the parent thread is the + /// main thread; the whole process is terminated when the main thread + /// finishes.) The thread handle can be used for low-level + /// synchronization. See the module documentation for additional details. + #[unstable = "may change with specifics of new Send semantics"] + pub fn spawn<F>(f: F) -> Thread where F: FnOnce(), F: Send + 'static { + Builder::new().spawn(f) + } + + /// Spawn a new *scoped* thread, returning a `JoinGuard` for it. /// /// The join guard can be used to explicitly join the child thread (via /// `join`), returning `Result<T>`, or it will implicitly join the child - /// upon being dropped. To detach the child, allowing it to outlive the - /// current thread, use `detach`. See the module documentation for additional details. - pub fn spawn<T, F>(f: F) -> JoinGuard<T> where - T: Send, F: FnOnce() -> T, F: Send + /// upon being dropped. Because the child thread may refer to data on the + /// current thread's stack (hence the "scoped" name), it cannot be detached; + /// it *must* be joined before the relevant stack frame is popped. See the + /// module documentation for additional details. + #[unstable = "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().spawn(f) + Builder::new().scoped(f) } /// Gets a handle to the thread that invokes it. + #[stable] pub fn current() -> Thread { thread_info::current_thread() } /// Cooperatively give up a timeslice to the OS scheduler. + #[unstable = "name may change"] pub fn yield_now() { unsafe { imp::yield_now() } } /// Determines whether the current thread is panicking. #[inline] + #[stable] pub fn panicking() -> bool { unwind::panicking() } @@ -341,6 +398,7 @@ impl Thread { // future, this will be implemented in a more efficient way, perhaps along the lines of // http://cr.openjdk.java.net/~stefank/6989984.1/raw_files/new/src/os/linux/vm/os_linux.cpp // or futuxes, and in either case may allow spurious wakeups. + #[unstable = "recently introduced"] pub fn park() { let thread = Thread::current(); let mut guard = thread.inner.lock.lock().unwrap(); @@ -353,6 +411,7 @@ impl Thread { /// Atomically makes the handle's token available if it is not already. /// /// See the module doc for more detail. + #[unstable = "recently introduced"] pub fn unpark(&self) { let mut guard = self.inner.lock.lock().unwrap(); if !*guard { @@ -362,6 +421,7 @@ impl Thread { } /// Get the thread's name. + #[stable] pub fn name(&self) -> Option<&str> { self.inner.name.as_ref().map(|s| s.as_slice()) } @@ -375,6 +435,7 @@ impl thread_info::NewThread for Thread { /// Indicates the manner in which a thread exited. /// /// A thread that completes without panicking is considered to exit successfully. +#[stable] pub type Result<T> = ::result::Result<T, Box<Any + Send>>; struct Packet<T>(Arc<UnsafeCell<Option<Result<T>>>>); @@ -382,21 +443,24 @@ struct Packet<T>(Arc<UnsafeCell<Option<Result<T>>>>); unsafe impl<T:'static+Send> Send for Packet<T> {} unsafe impl<T> Sync for Packet<T> {} -#[must_use] /// An RAII-style guard that will block until thread termination when dropped. /// /// The type `T` is the return type for the thread's main function. -pub struct JoinGuard<T> { +#[must_use] +#[unstable = "may change with specifics of new Send semantics"] +pub struct JoinGuard<'a, T: 'a> { native: imp::rust_thread, thread: Thread, joined: bool, packet: Packet<T>, } -unsafe impl<T: Send> Sync for JoinGuard<T> {} +#[stable] +unsafe impl<'a, T: Send + 'a> Sync for JoinGuard<'a, T> {} -impl<T: Send> JoinGuard<T> { +impl<'a, T: Send + 'a> JoinGuard<'a, T> { /// Extract a handle to the thread this guard will join on. + #[stable] pub fn thread(&self) -> &Thread { &self.thread } @@ -406,6 +470,7 @@ impl<T: Send> JoinGuard<T> { /// /// If the child thread panics, `Err` is returned with the parameter given /// to `panic`. + #[stable] pub fn join(mut self) -> Result<T> { assert!(!self.joined); unsafe { imp::join(self.native) }; @@ -414,8 +479,11 @@ impl<T: Send> JoinGuard<T> { (*self.packet.0.get()).take().unwrap() } } +} +impl<T: Send> JoinGuard<'static, T> { /// Detaches the child thread, allowing it to outlive its parent. + #[experimental = "unsure whether this API imposes limitations elsewhere"] pub fn detach(mut self) { unsafe { imp::detach(self.native) }; self.joined = true; // avoid joining in the destructor @@ -424,7 +492,7 @@ impl<T: Send> JoinGuard<T> { #[unsafe_destructor] #[stable] -impl<T: Send> Drop for JoinGuard<T> { +impl<'a, T: Send + 'a> Drop for JoinGuard<'a, T> { fn drop(&mut self) { if !self.joined { unsafe { imp::join(self.native) }; @@ -449,14 +517,14 @@ mod test { #[test] fn test_unnamed_thread() { - Thread::spawn(move|| { + Thread::scoped(move|| { assert!(Thread::current().name().is_none()); }).join().map_err(|_| ()).unwrap(); } #[test] fn test_named_thread() { - Builder::new().name("ada lovelace".to_string()).spawn(move|| { + Builder::new().name("ada lovelace".to_string()).scoped(move|| { assert!(Thread::current().name().unwrap() == "ada lovelace".to_string()); }).join().map_err(|_| ()).unwrap(); } @@ -466,13 +534,13 @@ mod test { let (tx, rx) = channel(); Thread::spawn(move|| { tx.send(()).unwrap(); - }).detach(); + }); rx.recv().unwrap(); } #[test] fn test_join_success() { - match Thread::spawn(move|| -> String { + match Thread::scoped(move|| -> String { "Success!".to_string() }).join().as_ref().map(|s| s.as_slice()) { result::Result::Ok("Success!") => (), @@ -482,7 +550,7 @@ mod test { #[test] fn test_join_panic() { - match Thread::spawn(move|| { + match Thread::scoped(move|| { panic!() }).join() { result::Result::Err(_) => (), @@ -504,7 +572,7 @@ mod test { } else { f(i - 1, tx); } - }).detach(); + }); } f(10, tx); @@ -518,8 +586,8 @@ mod test { Thread::spawn(move|| { Thread::spawn(move|| { tx.send(()).unwrap(); - }).detach(); - }).detach(); + }); + }); rx.recv().unwrap(); } @@ -542,7 +610,7 @@ mod test { #[test] fn test_avoid_copying_the_body_spawn() { avoid_copying_the_body(|v| { - Thread::spawn(move || v.invoke(())).detach(); + Thread::spawn(move || v.invoke(())); }); } @@ -551,14 +619,14 @@ mod test { avoid_copying_the_body(|f| { Thread::spawn(move|| { f.invoke(()); - }).detach(); + }); }) } #[test] fn test_avoid_copying_the_body_join() { avoid_copying_the_body(|f| { - let _ = Thread::spawn(move|| { + let _ = Thread::scoped(move|| { f.invoke(()) }).join(); }) @@ -574,21 +642,21 @@ mod test { fn child_no(x: uint) -> Thunk { return Thunk::new(move|| { if x < GENERATIONS { - Thread::spawn(move|| child_no(x+1).invoke(())).detach(); + Thread::spawn(move|| child_no(x+1).invoke(())); } }); } - Thread::spawn(|| child_no(0).invoke(())).detach(); + Thread::spawn(|| child_no(0).invoke(())); } #[test] fn test_simple_newsched_spawn() { - Thread::spawn(move || {}).detach(); + Thread::spawn(move || {}); } #[test] fn test_try_panic_message_static_str() { - match Thread::spawn(move|| { + match Thread::scoped(move|| { panic!("static string"); }).join() { Err(e) => { @@ -602,7 +670,7 @@ mod test { #[test] fn test_try_panic_message_owned_str() { - match Thread::spawn(move|| { + match Thread::scoped(move|| { panic!("owned string".to_string()); }).join() { Err(e) => { @@ -616,7 +684,7 @@ mod test { #[test] fn test_try_panic_message_any() { - match Thread::spawn(move|| { + match Thread::scoped(move|| { panic!(box 413u16 as Box<Any + Send>); }).join() { Err(e) => { @@ -634,7 +702,7 @@ mod test { fn test_try_panic_message_unit_struct() { struct Juju; - match Thread::spawn(move|| { + match Thread::scoped(move|| { panic!(Juju) }).join() { Err(ref e) if e.is::<Juju>() => {} @@ -648,7 +716,7 @@ mod test { let mut reader = ChanReader::new(rx); let stdout = ChanWriter::new(tx); - let r = Builder::new().stdout(box stdout as Box<Writer + Send>).spawn(move|| { + let r = Builder::new().stdout(box stdout as Box<Writer + Send>).scoped(move|| { print!("Hello, world!"); }).join(); assert!(r.is_ok()); diff --git a/src/libstd/thread_local/mod.rs b/src/libstd/thread_local/mod.rs index e0cbaa8ca50..e7c4e4ccdfb 100644 --- a/src/libstd/thread_local/mod.rs +++ b/src/libstd/thread_local/mod.rs @@ -40,8 +40,7 @@ use prelude::v1::*; use cell::UnsafeCell; -#[cfg_attr(stage0, macro_escape)] -#[cfg_attr(not(stage0), macro_use)] +#[macro_use] pub mod scoped; // Sure wish we had macro hygiene, no? @@ -87,7 +86,7 @@ pub mod __impl { /// assert_eq!(*f.borrow(), 1); /// *f.borrow_mut() = 3; /// }); -/// }).detach(); +/// }); /// /// // we retain our original value of 2 despite the child thread /// FOO.with(|f| { @@ -346,7 +345,7 @@ mod imp { pub dtor_running: UnsafeCell<bool>, // should be Cell } - unsafe impl<T> ::kinds::Sync for Key<T> { } + unsafe impl<T> ::marker::Sync for Key<T> { } #[doc(hidden)] impl<T> Key<T> { @@ -472,7 +471,7 @@ mod imp { pub os: OsStaticKey, } - unsafe impl<T> ::kinds::Sync for Key<T> { } + unsafe impl<T> ::marker::Sync for Key<T> { } struct Value<T: 'static> { key: &'static Key<T>, @@ -581,7 +580,7 @@ mod tests { } thread_local!(static FOO: Foo = foo()); - Thread::spawn(|| { + Thread::scoped(|| { assert!(FOO.state() == State::Uninitialized); FOO.with(|_| { assert!(FOO.state() == State::Valid); @@ -645,7 +644,7 @@ mod tests { } } - Thread::spawn(move|| { + Thread::scoped(move|| { drop(S1); }).join().ok().unwrap(); } @@ -663,7 +662,7 @@ mod tests { } } - Thread::spawn(move|| unsafe { + Thread::scoped(move|| unsafe { K1.with(|s| *s.get() = Some(S1)); }).join().ok().unwrap(); } diff --git a/src/libstd/thread_local/scoped.rs b/src/libstd/thread_local/scoped.rs index 714b71d5dbd..1fb5652bc0c 100644 --- a/src/libstd/thread_local/scoped.rs +++ b/src/libstd/thread_local/scoped.rs @@ -108,7 +108,7 @@ macro_rules! __scoped_thread_local_inner { const _INIT: __Key<$t> = __Key { inner: ::std::thread_local::scoped::__impl::KeyInner { inner: ::std::thread_local::scoped::__impl::OS_INIT, - marker: ::std::kinds::marker::InvariantType, + marker: ::std::marker::InvariantType, } }; @@ -211,7 +211,7 @@ mod imp { #[doc(hidden)] pub struct KeyInner<T> { pub inner: UnsafeCell<*mut T> } - unsafe impl<T> ::kinds::Sync for KeyInner<T> { } + unsafe impl<T> ::marker::Sync for KeyInner<T> { } #[doc(hidden)] impl<T> KeyInner<T> { @@ -224,7 +224,7 @@ mod imp { #[cfg(any(windows, target_os = "android", target_os = "ios", target_arch = "aarch64"))] mod imp { - use kinds::marker; + use marker; use sys_common::thread_local::StaticKey as OsStaticKey; #[doc(hidden)] @@ -233,7 +233,7 @@ mod imp { pub marker: marker::InvariantType<T>, } - unsafe impl<T> ::kinds::Sync for KeyInner<T> { } + unsafe impl<T> ::marker::Sync for KeyInner<T> { } #[doc(hidden)] impl<T> KeyInner<T> { diff --git a/src/libstd/thunk.rs b/src/libstd/thunk.rs index 067926042f1..1830a4df54a 100644 --- a/src/libstd/thunk.rs +++ b/src/libstd/thunk.rs @@ -12,7 +12,7 @@ #![allow(missing_docs)] use alloc::boxed::Box; -use core::kinds::Send; +use core::marker::Send; use core::ops::FnOnce; pub struct Thunk<A=(),R=()> { diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs index ac1f0c5d803..a651d927c14 100644 --- a/src/libstd/time/duration.rs +++ b/src/libstd/time/duration.rs @@ -19,9 +19,6 @@ use option::Option::{Some, None}; use num::Int; use result::Result::Ok; -// NOTE: for old macros; remove after the next snapshot -#[cfg(stage0)] use result::Result::Err; - /// The number of nanoseconds in a microsecond. const NANOS_PER_MICRO: i32 = 1000; /// The number of nanoseconds in a millisecond. @@ -48,7 +45,7 @@ macro_rules! try_opt { /// ISO 8601 time duration with nanosecond precision. /// This also allows for the negative duration; see individual methods for details. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Show)] pub struct Duration { secs: i64, nanos: i32, // Always 0 <= nanos < NANOS_PER_SEC @@ -337,7 +334,7 @@ impl Div<i32> for Duration { } } -impl fmt::Show for Duration { +impl fmt::String for Duration { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // technically speaking, negative duration is not valid ISO 8601, // but we need to print it anyway. |
