diff --git a/src/doc/guide-testing.md b/src/doc/guide-testing.md index 9d15f55f33f69..4128ae9538b6a 100644 --- a/src/doc/guide-testing.md +++ b/src/doc/guide-testing.md @@ -287,7 +287,7 @@ The benchmarking runner offers two ways to avoid this. Either, the closure that the `iter` method receives can return an arbitrary value which forces the optimizer to consider the result used and ensures it cannot remove the computation entirely. This could be done for the -example above by adjusting the `bh.iter` call to +example above by adjusting the `b.iter` call to ~~~ # struct X; impl X { fn iter(&self, _: || -> T) {} } let b = X; diff --git a/src/doc/intro.md b/src/doc/intro.md index 14c1f87fc1b62..a197115da90a0 100644 --- a/src/doc/intro.md +++ b/src/doc/intro.md @@ -494,14 +494,14 @@ non-deterministic aspect: $ cargo run Compiling hello_world v0.0.1 (file:///Users/you/src/hello_world) Running `target/hello_world` -numbers[1] is 2 -numbers[0] is 1 -numbers[2] is 3 +numbers[1] is 3 +numbers[0] is 2 +numbers[2] is 4 $ cargo run Running `target/hello_world` -numbers[2] is 3 -numbers[1] is 2 -numbers[0] is 1 +numbers[2] is 4 +numbers[1] is 3 +numbers[0] is 2 ``` Each time, we get a slightly different output, because each thread works in a diff --git a/src/doc/reference.md b/src/doc/reference.md index 084309e9978f6..6f165b679a3ec 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -400,11 +400,11 @@ An _integer literal_ has one of four forms: * A _decimal literal_ starts with a *decimal digit* and continues with any mixture of *decimal digits* and _underscores_. * A _hex literal_ starts with the character sequence `U+0030` `U+0078` - (`0x`) and continues as any mixture hex digits and underscores. + (`0x`) and continues as any mixture of hex digits and underscores. * An _octal literal_ starts with the character sequence `U+0030` `U+006F` - (`0o`) and continues as any mixture octal digits and underscores. + (`0o`) and continues as any mixture of octal digits and underscores. * A _binary literal_ starts with the character sequence `U+0030` `U+0062` - (`0b`) and continues as any mixture binary digits and underscores. + (`0b`) and continues as any mixture of binary digits and underscores. An integer literal may be followed (immediately, without any spaces) by an _integer suffix_, which changes the type of the literal. There are two kinds of @@ -944,10 +944,10 @@ An example of `use` declarations: ``` use std::iter::range_step; use std::option::{Some, None}; -use std::collections::hashmap::{mod, HashMap}; +use std::collections::hash_map::{mod, HashMap}; -# fn foo(_: T){} -# fn bar(map: HashMap, set: hashmap::HashSet){} +fn foo(_: T){} +fn bar(map1: HashMap, map2: hash_map::HashMap){} fn main() { // Equivalent to 'std::iter::range_step(0u, 10u, 2u);' @@ -957,10 +957,10 @@ fn main() { // std::option::None]);' foo(vec![Some(1.0f64), None]); - // Both `hash` and `HashMap` are in scope. - let map = HashMap::new(); - let set = hashmap::HashSet::new(); - bar(map, set); + // Both `hash_map` and `HashMap` are in scope. + let map1 = HashMap::new(); + let map2 = hash_map::HashMap::new(); + bar(map1, map2); } ``` @@ -2100,15 +2100,15 @@ plugins](guide-plugin.html#lint-plugins) can provide additional lint checks. ```{.ignore} mod m1 { // Missing documentation is ignored here - #[allow(missing_doc)] + #[allow(missing_docs)] pub fn undocumented_one() -> int { 1 } // Missing documentation signals a warning here - #[warn(missing_doc)] + #[warn(missing_docs)] pub fn undocumented_too() -> int { 2 } // Missing documentation signals an error here - #[deny(missing_doc)] + #[deny(missing_docs)] pub fn undocumented_end() -> int { 3 } } ``` @@ -2117,16 +2117,16 @@ This example shows how one can use `allow` and `warn` to toggle a particular check on and off. ```{.ignore} -#[warn(missing_doc)] +#[warn(missing_docs)] mod m2{ - #[allow(missing_doc)] + #[allow(missing_docs)] mod nested { // Missing documentation is ignored here pub fn undocumented_one() -> int { 1 } // Missing documentation signals a warning here, // despite the allow above. - #[warn(missing_doc)] + #[warn(missing_docs)] pub fn undocumented_two() -> int { 2 } } @@ -2139,10 +2139,10 @@ This example shows how one can use `forbid` to disallow uses of `allow` for that lint check. ```{.ignore} -#[forbid(missing_doc)] +#[forbid(missing_docs)] mod m3 { // Attempting to toggle warning signals an error here - #[allow(missing_doc)] + #[allow(missing_docs)] /// Returns 2. pub fn undocumented_too() -> int { 2 } } @@ -4096,7 +4096,7 @@ cause transitions between the states. The lifecycle states of a task are: * running * blocked -* panicked +* panicked * dead A task begins its lifecycle — once it has been spawned — in the diff --git a/src/doc/rust.css b/src/doc/rust.css index 4bbb809840211..9656d17721e47 100644 --- a/src/doc/rust.css +++ b/src/doc/rust.css @@ -62,6 +62,10 @@ body { font-size: 18px; color: #333; line-height: 1.428571429; + + -webkit-font-feature-settings: "kern", "liga"; + -moz-font-feature-settings: "kern", "liga"; + font-feature-settings: "kern", "liga"; } @media (min-width: 768px) { body { diff --git a/src/etc/unicode.py b/src/etc/unicode.py index d3de1d2b64e0a..4cb64b781af74 100755 --- a/src/etc/unicode.py +++ b/src/etc/unicode.py @@ -34,7 +34,7 @@ // NOTE: The following code was generated by "src/etc/unicode.py", do not edit directly -#![allow(missing_doc, non_uppercase_statics, non_snake_case)] +#![allow(missing_docs, non_uppercase_statics, non_snake_case)] ''' # Mapping taken from Table 12 from: diff --git a/src/libcollections/priority_queue.rs b/src/libcollections/binary_heap.rs similarity index 82% rename from src/libcollections/priority_queue.rs rename to src/libcollections/binary_heap.rs index 885b5c99c4501..8481111ae91a3 100644 --- a/src/libcollections/priority_queue.rs +++ b/src/libcollections/binary_heap.rs @@ -19,14 +19,14 @@ //! //! This is a larger example which implements [Dijkstra's algorithm][dijkstra] //! to solve the [shortest path problem][sssp] on a [directed graph][dir_graph]. -//! It showcases how to use the `PriorityQueue` with custom types. +//! It showcases how to use the `BinaryHeap` with custom types. //! //! [dijkstra]: http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm //! [sssp]: http://en.wikipedia.org/wiki/Shortest_path_problem //! [dir_graph]: http://en.wikipedia.org/wiki/Directed_graph //! //! ``` -//! use std::collections::PriorityQueue; +//! use std::collections::BinaryHeap; //! use std::uint; //! //! #[deriving(Eq, PartialEq)] @@ -68,7 +68,7 @@ //! // dist[node] = current shortest distance from `start` to `node` //! let mut dist = Vec::from_elem(adj_list.len(), uint::MAX); //! -//! let mut pq = PriorityQueue::new(); +//! let mut pq = BinaryHeap::new(); //! //! // We're at `start`, with a zero cost //! dist[start] = 0u; @@ -166,52 +166,52 @@ use vec::Vec; /// /// This will be a max-heap. #[deriving(Clone)] -pub struct PriorityQueue { +pub struct BinaryHeap { data: Vec, } -impl Default for PriorityQueue { +impl Default for BinaryHeap { #[inline] - fn default() -> PriorityQueue { PriorityQueue::new() } + fn default() -> BinaryHeap { BinaryHeap::new() } } -impl PriorityQueue { - /// Creates an empty `PriorityQueue` as a max-heap. +impl BinaryHeap { + /// Creates an empty `BinaryHeap` as a max-heap. /// /// # Example /// /// ``` - /// use std::collections::PriorityQueue; - /// let pq: PriorityQueue = PriorityQueue::new(); + /// use std::collections::BinaryHeap; + /// let pq: BinaryHeap = BinaryHeap::new(); /// ``` - pub fn new() -> PriorityQueue { PriorityQueue{data: vec!(),} } + pub fn new() -> BinaryHeap { BinaryHeap{data: vec!(),} } - /// Creates an empty `PriorityQueue` with a specific capacity. + /// Creates an empty `BinaryHeap` with a specific capacity. /// This preallocates enough memory for `capacity` elements, - /// so that the `PriorityQueue` does not have to be reallocated + /// so that the `BinaryHeap` does not have to be reallocated /// until it contains at least that many values. /// /// # Example /// /// ``` - /// use std::collections::PriorityQueue; - /// let pq: PriorityQueue = PriorityQueue::with_capacity(10u); + /// use std::collections::BinaryHeap; + /// let pq: BinaryHeap = BinaryHeap::with_capacity(10u); /// ``` - pub fn with_capacity(capacity: uint) -> PriorityQueue { - PriorityQueue { data: Vec::with_capacity(capacity) } + pub fn with_capacity(capacity: uint) -> BinaryHeap { + BinaryHeap { data: Vec::with_capacity(capacity) } } - /// Creates a `PriorityQueue` from a vector. This is sometimes called + /// Creates a `BinaryHeap` from a vector. This is sometimes called /// `heapifying` the vector. /// /// # Example /// /// ``` - /// use std::collections::PriorityQueue; - /// let pq = PriorityQueue::from_vec(vec![9i, 1, 2, 7, 3, 2]); + /// use std::collections::BinaryHeap; + /// let pq = BinaryHeap::from_vec(vec![9i, 1, 2, 7, 3, 2]); /// ``` - pub fn from_vec(xs: Vec) -> PriorityQueue { - let mut q = PriorityQueue{data: xs,}; + pub fn from_vec(xs: Vec) -> BinaryHeap { + let mut q = BinaryHeap{data: xs,}; let mut n = q.len() / 2; while n > 0 { n -= 1; @@ -226,8 +226,8 @@ impl PriorityQueue { /// # Example /// /// ``` - /// use std::collections::PriorityQueue; - /// let pq = PriorityQueue::from_vec(vec![1i, 2, 3, 4]); + /// use std::collections::BinaryHeap; + /// let pq = BinaryHeap::from_vec(vec![1i, 2, 3, 4]); /// /// // Print 1, 2, 3, 4 in arbitrary order /// for x in pq.iter() { @@ -243,9 +243,9 @@ impl PriorityQueue { /// # Example /// /// ``` - /// use std::collections::PriorityQueue; + /// use std::collections::BinaryHeap; /// - /// let mut pq = PriorityQueue::new(); + /// let mut pq = BinaryHeap::new(); /// assert_eq!(pq.top(), None); /// /// pq.push(1i); @@ -263,36 +263,36 @@ impl PriorityQueue { /// # Example /// /// ``` - /// use std::collections::PriorityQueue; + /// use std::collections::BinaryHeap; /// - /// let pq: PriorityQueue = PriorityQueue::with_capacity(100u); + /// let pq: BinaryHeap = BinaryHeap::with_capacity(100u); /// assert!(pq.capacity() >= 100u); /// ``` pub fn capacity(&self) -> uint { self.data.capacity() } - /// Reserves capacity for exactly `n` elements in the `PriorityQueue`. + /// Reserves capacity for exactly `n` elements in the `BinaryHeap`. /// Do nothing if the capacity is already sufficient. /// /// # Example /// /// ``` - /// use std::collections::PriorityQueue; + /// use std::collections::BinaryHeap; /// - /// let mut pq: PriorityQueue = PriorityQueue::new(); + /// let mut pq: BinaryHeap = BinaryHeap::new(); /// pq.reserve_exact(100u); /// assert!(pq.capacity() == 100u); /// ``` pub fn reserve_exact(&mut self, n: uint) { self.data.reserve_exact(n) } - /// Reserves capacity for at least `n` elements in the `PriorityQueue`. + /// Reserves capacity for at least `n` elements in the `BinaryHeap`. /// Do nothing if the capacity is already sufficient. /// /// # Example /// /// ``` - /// use std::collections::PriorityQueue; + /// use std::collections::BinaryHeap; /// - /// let mut pq: PriorityQueue = PriorityQueue::new(); + /// let mut pq: BinaryHeap = BinaryHeap::new(); /// pq.reserve(100u); /// assert!(pq.capacity() >= 100u); /// ``` @@ -306,9 +306,9 @@ impl PriorityQueue { /// # Example /// /// ``` - /// use std::collections::PriorityQueue; + /// use std::collections::BinaryHeap; /// - /// let mut pq = PriorityQueue::from_vec(vec![1i, 3]); + /// let mut pq = BinaryHeap::from_vec(vec![1i, 3]); /// /// assert_eq!(pq.pop(), Some(3i)); /// assert_eq!(pq.pop(), Some(1i)); @@ -332,9 +332,9 @@ impl PriorityQueue { /// # Example /// /// ``` - /// use std::collections::PriorityQueue; + /// use std::collections::BinaryHeap; /// - /// let mut pq = PriorityQueue::new(); + /// let mut pq = BinaryHeap::new(); /// pq.push(3i); /// pq.push(5i); /// pq.push(1i); @@ -354,9 +354,9 @@ impl PriorityQueue { /// # Example /// /// ``` - /// use std::collections::PriorityQueue; + /// use std::collections::BinaryHeap; /// - /// let mut pq = PriorityQueue::new(); + /// let mut pq = BinaryHeap::new(); /// pq.push(1i); /// pq.push(5i); /// @@ -380,9 +380,9 @@ impl PriorityQueue { /// # Example /// /// ``` - /// use std::collections::PriorityQueue; + /// use std::collections::BinaryHeap; /// - /// let mut pq = PriorityQueue::new(); + /// let mut pq = BinaryHeap::new(); /// /// assert_eq!(pq.replace(1i), None); /// assert_eq!(pq.replace(3i), Some(1i)); @@ -400,15 +400,15 @@ impl PriorityQueue { } } - /// Consumes the `PriorityQueue` and returns the underlying vector + /// Consumes the `BinaryHeap` and returns the underlying vector /// in arbitrary order. /// /// # Example /// /// ``` - /// use std::collections::PriorityQueue; + /// use std::collections::BinaryHeap; /// - /// let pq = PriorityQueue::from_vec(vec![1i, 2, 3, 4, 5, 6, 7]); + /// let pq = BinaryHeap::from_vec(vec![1i, 2, 3, 4, 5, 6, 7]); /// let vec = pq.into_vec(); /// /// // Will print in some order @@ -416,17 +416,17 @@ impl PriorityQueue { /// println!("{}", x); /// } /// ``` - pub fn into_vec(self) -> Vec { let PriorityQueue{data: v} = self; v } + pub fn into_vec(self) -> Vec { let BinaryHeap{data: v} = self; v } - /// Consumes the `PriorityQueue` and returns a vector in sorted + /// Consumes the `BinaryHeap` and returns a vector in sorted /// (ascending) order. /// /// # Example /// /// ``` - /// use std::collections::PriorityQueue; + /// use std::collections::BinaryHeap; /// - /// let mut pq = PriorityQueue::from_vec(vec![1i, 2, 4, 5, 7]); + /// let mut pq = BinaryHeap::from_vec(vec![1i, 2, 4, 5, 7]); /// pq.push(6); /// pq.push(3); /// @@ -504,7 +504,7 @@ impl PriorityQueue { pub fn clear(&mut self) { self.data.truncate(0) } } -/// `PriorityQueue` iterator. +/// `BinaryHeap` iterator. pub struct Items <'a, T:'a> { iter: slice::Items<'a, T>, } @@ -517,14 +517,14 @@ impl<'a, T> Iterator<&'a T> for Items<'a, T> { fn size_hint(&self) -> (uint, Option) { self.iter.size_hint() } } -impl FromIterator for PriorityQueue { - fn from_iter>(mut iter: Iter) -> PriorityQueue { +impl FromIterator for BinaryHeap { + fn from_iter>(mut iter: Iter) -> BinaryHeap { let vec: Vec = iter.collect(); - PriorityQueue::from_vec(vec) + BinaryHeap::from_vec(vec) } } -impl Extendable for PriorityQueue { +impl Extendable for BinaryHeap { fn extend>(&mut self, mut iter: Iter) { let (lower, _) = iter.size_hint(); @@ -541,14 +541,14 @@ impl Extendable for PriorityQueue { mod tests { use std::prelude::*; - use priority_queue::PriorityQueue; + use super::BinaryHeap; use vec::Vec; #[test] fn test_iterator() { let data = vec!(5i, 9, 3); let iterout = [9i, 5, 3]; - let pq = PriorityQueue::from_vec(data); + let pq = BinaryHeap::from_vec(data); let mut i = 0; for el in pq.iter() { assert_eq!(*el, iterout[i]); @@ -561,7 +561,7 @@ mod tests { let data = vec!(2u, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1); let mut sorted = data.clone(); sorted.sort(); - let mut heap = PriorityQueue::from_vec(data); + let mut heap = BinaryHeap::from_vec(data); while !heap.is_empty() { assert_eq!(heap.top().unwrap(), sorted.last().unwrap()); assert_eq!(heap.pop().unwrap(), sorted.pop().unwrap()); @@ -570,7 +570,7 @@ mod tests { #[test] fn test_push() { - let mut heap = PriorityQueue::from_vec(vec!(2i, 4, 9)); + let mut heap = BinaryHeap::from_vec(vec!(2i, 4, 9)); assert_eq!(heap.len(), 3); assert!(*heap.top().unwrap() == 9); heap.push(11); @@ -592,7 +592,7 @@ mod tests { #[test] fn test_push_unique() { - let mut heap = PriorityQueue::from_vec(vec!(box 2i, box 4, box 9)); + let mut heap = BinaryHeap::from_vec(vec!(box 2i, box 4, box 9)); assert_eq!(heap.len(), 3); assert!(*heap.top().unwrap() == box 9); heap.push(box 11); @@ -614,7 +614,7 @@ mod tests { #[test] fn test_push_pop() { - let mut heap = PriorityQueue::from_vec(vec!(5i, 5, 2, 1, 3)); + let mut heap = BinaryHeap::from_vec(vec!(5i, 5, 2, 1, 3)); assert_eq!(heap.len(), 5); assert_eq!(heap.push_pop(6), 6); assert_eq!(heap.len(), 5); @@ -628,7 +628,7 @@ mod tests { #[test] fn test_replace() { - let mut heap = PriorityQueue::from_vec(vec!(5i, 5, 2, 1, 3)); + let mut heap = BinaryHeap::from_vec(vec!(5i, 5, 2, 1, 3)); assert_eq!(heap.len(), 5); assert_eq!(heap.replace(6).unwrap(), 5); assert_eq!(heap.len(), 5); @@ -641,7 +641,7 @@ mod tests { } fn check_to_vec(mut data: Vec) { - let heap = PriorityQueue::from_vec(data.clone()); + let heap = BinaryHeap::from_vec(data.clone()); let mut v = heap.clone().into_vec(); v.sort(); data.sort(); @@ -669,19 +669,19 @@ mod tests { #[test] fn test_empty_pop() { - let mut heap: PriorityQueue = PriorityQueue::new(); + let mut heap: BinaryHeap = BinaryHeap::new(); assert!(heap.pop().is_none()); } #[test] fn test_empty_top() { - let empty: PriorityQueue = PriorityQueue::new(); + let empty: BinaryHeap = BinaryHeap::new(); assert!(empty.top().is_none()); } #[test] fn test_empty_replace() { - let mut heap: PriorityQueue = PriorityQueue::new(); + let mut heap: BinaryHeap = BinaryHeap::new(); heap.replace(5).is_none(); } @@ -689,7 +689,7 @@ mod tests { fn test_from_iter() { let xs = vec!(9u, 8, 7, 6, 5, 4, 3, 2, 1); - let mut q: PriorityQueue = xs.as_slice().iter().rev().map(|&x| x).collect(); + let mut q: BinaryHeap = xs.as_slice().iter().rev().map(|&x| x).collect(); for &x in xs.iter() { assert_eq!(q.pop().unwrap(), x); diff --git a/src/libcollections/bitv.rs b/src/libcollections/bit.rs similarity index 99% rename from src/libcollections/bitv.rs rename to src/libcollections/bit.rs index 26e0c73724c6a..b7085c96aed15 100644 --- a/src/libcollections/bitv.rs +++ b/src/libcollections/bit.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// FIXME(Gankro): Bitv and BitvSet are very tightly coupled. Ideally (for maintenance), +// they should be in separate files/modules, with BitvSet only using Bitv's public API. + //! Collections implemented with bit vectors. //! //! # Example @@ -1654,7 +1657,7 @@ mod tests { use std::rand::Rng; use test::Bencher; - use bitv::{Bitv, BitvSet, from_fn, from_bytes}; + use super::{Bitv, BitvSet, from_fn, from_bytes}; use bitv; use vec::Vec; diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 4570d49ba0ace..e3dfabfa29549 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -23,7 +23,7 @@ use core::default::Default; use core::{iter, fmt, mem}; use core::fmt::Show; -use ringbuf::RingBuf; +use ring_buf::RingBuf; /// A map based on a B-Tree. /// diff --git a/src/libcollections/btree/mod.rs b/src/libcollections/btree/mod.rs index 653de91c0ffd4..282128099da0a 100644 --- a/src/libcollections/btree/mod.rs +++ b/src/libcollections/btree/mod.rs @@ -8,27 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub use self::map::BTreeMap; -pub use self::map::Entries; -pub use self::map::MutEntries; -pub use self::map::MoveEntries; -pub use self::map::Keys; -pub use self::map::Values; -pub use self::map::Entry; -pub use self::map::Occupied; -pub use self::map::Vacant; -pub use self::map::OccupiedEntry; -pub use self::map::VacantEntry; - -pub use self::set::BTreeSet; -pub use self::set::Items; -pub use self::set::MoveItems; -pub use self::set::DifferenceItems; -pub use self::set::UnionItems; -pub use self::set::SymDifferenceItems; -pub use self::set::IntersectionItems; - - mod node; -mod map; -mod set; +pub mod map; +pub mod set; diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index eac74098758ae..27752207b9797 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -13,7 +13,7 @@ use core::prelude::*; -use super::{BTreeMap, Keys, MoveEntries}; +use btree_map::{BTreeMap, Keys, MoveEntries}; use std::hash::Hash; use core::default::Default; use core::{iter, fmt}; diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index b78c1897b0659..bcae4fe68c9b8 100644 --- a/src/libcollections/enum_set.rs +++ b/src/libcollections/enum_set.rs @@ -155,7 +155,7 @@ mod test { use std::prelude::*; use std::mem; - use enum_set::{EnumSet, CLike}; + use super::{EnumSet, CLike}; #[deriving(PartialEq, Show)] #[repr(uint)] diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index e28bc76648015..5ec8a85fb0fb7 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -37,34 +37,72 @@ extern crate alloc; #[cfg(test)] #[phase(plugin, link)] extern crate std; #[cfg(test)] #[phase(plugin, link)] extern crate log; -pub use bitv::{Bitv, BitvSet}; -pub use btree::{BTreeMap, BTreeSet}; + +pub use binary_heap::BinaryHeap; +pub use bitv::Bitv; +pub use bitv_set::BitvSet; +pub use btree_map::BTreeMap; +pub use btree_set::BTreeSet; pub use dlist::DList; pub use enum_set::EnumSet; -pub use priority_queue::PriorityQueue; -pub use ringbuf::RingBuf; -pub use smallintmap::SmallIntMap; +pub use ring_buf::RingBuf; pub use string::String; -pub use treemap::{TreeMap, TreeSet}; -pub use trie::{TrieMap, TrieSet}; +pub use tree_map::TreeMap; +pub use tree_set::TreeSet; +pub use trie_map::TrieMap; +pub use trie_set::TrieSet; pub use vec::Vec; +pub use vec_map::VecMap; mod macros; -pub mod bitv; -pub mod btree; +pub mod binary_heap; +mod bit; +mod btree; pub mod dlist; pub mod enum_set; -pub mod priority_queue; -pub mod ringbuf; -pub mod smallintmap; -pub mod treemap; -pub mod trie; +pub mod ring_buf; +mod tree; +mod trie; pub mod slice; pub mod str; pub mod string; pub mod vec; pub mod hash; +pub mod vec_map; + +pub mod bitv { + pub use bit::{Bitv, Bits, from_fn, from_bytes}; +} + +pub mod bitv_set { + pub use bit::{BitvSet, BitPositions, TwoBitPositions}; +} + +pub mod tree_map { + pub use tree::map::*; +} + +pub mod tree_set { + pub use tree::set::*; +} + +pub mod trie_map { + pub use trie::map::*; +} + +pub mod trie_set { + pub use trie::set::*; +} + +pub mod btree_map { + pub use btree::map::*; +} + +pub mod btree_set { + pub use btree::set::*; +} + #[cfg(test)] mod bench; diff --git a/src/libcollections/ringbuf.rs b/src/libcollections/ring_buf.rs similarity index 100% rename from src/libcollections/ringbuf.rs rename to src/libcollections/ring_buf.rs diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 5380f1cc1cd08..62182575c6d16 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -62,7 +62,7 @@ use core::prelude::{PartialEq, PartialOrd, Result, AsSlice, Some, Tuple2}; use core::prelude::{range}; use hash; -use ringbuf::RingBuf; +use ring_buf::RingBuf; use string::String; use unicode; use vec::Vec; diff --git a/src/libcollections/treemap.rs b/src/libcollections/tree/map.rs similarity index 67% rename from src/libcollections/treemap.rs rename to src/libcollections/tree/map.rs index 7e6efcb3d1266..9742bddb1f659 100644 --- a/src/libcollections/treemap.rs +++ b/src/libcollections/tree/map.rs @@ -8,37 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Maps are collections of unique keys with corresponding values, and sets are -//! just unique keys without a corresponding value. The `Map` and `Set` traits in -//! `std::container` define the basic interface. -//! -//! This crate defines the `TreeMap` and `TreeSet` types. Their keys must implement `Ord`. -//! -//! `TreeMap`s are ordered. -//! -//! ## Example -//! -//! ```{rust} -//! use std::collections::TreeSet; -//! -//! let mut tree_set = TreeSet::new(); -//! -//! tree_set.insert(2i); -//! tree_set.insert(1i); -//! tree_set.insert(3i); -//! -//! for i in tree_set.iter() { -//! println!("{}", i) // prints 1, then 2, then 3 -//! } -//! ``` - use core::prelude::*; use alloc::boxed::Box; use core::default::Default; use core::fmt; use core::fmt::Show; -use core::iter::Peekable; use core::iter; use core::mem::{replace, swap}; use core::ptr; @@ -378,7 +353,7 @@ impl TreeMap { RevMutEntries{iter: self.iter_mut()} } - /// Gets a lazy iterator that consumes the treemap. + /// Gets a lazy iterator that consumes the TreeMap. /// /// # Example /// @@ -592,7 +567,7 @@ impl TreeMap { /// # Example /// /// ``` - /// use collections::treemap::TreeMap; + /// use std::collections::TreeMap; /// /// fn get_headers() -> TreeMap { /// let mut result = TreeMap::new(); @@ -621,7 +596,9 @@ impl TreeMap { /// # Example /// /// ``` - /// let mut t = collections::treemap::TreeMap::new(); + /// use std::collections::TreeMap; + /// + /// let mut t = TreeMap::new(); /// t.insert("Content-Type", "application/xml"); /// t.insert("User-Agent", "Curl-Rust/0.1"); /// @@ -1075,616 +1052,6 @@ impl Iterator<(K, V)> for MoveEntries { } -impl<'a, T> Iterator<&'a T> for SetItems<'a, T> { - #[inline] - fn next(&mut self) -> Option<&'a T> { - self.iter.next().map(|(value, _)| value) - } -} - -impl<'a, T> Iterator<&'a T> for RevSetItems<'a, T> { - #[inline] - fn next(&mut self) -> Option<&'a T> { - self.iter.next().map(|(value, _)| value) - } -} - -/// An implementation of the `Set` trait on top of the `TreeMap` container. The -/// only requirement is that the type of the elements contained ascribes to the -/// `Ord` trait. -/// -/// ## Example -/// -/// ```{rust} -/// use std::collections::TreeSet; -/// -/// let mut set = TreeSet::new(); -/// -/// set.insert(2i); -/// set.insert(1i); -/// set.insert(3i); -/// -/// for i in set.iter() { -/// println!("{}", i) // prints 1, then 2, then 3 -/// } -/// -/// set.remove(&3); -/// -/// if !set.contains(&3) { -/// println!("set does not contain a 3 anymore"); -/// } -/// ``` -/// -/// The easiest way to use `TreeSet` with a custom type is to implement `Ord`. -/// We must also implement `PartialEq`, `Eq` and `PartialOrd`. -/// -/// ``` -/// use std::collections::TreeSet; -/// -/// // We need `Eq` and `PartialEq`, these can be derived. -/// #[deriving(Eq, PartialEq)] -/// struct Troll<'a> { -/// name: &'a str, -/// level: uint, -/// } -/// -/// // Implement `Ord` and sort trolls by level. -/// impl<'a> Ord for Troll<'a> { -/// fn cmp(&self, other: &Troll) -> Ordering { -/// // If we swap `self` and `other`, we get descending ordering. -/// self.level.cmp(&other.level) -/// } -/// } -/// -/// // `PartialOrd` needs to be implemented as well. -/// impl<'a> PartialOrd for Troll<'a> { -/// fn partial_cmp(&self, other: &Troll) -> Option { -/// Some(self.cmp(other)) -/// } -/// } -/// -/// let mut trolls = TreeSet::new(); -/// -/// trolls.insert(Troll { name: "Orgarr", level: 2 }); -/// trolls.insert(Troll { name: "Blargarr", level: 3 }); -/// trolls.insert(Troll { name: "Kron the Smelly One", level: 4 }); -/// trolls.insert(Troll { name: "Wartilda", level: 1 }); -/// -/// println!("You are facing {} trolls!", trolls.len()); -/// -/// // Print the trolls, ordered by level with smallest level first -/// for x in trolls.iter() { -/// println!("level {}: {}!", x.level, x.name); -/// } -/// -/// // Kill all trolls -/// trolls.clear(); -/// assert_eq!(trolls.len(), 0); -/// ``` -#[deriving(Clone)] -pub struct TreeSet { - map: TreeMap -} - -impl PartialEq for TreeSet { - #[inline] - fn eq(&self, other: &TreeSet) -> bool { self.map == other.map } -} - -impl Eq for TreeSet {} - -impl PartialOrd for TreeSet { - #[inline] - fn partial_cmp(&self, other: &TreeSet) -> Option { - self.map.partial_cmp(&other.map) - } -} - -impl Ord for TreeSet { - #[inline] - fn cmp(&self, other: &TreeSet) -> Ordering { - iter::order::cmp(self.iter(), other.iter()) - } -} - -impl Show for TreeSet { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "{{")); - - for (i, x) in self.iter().enumerate() { - if i != 0 { try!(write!(f, ", ")); } - try!(write!(f, "{}", *x)); - } - - write!(f, "}}") - } -} - -impl Default for TreeSet { - #[inline] - fn default() -> TreeSet { TreeSet::new() } -} - -impl TreeSet { - /// Creates an empty `TreeSet`. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// let mut set: TreeSet = TreeSet::new(); - /// ``` - #[inline] - pub fn new() -> TreeSet { TreeSet{map: TreeMap::new()} } - - /// Gets a lazy iterator over the values in the set, in ascending order. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// let set: TreeSet = [1i, 4, 3, 5, 2].iter().map(|&x| x).collect(); - /// - /// // Will print in ascending order. - /// for x in set.iter() { - /// println!("{}", x); - /// } - /// ``` - #[inline] - pub fn iter<'a>(&'a self) -> SetItems<'a, T> { - SetItems{iter: self.map.iter()} - } - - /// Gets a lazy iterator over the values in the set, in descending order. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// let set: TreeSet = [1i, 4, 3, 5, 2].iter().map(|&x| x).collect(); - /// - /// // Will print in descending order. - /// for x in set.rev_iter() { - /// println!("{}", x); - /// } - /// ``` - #[inline] - pub fn rev_iter<'a>(&'a self) -> RevSetItems<'a, T> { - RevSetItems{iter: self.map.rev_iter()} - } - - /// Creates a consuming iterator, that is, one that moves each value out of the - /// set in ascending order. The set cannot be used after calling this. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// let set: TreeSet = [1i, 4, 3, 5, 2].iter().map(|&x| x).collect(); - /// - /// // Not possible with a regular `.iter()` - /// let v: Vec = set.into_iter().collect(); - /// assert_eq!(v, vec![1, 2, 3, 4, 5]); - /// ``` - #[inline] - pub fn into_iter(self) -> MoveSetItems { - self.map.into_iter().map(|(value, _)| value) - } - - /// Gets a lazy iterator pointing to the first value not less than `v` (greater or equal). - /// If all elements in the set are less than `v` empty iterator is returned. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// let set: TreeSet = [2, 4, 6, 8].iter().map(|&x| x).collect(); - /// - /// assert_eq!(set.lower_bound(&4).next(), Some(&4)); - /// assert_eq!(set.lower_bound(&5).next(), Some(&6)); - /// assert_eq!(set.lower_bound(&10).next(), None); - /// ``` - #[inline] - pub fn lower_bound<'a>(&'a self, v: &T) -> SetItems<'a, T> { - SetItems{iter: self.map.lower_bound(v)} - } - - /// Gets a lazy iterator pointing to the first value greater than `v`. - /// If all elements in the set are less than or equal to `v` an - /// empty iterator is returned. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// let set: TreeSet = [2, 4, 6, 8].iter().map(|&x| x).collect(); - /// - /// assert_eq!(set.upper_bound(&4).next(), Some(&6)); - /// assert_eq!(set.upper_bound(&5).next(), Some(&6)); - /// assert_eq!(set.upper_bound(&10).next(), None); - /// ``` - #[inline] - pub fn upper_bound<'a>(&'a self, v: &T) -> SetItems<'a, T> { - SetItems{iter: self.map.upper_bound(v)} - } - - /// Visits the values representing the difference, in ascending order. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// - /// let a: TreeSet = [1, 2, 3].iter().map(|&x| x).collect(); - /// let b: TreeSet = [3, 4, 5].iter().map(|&x| x).collect(); - /// - /// // Can be seen as `a - b`. - /// for x in a.difference(&b) { - /// println!("{}", x); // Print 1 then 2 - /// } - /// - /// let diff: TreeSet = a.difference(&b).map(|&x| x).collect(); - /// assert_eq!(diff, [1, 2].iter().map(|&x| x).collect()); - /// - /// // Note that difference is not symmetric, - /// // and `b - a` means something else: - /// let diff: TreeSet = b.difference(&a).map(|&x| x).collect(); - /// assert_eq!(diff, [4, 5].iter().map(|&x| x).collect()); - /// ``` - pub fn difference<'a>(&'a self, other: &'a TreeSet) -> DifferenceItems<'a, T> { - DifferenceItems{a: self.iter().peekable(), b: other.iter().peekable()} - } - - /// Visits the values representing the symmetric difference, in ascending order. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// - /// let a: TreeSet = [1, 2, 3].iter().map(|&x| x).collect(); - /// let b: TreeSet = [3, 4, 5].iter().map(|&x| x).collect(); - /// - /// // Print 1, 2, 4, 5 in ascending order. - /// for x in a.symmetric_difference(&b) { - /// println!("{}", x); - /// } - /// - /// let diff1: TreeSet = a.symmetric_difference(&b).map(|&x| x).collect(); - /// let diff2: TreeSet = b.symmetric_difference(&a).map(|&x| x).collect(); - /// - /// assert_eq!(diff1, diff2); - /// assert_eq!(diff1, [1, 2, 4, 5].iter().map(|&x| x).collect()); - /// ``` - pub fn symmetric_difference<'a>(&'a self, other: &'a TreeSet) - -> SymDifferenceItems<'a, T> { - SymDifferenceItems{a: self.iter().peekable(), b: other.iter().peekable()} - } - - /// Visits the values representing the intersection, in ascending order. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// - /// let a: TreeSet = [1, 2, 3].iter().map(|&x| x).collect(); - /// let b: TreeSet = [2, 3, 4].iter().map(|&x| x).collect(); - /// - /// // Print 2, 3 in ascending order. - /// for x in a.intersection(&b) { - /// println!("{}", x); - /// } - /// - /// let diff: TreeSet = a.intersection(&b).map(|&x| x).collect(); - /// assert_eq!(diff, [2, 3].iter().map(|&x| x).collect()); - /// ``` - pub fn intersection<'a>(&'a self, other: &'a TreeSet) - -> IntersectionItems<'a, T> { - IntersectionItems{a: self.iter().peekable(), b: other.iter().peekable()} - } - - /// Visits the values representing the union, in ascending order. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// - /// let a: TreeSet = [1, 2, 3].iter().map(|&x| x).collect(); - /// let b: TreeSet = [3, 4, 5].iter().map(|&x| x).collect(); - /// - /// // Print 1, 2, 3, 4, 5 in ascending order. - /// for x in a.union(&b) { - /// println!("{}", x); - /// } - /// - /// let diff: TreeSet = a.union(&b).map(|&x| x).collect(); - /// assert_eq!(diff, [1, 2, 3, 4, 5].iter().map(|&x| x).collect()); - /// ``` - pub fn union<'a>(&'a self, other: &'a TreeSet) -> UnionItems<'a, T> { - UnionItems{a: self.iter().peekable(), b: other.iter().peekable()} - } - - /// Return the number of elements in the set - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// - /// let mut v = TreeSet::new(); - /// assert_eq!(v.len(), 0); - /// v.insert(1i); - /// assert_eq!(v.len(), 1); - /// ``` - #[inline] - pub fn len(&self) -> uint { self.map.len() } - - /// Returns true if the set contains no elements - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// - /// let mut v = TreeSet::new(); - /// assert!(v.is_empty()); - /// v.insert(1i); - /// assert!(!v.is_empty()); - /// ``` - pub fn is_empty(&self) -> bool { self.len() == 0 } - - /// Clears the set, removing all values. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// - /// let mut v = TreeSet::new(); - /// v.insert(1i); - /// v.clear(); - /// assert!(v.is_empty()); - /// ``` - #[inline] - pub fn clear(&mut self) { self.map.clear() } - - /// Returns `true` if the set contains a value. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// - /// let set: TreeSet = [1i, 2, 3].iter().map(|&x| x).collect(); - /// assert_eq!(set.contains(&1), true); - /// assert_eq!(set.contains(&4), false); - /// ``` - #[inline] - pub fn contains(&self, value: &T) -> bool { - self.map.contains_key(value) - } - - /// Returns `true` if the set has no elements in common with `other`. - /// This is equivalent to checking for an empty intersection. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// - /// let a: TreeSet = [1i, 2, 3].iter().map(|&x| x).collect(); - /// let mut b: TreeSet = TreeSet::new(); - /// - /// assert_eq!(a.is_disjoint(&b), true); - /// b.insert(4); - /// assert_eq!(a.is_disjoint(&b), true); - /// b.insert(1); - /// assert_eq!(a.is_disjoint(&b), false); - /// ``` - pub fn is_disjoint(&self, other: &TreeSet) -> bool { - self.intersection(other).next().is_none() - } - - /// Returns `true` if the set is a subset of another. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// - /// let sup: TreeSet = [1i, 2, 3].iter().map(|&x| x).collect(); - /// let mut set: TreeSet = TreeSet::new(); - /// - /// assert_eq!(set.is_subset(&sup), true); - /// set.insert(2); - /// assert_eq!(set.is_subset(&sup), true); - /// set.insert(4); - /// assert_eq!(set.is_subset(&sup), false); - /// ``` - pub fn is_subset(&self, other: &TreeSet) -> bool { - let mut x = self.iter(); - let mut y = other.iter(); - let mut a = x.next(); - let mut b = y.next(); - while a.is_some() { - if b.is_none() { - return false; - } - - let a1 = a.unwrap(); - let b1 = b.unwrap(); - - match b1.cmp(a1) { - Less => (), - Greater => return false, - Equal => a = x.next(), - } - - b = y.next(); - } - true - } - - /// Returns `true` if the set is a superset of another. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// - /// let sub: TreeSet = [1i, 2].iter().map(|&x| x).collect(); - /// let mut set: TreeSet = TreeSet::new(); - /// - /// assert_eq!(set.is_superset(&sub), false); - /// - /// set.insert(0); - /// set.insert(1); - /// assert_eq!(set.is_superset(&sub), false); - /// - /// set.insert(2); - /// assert_eq!(set.is_superset(&sub), true); - /// ``` - pub fn is_superset(&self, other: &TreeSet) -> bool { - other.is_subset(self) - } - - /// Adds a value to the set. Returns `true` if the value was not already - /// present in the set. - /// - /// # Example - /// - /// ``` - /// use std::collections::BTreeSet; - /// - /// let mut set = BTreeSet::new(); - /// - /// assert_eq!(set.insert(2i), true); - /// assert_eq!(set.insert(2i), false); - /// assert_eq!(set.len(), 1); - /// ``` - #[inline] - pub fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()) } - - /// Removes a value from the set. Returns `true` if the value was - /// present in the set. - /// - /// # Example - /// - /// ``` - /// use std::collections::BTreeSet; - /// - /// let mut set = BTreeSet::new(); - /// - /// set.insert(2i); - /// assert_eq!(set.remove(&2), true); - /// assert_eq!(set.remove(&2), false); - /// ``` - #[inline] - pub fn remove(&mut self, value: &T) -> bool { self.map.remove(value) } -} - -/// A lazy forward iterator over a set. -pub struct SetItems<'a, T:'a> { - iter: Entries<'a, T, ()> -} - -/// A lazy backward iterator over a set. -pub struct RevSetItems<'a, T:'a> { - iter: RevEntries<'a, T, ()> -} - -/// A lazy forward iterator over a set that consumes the set while iterating. -pub type MoveSetItems = iter::Map<'static, (T, ()), T, MoveEntries>; - -/// A lazy iterator producing elements in the set difference (in-order). -pub struct DifferenceItems<'a, T:'a> { - a: Peekable<&'a T, SetItems<'a, T>>, - b: Peekable<&'a T, SetItems<'a, T>>, -} - -/// A lazy iterator producing elements in the set symmetric difference (in-order). -pub struct SymDifferenceItems<'a, T:'a> { - a: Peekable<&'a T, SetItems<'a, T>>, - b: Peekable<&'a T, SetItems<'a, T>>, -} - -/// A lazy iterator producing elements in the set intersection (in-order). -pub struct IntersectionItems<'a, T:'a> { - a: Peekable<&'a T, SetItems<'a, T>>, - b: Peekable<&'a T, SetItems<'a, T>>, -} - -/// A lazy iterator producing elements in the set union (in-order). -pub struct UnionItems<'a, T:'a> { - a: Peekable<&'a T, SetItems<'a, T>>, - b: Peekable<&'a T, SetItems<'a, T>>, -} - -/// Compare `x` and `y`, but return `short` if x is None and `long` if y is None -fn cmp_opt(x: Option<&T>, y: Option<&T>, - short: Ordering, long: Ordering) -> Ordering { - match (x, y) { - (None , _ ) => short, - (_ , None ) => long, - (Some(x1), Some(y1)) => x1.cmp(y1), - } -} - -impl<'a, T: Ord> Iterator<&'a T> for DifferenceItems<'a, T> { - fn next(&mut self) -> Option<&'a T> { - loop { - match cmp_opt(self.a.peek(), self.b.peek(), Less, Less) { - Less => return self.a.next(), - Equal => { self.a.next(); self.b.next(); } - Greater => { self.b.next(); } - } - } - } -} - -impl<'a, T: Ord> Iterator<&'a T> for SymDifferenceItems<'a, T> { - fn next(&mut self) -> Option<&'a T> { - loop { - match cmp_opt(self.a.peek(), self.b.peek(), Greater, Less) { - Less => return self.a.next(), - Equal => { self.a.next(); self.b.next(); } - Greater => return self.b.next(), - } - } - } -} - -impl<'a, T: Ord> Iterator<&'a T> for IntersectionItems<'a, T> { - fn next(&mut self) -> Option<&'a T> { - loop { - let o_cmp = match (self.a.peek(), self.b.peek()) { - (None , _ ) => None, - (_ , None ) => None, - (Some(a1), Some(b1)) => Some(a1.cmp(b1)), - }; - match o_cmp { - None => return None, - Some(Less) => { self.a.next(); } - Some(Equal) => { self.b.next(); return self.a.next() } - Some(Greater) => { self.b.next(); } - } - } - } -} - -impl<'a, T: Ord> Iterator<&'a T> for UnionItems<'a, T> { - fn next(&mut self) -> Option<&'a T> { - loop { - match cmp_opt(self.a.peek(), self.b.peek(), Greater, Less) { - Less => return self.a.next(), - Equal => { self.b.next(); return self.a.next() } - Greater => return self.b.next(), - } - } - } -} // Nodes keep track of their level in the tree, starting at 1 in the @@ -1908,30 +1275,6 @@ impl, V: Hash> Hash for TreeMap { } } -impl FromIterator for TreeSet { - fn from_iter>(iter: Iter) -> TreeSet { - let mut set = TreeSet::new(); - set.extend(iter); - set - } -} - -impl Extendable for TreeSet { - #[inline] - fn extend>(&mut self, mut iter: Iter) { - for elem in iter { - self.insert(elem); - } - } -} - -impl> Hash for TreeSet { - fn hash(&self, state: &mut S) { - for elt in self.iter() { - elt.hash(state); - } - } -} #[cfg(test)] mod test_treemap { @@ -2448,6 +1791,22 @@ mod test_treemap { map[4]; } + + #[test] + fn test_swap() { + let mut m = TreeMap::new(); + assert_eq!(m.swap(1u, 2i), None); + assert_eq!(m.swap(1u, 3i), Some(2)); + assert_eq!(m.swap(1u, 4i), Some(3)); + } + + #[test] + fn test_pop() { + let mut m = TreeMap::new(); + m.insert(1u, 2i); + assert_eq!(m.pop(&1), Some(2)); + assert_eq!(m.pop(&1), None); + } } #[cfg(test)] @@ -2557,311 +1916,3 @@ mod bench { } } -#[cfg(test)] -mod test_set { - use std::prelude::*; - use std::hash; - - use super::{TreeMap, TreeSet}; - - #[test] - fn test_clear() { - let mut s = TreeSet::new(); - s.clear(); - assert!(s.insert(5i)); - assert!(s.insert(12)); - assert!(s.insert(19)); - s.clear(); - assert!(!s.contains(&5)); - assert!(!s.contains(&12)); - assert!(!s.contains(&19)); - assert!(s.is_empty()); - } - - #[test] - fn test_disjoint() { - let mut xs = TreeSet::new(); - let mut ys = TreeSet::new(); - assert!(xs.is_disjoint(&ys)); - assert!(ys.is_disjoint(&xs)); - assert!(xs.insert(5i)); - assert!(ys.insert(11i)); - assert!(xs.is_disjoint(&ys)); - assert!(ys.is_disjoint(&xs)); - assert!(xs.insert(7)); - assert!(xs.insert(19)); - assert!(xs.insert(4)); - assert!(ys.insert(2)); - assert!(ys.insert(-11)); - assert!(xs.is_disjoint(&ys)); - assert!(ys.is_disjoint(&xs)); - assert!(ys.insert(7)); - assert!(!xs.is_disjoint(&ys)); - assert!(!ys.is_disjoint(&xs)); - } - - #[test] - fn test_subset_and_superset() { - let mut a = TreeSet::new(); - assert!(a.insert(0i)); - assert!(a.insert(5)); - assert!(a.insert(11)); - assert!(a.insert(7)); - - let mut b = TreeSet::new(); - assert!(b.insert(0i)); - assert!(b.insert(7)); - assert!(b.insert(19)); - assert!(b.insert(250)); - assert!(b.insert(11)); - assert!(b.insert(200)); - - assert!(!a.is_subset(&b)); - assert!(!a.is_superset(&b)); - assert!(!b.is_subset(&a)); - assert!(!b.is_superset(&a)); - - assert!(b.insert(5)); - - assert!(a.is_subset(&b)); - assert!(!a.is_superset(&b)); - assert!(!b.is_subset(&a)); - assert!(b.is_superset(&a)); - } - - #[test] - fn test_iterator() { - let mut m = TreeSet::new(); - - assert!(m.insert(3i)); - assert!(m.insert(0)); - assert!(m.insert(4)); - assert!(m.insert(2)); - assert!(m.insert(1)); - - let mut n = 0; - for x in m.iter() { - assert_eq!(*x, n); - n += 1 - } - } - - #[test] - fn test_rev_iter() { - let mut m = TreeSet::new(); - - assert!(m.insert(3i)); - assert!(m.insert(0)); - assert!(m.insert(4)); - assert!(m.insert(2)); - assert!(m.insert(1)); - - let mut n = 4; - for x in m.rev_iter() { - assert_eq!(*x, n); - n -= 1; - } - } - - #[test] - fn test_move_iter() { - let s: TreeSet = range(0i, 5).collect(); - - let mut n = 0; - for x in s.into_iter() { - assert_eq!(x, n); - n += 1; - } - } - - #[test] - fn test_move_iter_size_hint() { - let s: TreeSet = vec!(0i, 1).into_iter().collect(); - - let mut it = s.into_iter(); - - assert_eq!(it.size_hint(), (2, Some(2))); - assert!(it.next() != None); - - assert_eq!(it.size_hint(), (1, Some(1))); - assert!(it.next() != None); - - assert_eq!(it.size_hint(), (0, Some(0))); - assert_eq!(it.next(), None); - } - - #[test] - fn test_clone_eq() { - let mut m = TreeSet::new(); - - m.insert(1i); - m.insert(2); - - assert!(m.clone() == m); - } - - #[test] - fn test_hash() { - let mut x = TreeSet::new(); - let mut y = TreeSet::new(); - - x.insert(1i); - x.insert(2); - x.insert(3); - - y.insert(3i); - y.insert(2); - y.insert(1); - - assert!(hash::hash(&x) == hash::hash(&y)); - } - - fn check(a: &[int], - b: &[int], - expected: &[int], - f: |&TreeSet, &TreeSet, f: |&int| -> bool| -> bool) { - let mut set_a = TreeSet::new(); - let mut set_b = TreeSet::new(); - - for x in a.iter() { assert!(set_a.insert(*x)) } - for y in b.iter() { assert!(set_b.insert(*y)) } - - let mut i = 0; - f(&set_a, &set_b, |x| { - assert_eq!(*x, expected[i]); - i += 1; - true - }); - assert_eq!(i, expected.len()); - } - - #[test] - fn test_intersection() { - fn check_intersection(a: &[int], b: &[int], expected: &[int]) { - check(a, b, expected, |x, y, f| x.intersection(y).all(f)) - } - - check_intersection([], [], []); - check_intersection([1, 2, 3], [], []); - check_intersection([], [1, 2, 3], []); - check_intersection([2], [1, 2, 3], [2]); - check_intersection([1, 2, 3], [2], [2]); - check_intersection([11, 1, 3, 77, 103, 5, -5], - [2, 11, 77, -9, -42, 5, 3], - [3, 5, 11, 77]); - } - - #[test] - fn test_difference() { - fn check_difference(a: &[int], b: &[int], expected: &[int]) { - check(a, b, expected, |x, y, f| x.difference(y).all(f)) - } - - check_difference([], [], []); - check_difference([1, 12], [], [1, 12]); - check_difference([], [1, 2, 3, 9], []); - check_difference([1, 3, 5, 9, 11], - [3, 9], - [1, 5, 11]); - check_difference([-5, 11, 22, 33, 40, 42], - [-12, -5, 14, 23, 34, 38, 39, 50], - [11, 22, 33, 40, 42]); - } - - #[test] - fn test_symmetric_difference() { - fn check_symmetric_difference(a: &[int], b: &[int], - expected: &[int]) { - check(a, b, expected, |x, y, f| x.symmetric_difference(y).all(f)) - } - - check_symmetric_difference([], [], []); - check_symmetric_difference([1, 2, 3], [2], [1, 3]); - check_symmetric_difference([2], [1, 2, 3], [1, 3]); - check_symmetric_difference([1, 3, 5, 9, 11], - [-2, 3, 9, 14, 22], - [-2, 1, 5, 11, 14, 22]); - } - - #[test] - fn test_union() { - fn check_union(a: &[int], b: &[int], - expected: &[int]) { - check(a, b, expected, |x, y, f| x.union(y).all(f)) - } - - check_union([], [], []); - check_union([1, 2, 3], [2], [1, 2, 3]); - check_union([2], [1, 2, 3], [1, 2, 3]); - check_union([1, 3, 5, 9, 11, 16, 19, 24], - [-2, 1, 5, 9, 13, 19], - [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]); - } - - #[test] - fn test_zip() { - let mut x = TreeSet::new(); - x.insert(5u); - x.insert(12u); - x.insert(11u); - - let mut y = TreeSet::new(); - y.insert("foo"); - y.insert("bar"); - - let x = x; - let y = y; - let mut z = x.iter().zip(y.iter()); - - // FIXME: #5801: this needs a type hint to compile... - let result: Option<(&uint, & &'static str)> = z.next(); - assert_eq!(result.unwrap(), (&5u, &("bar"))); - - let result: Option<(&uint, & &'static str)> = z.next(); - assert_eq!(result.unwrap(), (&11u, &("foo"))); - - let result: Option<(&uint, & &'static str)> = z.next(); - assert!(result.is_none()); - } - - #[test] - fn test_swap() { - let mut m = TreeMap::new(); - assert_eq!(m.swap(1u, 2i), None); - assert_eq!(m.swap(1u, 3i), Some(2)); - assert_eq!(m.swap(1u, 4i), Some(3)); - } - - #[test] - fn test_pop() { - let mut m = TreeMap::new(); - m.insert(1u, 2i); - assert_eq!(m.pop(&1), Some(2)); - assert_eq!(m.pop(&1), None); - } - - #[test] - fn test_from_iter() { - let xs = [1i, 2, 3, 4, 5, 6, 7, 8, 9]; - - let set: TreeSet = xs.iter().map(|&x| x).collect(); - - for x in xs.iter() { - assert!(set.contains(x)); - } - } - - #[test] - fn test_show() { - let mut set: TreeSet = TreeSet::new(); - let empty: TreeSet = TreeSet::new(); - - set.insert(1); - set.insert(2); - - let set_str = format!("{}", set); - - assert!(set_str == "{1, 2}".to_string()); - assert_eq!(format!("{}", empty), "{}".to_string()); - } -} diff --git a/src/libcollections/tree/mod.rs b/src/libcollections/tree/mod.rs new file mode 100644 index 0000000000000..ac8279c92feeb --- /dev/null +++ b/src/libcollections/tree/mod.rs @@ -0,0 +1,36 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Maps are collections of unique keys with corresponding values, and sets are +//! just unique keys without a corresponding value. The `Map` and `Set` traits in +//! `std::container` define the basic interface. +//! +//! This crate defines the `TreeMap` and `TreeSet` types. Their keys must implement `Ord`. +//! +//! `TreeMap`s are ordered. +//! +//! ## Example +//! +//! ```{rust} +//! use std::collections::TreeSet; +//! +//! let mut tree_set = TreeSet::new(); +//! +//! tree_set.insert(2i); +//! tree_set.insert(1i); +//! tree_set.insert(3i); +//! +//! for i in tree_set.iter() { +//! println!("{}", i) // prints 1, then 2, then 3 +//! } +//! ``` + +pub mod map; +pub mod set; \ No newline at end of file diff --git a/src/libcollections/tree/set.rs b/src/libcollections/tree/set.rs new file mode 100644 index 0000000000000..d24a8234b20b8 --- /dev/null +++ b/src/libcollections/tree/set.rs @@ -0,0 +1,950 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::prelude::*; + +use core::default::Default; +use core::fmt; +use core::fmt::Show; +use core::iter::Peekable; +use core::iter; +use std::hash::{Writer, Hash}; + +use tree_map::{TreeMap, Entries, RevEntries, MoveEntries}; + +/// An implementation of the `Set` trait on top of the `TreeMap` container. The +/// only requirement is that the type of the elements contained ascribes to the +/// `Ord` trait. +/// +/// ## Example +/// +/// ```{rust} +/// use std::collections::TreeSet; +/// +/// let mut set = TreeSet::new(); +/// +/// set.insert(2i); +/// set.insert(1i); +/// set.insert(3i); +/// +/// for i in set.iter() { +/// println!("{}", i) // prints 1, then 2, then 3 +/// } +/// +/// set.remove(&3); +/// +/// if !set.contains(&3) { +/// println!("set does not contain a 3 anymore"); +/// } +/// ``` +/// +/// The easiest way to use `TreeSet` with a custom type is to implement `Ord`. +/// We must also implement `PartialEq`, `Eq` and `PartialOrd`. +/// +/// ``` +/// use std::collections::TreeSet; +/// +/// // We need `Eq` and `PartialEq`, these can be derived. +/// #[deriving(Eq, PartialEq)] +/// struct Troll<'a> { +/// name: &'a str, +/// level: uint, +/// } +/// +/// // Implement `Ord` and sort trolls by level. +/// impl<'a> Ord for Troll<'a> { +/// fn cmp(&self, other: &Troll) -> Ordering { +/// // If we swap `self` and `other`, we get descending ordering. +/// self.level.cmp(&other.level) +/// } +/// } +/// +/// // `PartialOrd` needs to be implemented as well. +/// impl<'a> PartialOrd for Troll<'a> { +/// fn partial_cmp(&self, other: &Troll) -> Option { +/// Some(self.cmp(other)) +/// } +/// } +/// +/// let mut trolls = TreeSet::new(); +/// +/// trolls.insert(Troll { name: "Orgarr", level: 2 }); +/// trolls.insert(Troll { name: "Blargarr", level: 3 }); +/// trolls.insert(Troll { name: "Kron the Smelly One", level: 4 }); +/// trolls.insert(Troll { name: "Wartilda", level: 1 }); +/// +/// println!("You are facing {} trolls!", trolls.len()); +/// +/// // Print the trolls, ordered by level with smallest level first +/// for x in trolls.iter() { +/// println!("level {}: {}!", x.level, x.name); +/// } +/// +/// // Kill all trolls +/// trolls.clear(); +/// assert_eq!(trolls.len(), 0); +/// ``` +#[deriving(Clone)] +pub struct TreeSet { + map: TreeMap +} + +impl PartialEq for TreeSet { + #[inline] + fn eq(&self, other: &TreeSet) -> bool { self.map == other.map } +} + +impl Eq for TreeSet {} + +impl PartialOrd for TreeSet { + #[inline] + fn partial_cmp(&self, other: &TreeSet) -> Option { + self.map.partial_cmp(&other.map) + } +} + +impl Ord for TreeSet { + #[inline] + fn cmp(&self, other: &TreeSet) -> Ordering { + iter::order::cmp(self.iter(), other.iter()) + } +} + +impl Show for TreeSet { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(write!(f, "{{")); + + for (i, x) in self.iter().enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, "{}", *x)); + } + + write!(f, "}}") + } +} + +impl Default for TreeSet { + #[inline] + fn default() -> TreeSet { TreeSet::new() } +} + +impl TreeSet { + /// Creates an empty `TreeSet`. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// let mut set: TreeSet = TreeSet::new(); + /// ``` + #[inline] + pub fn new() -> TreeSet { TreeSet{map: TreeMap::new()} } + + /// Gets a lazy iterator over the values in the set, in ascending order. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// let set: TreeSet = [1i, 4, 3, 5, 2].iter().map(|&x| x).collect(); + /// + /// // Will print in ascending order. + /// for x in set.iter() { + /// println!("{}", x); + /// } + /// ``` + #[inline] + pub fn iter<'a>(&'a self) -> SetItems<'a, T> { + SetItems{iter: self.map.iter()} + } + + /// Gets a lazy iterator over the values in the set, in descending order. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// let set: TreeSet = [1i, 4, 3, 5, 2].iter().map(|&x| x).collect(); + /// + /// // Will print in descending order. + /// for x in set.rev_iter() { + /// println!("{}", x); + /// } + /// ``` + #[inline] + pub fn rev_iter<'a>(&'a self) -> RevSetItems<'a, T> { + RevSetItems{iter: self.map.rev_iter()} + } + + /// Creates a consuming iterator, that is, one that moves each value out of the + /// set in ascending order. The set cannot be used after calling this. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// let set: TreeSet = [1i, 4, 3, 5, 2].iter().map(|&x| x).collect(); + /// + /// // Not possible with a regular `.iter()` + /// let v: Vec = set.into_iter().collect(); + /// assert_eq!(v, vec![1, 2, 3, 4, 5]); + /// ``` + #[inline] + pub fn into_iter(self) -> MoveSetItems { + self.map.into_iter().map(|(value, _)| value) + } + + /// Gets a lazy iterator pointing to the first value not less than `v` (greater or equal). + /// If all elements in the set are less than `v` empty iterator is returned. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// let set: TreeSet = [2, 4, 6, 8].iter().map(|&x| x).collect(); + /// + /// assert_eq!(set.lower_bound(&4).next(), Some(&4)); + /// assert_eq!(set.lower_bound(&5).next(), Some(&6)); + /// assert_eq!(set.lower_bound(&10).next(), None); + /// ``` + #[inline] + pub fn lower_bound<'a>(&'a self, v: &T) -> SetItems<'a, T> { + SetItems{iter: self.map.lower_bound(v)} + } + + /// Gets a lazy iterator pointing to the first value greater than `v`. + /// If all elements in the set are less than or equal to `v` an + /// empty iterator is returned. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// let set: TreeSet = [2, 4, 6, 8].iter().map(|&x| x).collect(); + /// + /// assert_eq!(set.upper_bound(&4).next(), Some(&6)); + /// assert_eq!(set.upper_bound(&5).next(), Some(&6)); + /// assert_eq!(set.upper_bound(&10).next(), None); + /// ``` + #[inline] + pub fn upper_bound<'a>(&'a self, v: &T) -> SetItems<'a, T> { + SetItems{iter: self.map.upper_bound(v)} + } + + /// Visits the values representing the difference, in ascending order. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// + /// let a: TreeSet = [1, 2, 3].iter().map(|&x| x).collect(); + /// let b: TreeSet = [3, 4, 5].iter().map(|&x| x).collect(); + /// + /// // Can be seen as `a - b`. + /// for x in a.difference(&b) { + /// println!("{}", x); // Print 1 then 2 + /// } + /// + /// let diff: TreeSet = a.difference(&b).map(|&x| x).collect(); + /// assert_eq!(diff, [1, 2].iter().map(|&x| x).collect()); + /// + /// // Note that difference is not symmetric, + /// // and `b - a` means something else: + /// let diff: TreeSet = b.difference(&a).map(|&x| x).collect(); + /// assert_eq!(diff, [4, 5].iter().map(|&x| x).collect()); + /// ``` + pub fn difference<'a>(&'a self, other: &'a TreeSet) -> DifferenceItems<'a, T> { + DifferenceItems{a: self.iter().peekable(), b: other.iter().peekable()} + } + + /// Visits the values representing the symmetric difference, in ascending order. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// + /// let a: TreeSet = [1, 2, 3].iter().map(|&x| x).collect(); + /// let b: TreeSet = [3, 4, 5].iter().map(|&x| x).collect(); + /// + /// // Print 1, 2, 4, 5 in ascending order. + /// for x in a.symmetric_difference(&b) { + /// println!("{}", x); + /// } + /// + /// let diff1: TreeSet = a.symmetric_difference(&b).map(|&x| x).collect(); + /// let diff2: TreeSet = b.symmetric_difference(&a).map(|&x| x).collect(); + /// + /// assert_eq!(diff1, diff2); + /// assert_eq!(diff1, [1, 2, 4, 5].iter().map(|&x| x).collect()); + /// ``` + pub fn symmetric_difference<'a>(&'a self, other: &'a TreeSet) + -> SymDifferenceItems<'a, T> { + SymDifferenceItems{a: self.iter().peekable(), b: other.iter().peekable()} + } + + /// Visits the values representing the intersection, in ascending order. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// + /// let a: TreeSet = [1, 2, 3].iter().map(|&x| x).collect(); + /// let b: TreeSet = [2, 3, 4].iter().map(|&x| x).collect(); + /// + /// // Print 2, 3 in ascending order. + /// for x in a.intersection(&b) { + /// println!("{}", x); + /// } + /// + /// let diff: TreeSet = a.intersection(&b).map(|&x| x).collect(); + /// assert_eq!(diff, [2, 3].iter().map(|&x| x).collect()); + /// ``` + pub fn intersection<'a>(&'a self, other: &'a TreeSet) + -> IntersectionItems<'a, T> { + IntersectionItems{a: self.iter().peekable(), b: other.iter().peekable()} + } + + /// Visits the values representing the union, in ascending order. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// + /// let a: TreeSet = [1, 2, 3].iter().map(|&x| x).collect(); + /// let b: TreeSet = [3, 4, 5].iter().map(|&x| x).collect(); + /// + /// // Print 1, 2, 3, 4, 5 in ascending order. + /// for x in a.union(&b) { + /// println!("{}", x); + /// } + /// + /// let diff: TreeSet = a.union(&b).map(|&x| x).collect(); + /// assert_eq!(diff, [1, 2, 3, 4, 5].iter().map(|&x| x).collect()); + /// ``` + pub fn union<'a>(&'a self, other: &'a TreeSet) -> UnionItems<'a, T> { + UnionItems{a: self.iter().peekable(), b: other.iter().peekable()} + } + + /// Return the number of elements in the set + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// + /// let mut v = TreeSet::new(); + /// assert_eq!(v.len(), 0); + /// v.insert(1i); + /// assert_eq!(v.len(), 1); + /// ``` + #[inline] + pub fn len(&self) -> uint { self.map.len() } + + /// Returns true if the set contains no elements + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// + /// let mut v = TreeSet::new(); + /// assert!(v.is_empty()); + /// v.insert(1i); + /// assert!(!v.is_empty()); + /// ``` + pub fn is_empty(&self) -> bool { self.len() == 0 } + + /// Clears the set, removing all values. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// + /// let mut v = TreeSet::new(); + /// v.insert(1i); + /// v.clear(); + /// assert!(v.is_empty()); + /// ``` + #[inline] + pub fn clear(&mut self) { self.map.clear() } + + /// Returns `true` if the set contains a value. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// + /// let set: TreeSet = [1i, 2, 3].iter().map(|&x| x).collect(); + /// assert_eq!(set.contains(&1), true); + /// assert_eq!(set.contains(&4), false); + /// ``` + #[inline] + pub fn contains(&self, value: &T) -> bool { + self.map.contains_key(value) + } + + /// Returns `true` if the set has no elements in common with `other`. + /// This is equivalent to checking for an empty intersection. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// + /// let a: TreeSet = [1i, 2, 3].iter().map(|&x| x).collect(); + /// let mut b: TreeSet = TreeSet::new(); + /// + /// assert_eq!(a.is_disjoint(&b), true); + /// b.insert(4); + /// assert_eq!(a.is_disjoint(&b), true); + /// b.insert(1); + /// assert_eq!(a.is_disjoint(&b), false); + /// ``` + pub fn is_disjoint(&self, other: &TreeSet) -> bool { + self.intersection(other).next().is_none() + } + + /// Returns `true` if the set is a subset of another. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// + /// let sup: TreeSet = [1i, 2, 3].iter().map(|&x| x).collect(); + /// let mut set: TreeSet = TreeSet::new(); + /// + /// assert_eq!(set.is_subset(&sup), true); + /// set.insert(2); + /// assert_eq!(set.is_subset(&sup), true); + /// set.insert(4); + /// assert_eq!(set.is_subset(&sup), false); + /// ``` + pub fn is_subset(&self, other: &TreeSet) -> bool { + let mut x = self.iter(); + let mut y = other.iter(); + let mut a = x.next(); + let mut b = y.next(); + while a.is_some() { + if b.is_none() { + return false; + } + + let a1 = a.unwrap(); + let b1 = b.unwrap(); + + match b1.cmp(a1) { + Less => (), + Greater => return false, + Equal => a = x.next(), + } + + b = y.next(); + } + true + } + + /// Returns `true` if the set is a superset of another. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// + /// let sub: TreeSet = [1i, 2].iter().map(|&x| x).collect(); + /// let mut set: TreeSet = TreeSet::new(); + /// + /// assert_eq!(set.is_superset(&sub), false); + /// + /// set.insert(0); + /// set.insert(1); + /// assert_eq!(set.is_superset(&sub), false); + /// + /// set.insert(2); + /// assert_eq!(set.is_superset(&sub), true); + /// ``` + pub fn is_superset(&self, other: &TreeSet) -> bool { + other.is_subset(self) + } + + /// Adds a value to the set. Returns `true` if the value was not already + /// present in the set. + /// + /// # Example + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// + /// assert_eq!(set.insert(2i), true); + /// assert_eq!(set.insert(2i), false); + /// assert_eq!(set.len(), 1); + /// ``` + #[inline] + pub fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()) } + + /// Removes a value from the set. Returns `true` if the value was + /// present in the set. + /// + /// # Example + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// + /// set.insert(2i); + /// assert_eq!(set.remove(&2), true); + /// assert_eq!(set.remove(&2), false); + /// ``` + #[inline] + pub fn remove(&mut self, value: &T) -> bool { self.map.remove(value) } +} + +/// A lazy forward iterator over a set. +pub struct SetItems<'a, T:'a> { + iter: Entries<'a, T, ()> +} + +/// A lazy backward iterator over a set. +pub struct RevSetItems<'a, T:'a> { + iter: RevEntries<'a, T, ()> +} + +/// A lazy forward iterator over a set that consumes the set while iterating. +pub type MoveSetItems = iter::Map<'static, (T, ()), T, MoveEntries>; + +/// A lazy iterator producing elements in the set difference (in-order). +pub struct DifferenceItems<'a, T:'a> { + a: Peekable<&'a T, SetItems<'a, T>>, + b: Peekable<&'a T, SetItems<'a, T>>, +} + +/// A lazy iterator producing elements in the set symmetric difference (in-order). +pub struct SymDifferenceItems<'a, T:'a> { + a: Peekable<&'a T, SetItems<'a, T>>, + b: Peekable<&'a T, SetItems<'a, T>>, +} + +/// A lazy iterator producing elements in the set intersection (in-order). +pub struct IntersectionItems<'a, T:'a> { + a: Peekable<&'a T, SetItems<'a, T>>, + b: Peekable<&'a T, SetItems<'a, T>>, +} + +/// A lazy iterator producing elements in the set union (in-order). +pub struct UnionItems<'a, T:'a> { + a: Peekable<&'a T, SetItems<'a, T>>, + b: Peekable<&'a T, SetItems<'a, T>>, +} + +/// Compare `x` and `y`, but return `short` if x is None and `long` if y is None +fn cmp_opt(x: Option<&T>, y: Option<&T>, + short: Ordering, long: Ordering) -> Ordering { + match (x, y) { + (None , _ ) => short, + (_ , None ) => long, + (Some(x1), Some(y1)) => x1.cmp(y1), + } +} + + +impl<'a, T> Iterator<&'a T> for SetItems<'a, T> { + #[inline] + fn next(&mut self) -> Option<&'a T> { + self.iter.next().map(|(value, _)| value) + } +} + +impl<'a, T> Iterator<&'a T> for RevSetItems<'a, T> { + #[inline] + fn next(&mut self) -> Option<&'a T> { + self.iter.next().map(|(value, _)| value) + } +} + +impl<'a, T: Ord> Iterator<&'a T> for DifferenceItems<'a, T> { + fn next(&mut self) -> Option<&'a T> { + loop { + match cmp_opt(self.a.peek(), self.b.peek(), Less, Less) { + Less => return self.a.next(), + Equal => { self.a.next(); self.b.next(); } + Greater => { self.b.next(); } + } + } + } +} + +impl<'a, T: Ord> Iterator<&'a T> for SymDifferenceItems<'a, T> { + fn next(&mut self) -> Option<&'a T> { + loop { + match cmp_opt(self.a.peek(), self.b.peek(), Greater, Less) { + Less => return self.a.next(), + Equal => { self.a.next(); self.b.next(); } + Greater => return self.b.next(), + } + } + } +} + +impl<'a, T: Ord> Iterator<&'a T> for IntersectionItems<'a, T> { + fn next(&mut self) -> Option<&'a T> { + loop { + let o_cmp = match (self.a.peek(), self.b.peek()) { + (None , _ ) => None, + (_ , None ) => None, + (Some(a1), Some(b1)) => Some(a1.cmp(b1)), + }; + match o_cmp { + None => return None, + Some(Less) => { self.a.next(); } + Some(Equal) => { self.b.next(); return self.a.next() } + Some(Greater) => { self.b.next(); } + } + } + } +} + +impl<'a, T: Ord> Iterator<&'a T> for UnionItems<'a, T> { + fn next(&mut self) -> Option<&'a T> { + loop { + match cmp_opt(self.a.peek(), self.b.peek(), Greater, Less) { + Less => return self.a.next(), + Equal => { self.b.next(); return self.a.next() } + Greater => return self.b.next(), + } + } + } +} + +impl FromIterator for TreeSet { + fn from_iter>(iter: Iter) -> TreeSet { + let mut set = TreeSet::new(); + set.extend(iter); + set + } +} + +impl Extendable for TreeSet { + #[inline] + fn extend>(&mut self, mut iter: Iter) { + for elem in iter { + self.insert(elem); + } + } +} + +impl> Hash for TreeSet { + fn hash(&self, state: &mut S) { + for elt in self.iter() { + elt.hash(state); + } + } +} + +#[cfg(test)] +mod test { + use std::prelude::*; + use std::hash; + + use super::TreeSet; + + #[test] + fn test_clear() { + let mut s = TreeSet::new(); + s.clear(); + assert!(s.insert(5i)); + assert!(s.insert(12)); + assert!(s.insert(19)); + s.clear(); + assert!(!s.contains(&5)); + assert!(!s.contains(&12)); + assert!(!s.contains(&19)); + assert!(s.is_empty()); + } + + #[test] + fn test_disjoint() { + let mut xs = TreeSet::new(); + let mut ys = TreeSet::new(); + assert!(xs.is_disjoint(&ys)); + assert!(ys.is_disjoint(&xs)); + assert!(xs.insert(5i)); + assert!(ys.insert(11i)); + assert!(xs.is_disjoint(&ys)); + assert!(ys.is_disjoint(&xs)); + assert!(xs.insert(7)); + assert!(xs.insert(19)); + assert!(xs.insert(4)); + assert!(ys.insert(2)); + assert!(ys.insert(-11)); + assert!(xs.is_disjoint(&ys)); + assert!(ys.is_disjoint(&xs)); + assert!(ys.insert(7)); + assert!(!xs.is_disjoint(&ys)); + assert!(!ys.is_disjoint(&xs)); + } + + #[test] + fn test_subset_and_superset() { + let mut a = TreeSet::new(); + assert!(a.insert(0i)); + assert!(a.insert(5)); + assert!(a.insert(11)); + assert!(a.insert(7)); + + let mut b = TreeSet::new(); + assert!(b.insert(0i)); + assert!(b.insert(7)); + assert!(b.insert(19)); + assert!(b.insert(250)); + assert!(b.insert(11)); + assert!(b.insert(200)); + + assert!(!a.is_subset(&b)); + assert!(!a.is_superset(&b)); + assert!(!b.is_subset(&a)); + assert!(!b.is_superset(&a)); + + assert!(b.insert(5)); + + assert!(a.is_subset(&b)); + assert!(!a.is_superset(&b)); + assert!(!b.is_subset(&a)); + assert!(b.is_superset(&a)); + } + + #[test] + fn test_iterator() { + let mut m = TreeSet::new(); + + assert!(m.insert(3i)); + assert!(m.insert(0)); + assert!(m.insert(4)); + assert!(m.insert(2)); + assert!(m.insert(1)); + + let mut n = 0; + for x in m.iter() { + assert_eq!(*x, n); + n += 1 + } + } + + #[test] + fn test_rev_iter() { + let mut m = TreeSet::new(); + + assert!(m.insert(3i)); + assert!(m.insert(0)); + assert!(m.insert(4)); + assert!(m.insert(2)); + assert!(m.insert(1)); + + let mut n = 4; + for x in m.rev_iter() { + assert_eq!(*x, n); + n -= 1; + } + } + + #[test] + fn test_move_iter() { + let s: TreeSet = range(0i, 5).collect(); + + let mut n = 0; + for x in s.into_iter() { + assert_eq!(x, n); + n += 1; + } + } + + #[test] + fn test_move_iter_size_hint() { + let s: TreeSet = vec!(0i, 1).into_iter().collect(); + + let mut it = s.into_iter(); + + assert_eq!(it.size_hint(), (2, Some(2))); + assert!(it.next() != None); + + assert_eq!(it.size_hint(), (1, Some(1))); + assert!(it.next() != None); + + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next(), None); + } + + #[test] + fn test_clone_eq() { + let mut m = TreeSet::new(); + + m.insert(1i); + m.insert(2); + + assert!(m.clone() == m); + } + + #[test] + fn test_hash() { + let mut x = TreeSet::new(); + let mut y = TreeSet::new(); + + x.insert(1i); + x.insert(2); + x.insert(3); + + y.insert(3i); + y.insert(2); + y.insert(1); + + assert!(hash::hash(&x) == hash::hash(&y)); + } + + fn check(a: &[int], + b: &[int], + expected: &[int], + f: |&TreeSet, &TreeSet, f: |&int| -> bool| -> bool) { + let mut set_a = TreeSet::new(); + let mut set_b = TreeSet::new(); + + for x in a.iter() { assert!(set_a.insert(*x)) } + for y in b.iter() { assert!(set_b.insert(*y)) } + + let mut i = 0; + f(&set_a, &set_b, |x| { + assert_eq!(*x, expected[i]); + i += 1; + true + }); + assert_eq!(i, expected.len()); + } + + #[test] + fn test_intersection() { + fn check_intersection(a: &[int], b: &[int], expected: &[int]) { + check(a, b, expected, |x, y, f| x.intersection(y).all(f)) + } + + check_intersection([], [], []); + check_intersection([1, 2, 3], [], []); + check_intersection([], [1, 2, 3], []); + check_intersection([2], [1, 2, 3], [2]); + check_intersection([1, 2, 3], [2], [2]); + check_intersection([11, 1, 3, 77, 103, 5, -5], + [2, 11, 77, -9, -42, 5, 3], + [3, 5, 11, 77]); + } + + #[test] + fn test_difference() { + fn check_difference(a: &[int], b: &[int], expected: &[int]) { + check(a, b, expected, |x, y, f| x.difference(y).all(f)) + } + + check_difference([], [], []); + check_difference([1, 12], [], [1, 12]); + check_difference([], [1, 2, 3, 9], []); + check_difference([1, 3, 5, 9, 11], + [3, 9], + [1, 5, 11]); + check_difference([-5, 11, 22, 33, 40, 42], + [-12, -5, 14, 23, 34, 38, 39, 50], + [11, 22, 33, 40, 42]); + } + + #[test] + fn test_symmetric_difference() { + fn check_symmetric_difference(a: &[int], b: &[int], + expected: &[int]) { + check(a, b, expected, |x, y, f| x.symmetric_difference(y).all(f)) + } + + check_symmetric_difference([], [], []); + check_symmetric_difference([1, 2, 3], [2], [1, 3]); + check_symmetric_difference([2], [1, 2, 3], [1, 3]); + check_symmetric_difference([1, 3, 5, 9, 11], + [-2, 3, 9, 14, 22], + [-2, 1, 5, 11, 14, 22]); + } + + #[test] + fn test_union() { + fn check_union(a: &[int], b: &[int], + expected: &[int]) { + check(a, b, expected, |x, y, f| x.union(y).all(f)) + } + + check_union([], [], []); + check_union([1, 2, 3], [2], [1, 2, 3]); + check_union([2], [1, 2, 3], [1, 2, 3]); + check_union([1, 3, 5, 9, 11, 16, 19, 24], + [-2, 1, 5, 9, 13, 19], + [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]); + } + + #[test] + fn test_zip() { + let mut x = TreeSet::new(); + x.insert(5u); + x.insert(12u); + x.insert(11u); + + let mut y = TreeSet::new(); + y.insert("foo"); + y.insert("bar"); + + let x = x; + let y = y; + let mut z = x.iter().zip(y.iter()); + + // FIXME: #5801: this needs a type hint to compile... + let result: Option<(&uint, & &'static str)> = z.next(); + assert_eq!(result.unwrap(), (&5u, &("bar"))); + + let result: Option<(&uint, & &'static str)> = z.next(); + assert_eq!(result.unwrap(), (&11u, &("foo"))); + + let result: Option<(&uint, & &'static str)> = z.next(); + assert!(result.is_none()); + } + + #[test] + fn test_from_iter() { + let xs = [1i, 2, 3, 4, 5, 6, 7, 8, 9]; + + let set: TreeSet = xs.iter().map(|&x| x).collect(); + + for x in xs.iter() { + assert!(set.contains(x)); + } + } + + #[test] + fn test_show() { + let mut set: TreeSet = TreeSet::new(); + let empty: TreeSet = TreeSet::new(); + + set.insert(1); + set.insert(2); + + let set_str = format!("{}", set); + + assert!(set_str == "{1, 2}".to_string()); + assert_eq!(format!("{}", empty), "{}".to_string()); + } +} diff --git a/src/libcollections/trie.rs b/src/libcollections/trie/map.rs similarity index 80% rename from src/libcollections/trie.rs rename to src/libcollections/trie/map.rs index 7a8cc5df55a27..27486de6f1993 100644 --- a/src/libcollections/trie.rs +++ b/src/libcollections/trie/map.rs @@ -654,335 +654,6 @@ impl IndexMut for TrieMap { } } -/// A set implemented as a radix trie. -/// -/// # Example -/// -/// ``` -/// use std::collections::TrieSet; -/// -/// let mut set = TrieSet::new(); -/// set.insert(6); -/// set.insert(28); -/// set.insert(6); -/// -/// assert_eq!(set.len(), 2); -/// -/// if !set.contains(&3) { -/// println!("3 is not in the set"); -/// } -/// -/// // Print contents in order -/// for x in set.iter() { -/// println!("{}", x); -/// } -/// -/// set.remove(&6); -/// assert_eq!(set.len(), 1); -/// -/// set.clear(); -/// assert!(set.is_empty()); -/// ``` -#[deriving(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] -pub struct TrieSet { - map: TrieMap<()> -} - -impl Show for TrieSet { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "{{")); - - for (i, x) in self.iter().enumerate() { - if i != 0 { try!(write!(f, ", ")); } - try!(write!(f, "{}", x)); - } - - write!(f, "}}") - } -} - -impl Default for TrieSet { - #[inline] - fn default() -> TrieSet { TrieSet::new() } -} - -impl TrieSet { - /// Creates an empty TrieSet. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// let mut set = TrieSet::new(); - /// ``` - #[inline] - pub fn new() -> TrieSet { - TrieSet{map: TrieMap::new()} - } - - /// Visits all values in reverse order. Aborts traversal when `f` returns `false`. - /// Returns `true` if `f` returns `true` for all elements. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// - /// let set: TrieSet = [1, 2, 3, 4, 5].iter().map(|&x| x).collect(); - /// - /// let mut vec = Vec::new(); - /// assert_eq!(true, set.each_reverse(|&x| { vec.push(x); true })); - /// assert_eq!(vec, vec![5, 4, 3, 2, 1]); - /// - /// // Stop when we reach 3 - /// let mut vec = Vec::new(); - /// assert_eq!(false, set.each_reverse(|&x| { vec.push(x); x != 3 })); - /// assert_eq!(vec, vec![5, 4, 3]); - /// ``` - #[inline] - pub fn each_reverse(&self, f: |&uint| -> bool) -> bool { - self.map.each_reverse(|k, _| f(k)) - } - - /// Gets an iterator over the values in the set, in sorted order. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// - /// let mut set = TrieSet::new(); - /// set.insert(3); - /// set.insert(2); - /// set.insert(1); - /// set.insert(2); - /// - /// // Print 1, 2, 3 - /// for x in set.iter() { - /// println!("{}", x); - /// } - /// ``` - #[inline] - pub fn iter<'a>(&'a self) -> SetItems<'a> { - SetItems{iter: self.map.iter()} - } - - /// Gets an iterator pointing to the first value that is not less than `val`. - /// If all values in the set are less than `val` an empty iterator is returned. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// - /// let set: TrieSet = [2, 4, 6, 8].iter().map(|&x| x).collect(); - /// assert_eq!(set.lower_bound(4).next(), Some(4)); - /// assert_eq!(set.lower_bound(5).next(), Some(6)); - /// assert_eq!(set.lower_bound(10).next(), None); - /// ``` - pub fn lower_bound<'a>(&'a self, val: uint) -> SetItems<'a> { - SetItems{iter: self.map.lower_bound(val)} - } - - /// Gets an iterator pointing to the first value that key is greater than `val`. - /// If all values in the set are less than or equal to `val` an empty iterator is returned. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// - /// let set: TrieSet = [2, 4, 6, 8].iter().map(|&x| x).collect(); - /// assert_eq!(set.upper_bound(4).next(), Some(6)); - /// assert_eq!(set.upper_bound(5).next(), Some(6)); - /// assert_eq!(set.upper_bound(10).next(), None); - /// ``` - pub fn upper_bound<'a>(&'a self, val: uint) -> SetItems<'a> { - SetItems{iter: self.map.upper_bound(val)} - } - - /// Return the number of elements in the set - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// - /// let mut v = TrieSet::new(); - /// assert_eq!(v.len(), 0); - /// v.insert(1); - /// assert_eq!(v.len(), 1); - /// ``` - #[inline] - pub fn len(&self) -> uint { self.map.len() } - - /// Returns true if the set contains no elements - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// - /// let mut v = TrieSet::new(); - /// assert!(v.is_empty()); - /// v.insert(1); - /// assert!(!v.is_empty()); - /// ``` - pub fn is_empty(&self) -> bool { self.len() == 0 } - - /// Clears the set, removing all values. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// - /// let mut v = TrieSet::new(); - /// v.insert(1); - /// v.clear(); - /// assert!(v.is_empty()); - /// ``` - #[inline] - pub fn clear(&mut self) { self.map.clear() } - - /// Returns `true` if the set contains a value. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// - /// let set: TrieSet = [1, 2, 3].iter().map(|&x| x).collect(); - /// assert_eq!(set.contains(&1), true); - /// assert_eq!(set.contains(&4), false); - /// ``` - #[inline] - pub fn contains(&self, value: &uint) -> bool { - self.map.contains_key(value) - } - - /// Returns `true` if the set has no elements in common with `other`. - /// This is equivalent to checking for an empty intersection. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// - /// let a: TrieSet = [1, 2, 3].iter().map(|&x| x).collect(); - /// let mut b: TrieSet = TrieSet::new(); - /// - /// assert_eq!(a.is_disjoint(&b), true); - /// b.insert(4); - /// assert_eq!(a.is_disjoint(&b), true); - /// b.insert(1); - /// assert_eq!(a.is_disjoint(&b), false); - /// ``` - #[inline] - pub fn is_disjoint(&self, other: &TrieSet) -> bool { - self.iter().all(|v| !other.contains(&v)) - } - - /// Returns `true` if the set is a subset of another. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// - /// let sup: TrieSet = [1, 2, 3].iter().map(|&x| x).collect(); - /// let mut set: TrieSet = TrieSet::new(); - /// - /// assert_eq!(set.is_subset(&sup), true); - /// set.insert(2); - /// assert_eq!(set.is_subset(&sup), true); - /// set.insert(4); - /// assert_eq!(set.is_subset(&sup), false); - /// ``` - #[inline] - pub fn is_subset(&self, other: &TrieSet) -> bool { - self.iter().all(|v| other.contains(&v)) - } - - /// Returns `true` if the set is a superset of another. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// - /// let sub: TrieSet = [1, 2].iter().map(|&x| x).collect(); - /// let mut set: TrieSet = TrieSet::new(); - /// - /// assert_eq!(set.is_superset(&sub), false); - /// - /// set.insert(0); - /// set.insert(1); - /// assert_eq!(set.is_superset(&sub), false); - /// - /// set.insert(2); - /// assert_eq!(set.is_superset(&sub), true); - /// ``` - #[inline] - pub fn is_superset(&self, other: &TrieSet) -> bool { - other.is_subset(self) - } - - /// Adds a value to the set. Returns `true` if the value was not already - /// present in the set. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// - /// let mut set = TrieSet::new(); - /// - /// assert_eq!(set.insert(2), true); - /// assert_eq!(set.insert(2), false); - /// assert_eq!(set.len(), 1); - /// ``` - #[inline] - pub fn insert(&mut self, value: uint) -> bool { - self.map.insert(value, ()) - } - - /// Removes a value from the set. Returns `true` if the value was - /// present in the set. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// - /// let mut set = TrieSet::new(); - /// - /// set.insert(2); - /// assert_eq!(set.remove(&2), true); - /// assert_eq!(set.remove(&2), false); - /// ``` - #[inline] - pub fn remove(&mut self, value: &uint) -> bool { - self.map.remove(value) - } -} - -impl FromIterator for TrieSet { - fn from_iter>(iter: Iter) -> TrieSet { - let mut set = TrieSet::new(); - set.extend(iter); - set - } -} - -impl Extendable for TrieSet { - fn extend>(&mut self, mut iter: Iter) { - for elem in iter { - self.insert(elem); - } - } -} - struct TrieNode { count: uint, children: [Child, ..SIZE] @@ -1255,23 +926,8 @@ macro_rules! iterator_impl { iterator_impl! { Entries, iter = iter, mutability = } iterator_impl! { MutEntries, iter = iter_mut, mutability = mut } -/// A forward iterator over a set. -pub struct SetItems<'a> { - iter: Entries<'a, ()> -} - -impl<'a> Iterator for SetItems<'a> { - fn next(&mut self) -> Option { - self.iter.next().map(|(key, _)| key) - } - - fn size_hint(&self) -> (uint, Option) { - self.iter.size_hint() - } -} - #[cfg(test)] -mod test_map { +mod test { use std::prelude::*; use std::iter::range_step; use std::uint; @@ -1687,7 +1343,7 @@ mod test_map { } #[cfg(test)] -mod bench_map { +mod bench { use std::prelude::*; use std::rand::{weak_rng, Rng}; use test::{Bencher, black_box}; @@ -1802,98 +1458,3 @@ mod bench_map { }) } } - -#[cfg(test)] -mod test_set { - use std::prelude::*; - use std::uint; - - use super::TrieSet; - - #[test] - fn test_sane_chunk() { - let x = 1; - let y = 1 << (uint::BITS - 1); - - let mut trie = TrieSet::new(); - - assert!(trie.insert(x)); - assert!(trie.insert(y)); - - assert_eq!(trie.len(), 2); - - let expected = [x, y]; - - for (i, x) in trie.iter().enumerate() { - assert_eq!(expected[i], x); - } - } - - #[test] - fn test_from_iter() { - let xs = vec![9u, 8, 7, 6, 5, 4, 3, 2, 1]; - - let set: TrieSet = xs.iter().map(|&x| x).collect(); - - for x in xs.iter() { - assert!(set.contains(x)); - } - } - - #[test] - fn test_show() { - let mut set = TrieSet::new(); - let empty = TrieSet::new(); - - set.insert(1); - set.insert(2); - - let set_str = format!("{}", set); - - assert!(set_str == "{1, 2}".to_string()); - assert_eq!(format!("{}", empty), "{}".to_string()); - } - - #[test] - fn test_clone() { - let mut a = TrieSet::new(); - - a.insert(1); - a.insert(2); - a.insert(3); - - assert!(a.clone() == a); - } - - #[test] - fn test_lt() { - let mut a = TrieSet::new(); - let mut b = TrieSet::new(); - - assert!(!(a < b) && !(b < a)); - assert!(b.insert(2u)); - assert!(a < b); - assert!(a.insert(3u)); - assert!(!(a < b) && b < a); - assert!(b.insert(1)); - assert!(b < a); - assert!(a.insert(0)); - assert!(a < b); - assert!(a.insert(6)); - assert!(a < b && !(b < a)); - } - - #[test] - fn test_ord() { - let mut a = TrieSet::new(); - let mut b = TrieSet::new(); - - assert!(a <= b && a >= b); - assert!(a.insert(1u)); - assert!(a > b && a >= b); - assert!(b < a && b <= a); - assert!(b.insert(2u)); - assert!(b > a && b >= a); - assert!(a < b && a <= b); - } -} diff --git a/src/libcollections/trie/mod.rs b/src/libcollections/trie/mod.rs new file mode 100644 index 0000000000000..f0f8f00a6a0db --- /dev/null +++ b/src/libcollections/trie/mod.rs @@ -0,0 +1,20 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Maps are collections of unique keys with corresponding values, and sets are +//! just unique keys without a corresponding value. The `Map` and `Set` traits in +//! `std::container` define the basic interface. +//! +//! This crate defines `TrieMap` and `TrieSet`, which require `uint` keys. +//! +//! `TrieMap` is ordered. + +pub mod map; +pub mod set; \ No newline at end of file diff --git a/src/libcollections/trie/set.rs b/src/libcollections/trie/set.rs new file mode 100644 index 0000000000000..ddddd279b0467 --- /dev/null +++ b/src/libcollections/trie/set.rs @@ -0,0 +1,457 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::prelude::*; + +use core::default::Default; +use core::fmt; +use core::fmt::Show; +use std::hash::Hash; + +use trie_map::{TrieMap, Entries}; + +/// A set implemented as a radix trie. +/// +/// # Example +/// +/// ``` +/// use std::collections::TrieSet; +/// +/// let mut set = TrieSet::new(); +/// set.insert(6); +/// set.insert(28); +/// set.insert(6); +/// +/// assert_eq!(set.len(), 2); +/// +/// if !set.contains(&3) { +/// println!("3 is not in the set"); +/// } +/// +/// // Print contents in order +/// for x in set.iter() { +/// println!("{}", x); +/// } +/// +/// set.remove(&6); +/// assert_eq!(set.len(), 1); +/// +/// set.clear(); +/// assert!(set.is_empty()); +/// ``` +#[deriving(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct TrieSet { + map: TrieMap<()> +} + +impl Show for TrieSet { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(write!(f, "{{")); + + for (i, x) in self.iter().enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, "{}", x)); + } + + write!(f, "}}") + } +} + +impl Default for TrieSet { + #[inline] + fn default() -> TrieSet { TrieSet::new() } +} + +impl TrieSet { + /// Creates an empty TrieSet. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// let mut set = TrieSet::new(); + /// ``` + #[inline] + pub fn new() -> TrieSet { + TrieSet{map: TrieMap::new()} + } + + /// Visits all values in reverse order. Aborts traversal when `f` returns `false`. + /// Returns `true` if `f` returns `true` for all elements. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// + /// let set: TrieSet = [1, 2, 3, 4, 5].iter().map(|&x| x).collect(); + /// + /// let mut vec = Vec::new(); + /// assert_eq!(true, set.each_reverse(|&x| { vec.push(x); true })); + /// assert_eq!(vec, vec![5, 4, 3, 2, 1]); + /// + /// // Stop when we reach 3 + /// let mut vec = Vec::new(); + /// assert_eq!(false, set.each_reverse(|&x| { vec.push(x); x != 3 })); + /// assert_eq!(vec, vec![5, 4, 3]); + /// ``` + #[inline] + pub fn each_reverse(&self, f: |&uint| -> bool) -> bool { + self.map.each_reverse(|k, _| f(k)) + } + + /// Gets an iterator over the values in the set, in sorted order. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// + /// let mut set = TrieSet::new(); + /// set.insert(3); + /// set.insert(2); + /// set.insert(1); + /// set.insert(2); + /// + /// // Print 1, 2, 3 + /// for x in set.iter() { + /// println!("{}", x); + /// } + /// ``` + #[inline] + pub fn iter<'a>(&'a self) -> SetItems<'a> { + SetItems{iter: self.map.iter()} + } + + /// Gets an iterator pointing to the first value that is not less than `val`. + /// If all values in the set are less than `val` an empty iterator is returned. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// + /// let set: TrieSet = [2, 4, 6, 8].iter().map(|&x| x).collect(); + /// assert_eq!(set.lower_bound(4).next(), Some(4)); + /// assert_eq!(set.lower_bound(5).next(), Some(6)); + /// assert_eq!(set.lower_bound(10).next(), None); + /// ``` + pub fn lower_bound<'a>(&'a self, val: uint) -> SetItems<'a> { + SetItems{iter: self.map.lower_bound(val)} + } + + /// Gets an iterator pointing to the first value that key is greater than `val`. + /// If all values in the set are less than or equal to `val` an empty iterator is returned. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// + /// let set: TrieSet = [2, 4, 6, 8].iter().map(|&x| x).collect(); + /// assert_eq!(set.upper_bound(4).next(), Some(6)); + /// assert_eq!(set.upper_bound(5).next(), Some(6)); + /// assert_eq!(set.upper_bound(10).next(), None); + /// ``` + pub fn upper_bound<'a>(&'a self, val: uint) -> SetItems<'a> { + SetItems{iter: self.map.upper_bound(val)} + } + + /// Return the number of elements in the set + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// + /// let mut v = TrieSet::new(); + /// assert_eq!(v.len(), 0); + /// v.insert(1); + /// assert_eq!(v.len(), 1); + /// ``` + #[inline] + pub fn len(&self) -> uint { self.map.len() } + + /// Returns true if the set contains no elements + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// + /// let mut v = TrieSet::new(); + /// assert!(v.is_empty()); + /// v.insert(1); + /// assert!(!v.is_empty()); + /// ``` + pub fn is_empty(&self) -> bool { self.len() == 0 } + + /// Clears the set, removing all values. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// + /// let mut v = TrieSet::new(); + /// v.insert(1); + /// v.clear(); + /// assert!(v.is_empty()); + /// ``` + #[inline] + pub fn clear(&mut self) { self.map.clear() } + + /// Returns `true` if the set contains a value. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// + /// let set: TrieSet = [1, 2, 3].iter().map(|&x| x).collect(); + /// assert_eq!(set.contains(&1), true); + /// assert_eq!(set.contains(&4), false); + /// ``` + #[inline] + pub fn contains(&self, value: &uint) -> bool { + self.map.contains_key(value) + } + + /// Returns `true` if the set has no elements in common with `other`. + /// This is equivalent to checking for an empty intersection. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// + /// let a: TrieSet = [1, 2, 3].iter().map(|&x| x).collect(); + /// let mut b: TrieSet = TrieSet::new(); + /// + /// assert_eq!(a.is_disjoint(&b), true); + /// b.insert(4); + /// assert_eq!(a.is_disjoint(&b), true); + /// b.insert(1); + /// assert_eq!(a.is_disjoint(&b), false); + /// ``` + #[inline] + pub fn is_disjoint(&self, other: &TrieSet) -> bool { + self.iter().all(|v| !other.contains(&v)) + } + + /// Returns `true` if the set is a subset of another. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// + /// let sup: TrieSet = [1, 2, 3].iter().map(|&x| x).collect(); + /// let mut set: TrieSet = TrieSet::new(); + /// + /// assert_eq!(set.is_subset(&sup), true); + /// set.insert(2); + /// assert_eq!(set.is_subset(&sup), true); + /// set.insert(4); + /// assert_eq!(set.is_subset(&sup), false); + /// ``` + #[inline] + pub fn is_subset(&self, other: &TrieSet) -> bool { + self.iter().all(|v| other.contains(&v)) + } + + /// Returns `true` if the set is a superset of another. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// + /// let sub: TrieSet = [1, 2].iter().map(|&x| x).collect(); + /// let mut set: TrieSet = TrieSet::new(); + /// + /// assert_eq!(set.is_superset(&sub), false); + /// + /// set.insert(0); + /// set.insert(1); + /// assert_eq!(set.is_superset(&sub), false); + /// + /// set.insert(2); + /// assert_eq!(set.is_superset(&sub), true); + /// ``` + #[inline] + pub fn is_superset(&self, other: &TrieSet) -> bool { + other.is_subset(self) + } + + /// Adds a value to the set. Returns `true` if the value was not already + /// present in the set. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// + /// let mut set = TrieSet::new(); + /// + /// assert_eq!(set.insert(2), true); + /// assert_eq!(set.insert(2), false); + /// assert_eq!(set.len(), 1); + /// ``` + #[inline] + pub fn insert(&mut self, value: uint) -> bool { + self.map.insert(value, ()) + } + + /// Removes a value from the set. Returns `true` if the value was + /// present in the set. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// + /// let mut set = TrieSet::new(); + /// + /// set.insert(2); + /// assert_eq!(set.remove(&2), true); + /// assert_eq!(set.remove(&2), false); + /// ``` + #[inline] + pub fn remove(&mut self, value: &uint) -> bool { + self.map.remove(value) + } +} + +impl FromIterator for TrieSet { + fn from_iter>(iter: Iter) -> TrieSet { + let mut set = TrieSet::new(); + set.extend(iter); + set + } +} + +impl Extendable for TrieSet { + fn extend>(&mut self, mut iter: Iter) { + for elem in iter { + self.insert(elem); + } + } +} + +/// A forward iterator over a set. +pub struct SetItems<'a> { + iter: Entries<'a, ()> +} + +impl<'a> Iterator for SetItems<'a> { + fn next(&mut self) -> Option { + self.iter.next().map(|(key, _)| key) + } + + fn size_hint(&self) -> (uint, Option) { + self.iter.size_hint() + } +} + +#[cfg(test)] +mod test { + use std::prelude::*; + use std::uint; + + use super::TrieSet; + + #[test] + fn test_sane_chunk() { + let x = 1; + let y = 1 << (uint::BITS - 1); + + let mut trie = TrieSet::new(); + + assert!(trie.insert(x)); + assert!(trie.insert(y)); + + assert_eq!(trie.len(), 2); + + let expected = [x, y]; + + for (i, x) in trie.iter().enumerate() { + assert_eq!(expected[i], x); + } + } + + #[test] + fn test_from_iter() { + let xs = vec![9u, 8, 7, 6, 5, 4, 3, 2, 1]; + + let set: TrieSet = xs.iter().map(|&x| x).collect(); + + for x in xs.iter() { + assert!(set.contains(x)); + } + } + + #[test] + fn test_show() { + let mut set = TrieSet::new(); + let empty = TrieSet::new(); + + set.insert(1); + set.insert(2); + + let set_str = format!("{}", set); + + assert!(set_str == "{1, 2}".to_string()); + assert_eq!(format!("{}", empty), "{}".to_string()); + } + + #[test] + fn test_clone() { + let mut a = TrieSet::new(); + + a.insert(1); + a.insert(2); + a.insert(3); + + assert!(a.clone() == a); + } + + #[test] + fn test_lt() { + let mut a = TrieSet::new(); + let mut b = TrieSet::new(); + + assert!(!(a < b) && !(b < a)); + assert!(b.insert(2u)); + assert!(a < b); + assert!(a.insert(3u)); + assert!(!(a < b) && b < a); + assert!(b.insert(1)); + assert!(b < a); + assert!(a.insert(0)); + assert!(a < b); + assert!(a.insert(6)); + assert!(a < b && !(b < a)); + } + + #[test] + fn test_ord() { + let mut a = TrieSet::new(); + let mut b = TrieSet::new(); + + assert!(a <= b && a >= b); + assert!(a.insert(1u)); + assert!(a > b && a >= b); + assert!(b < a && b <= a); + assert!(b.insert(2u)); + assert!(b > a && b >= a); + assert!(a < b && a <= b); + } +} diff --git a/src/libcollections/smallintmap.rs b/src/libcollections/vec_map.rs similarity index 84% rename from src/libcollections/smallintmap.rs rename to src/libcollections/vec_map.rs index b2e018743da7d..c0bc785126c70 100644 --- a/src/libcollections/smallintmap.rs +++ b/src/libcollections/vec_map.rs @@ -31,9 +31,9 @@ use hash::Hash; /// # Example /// /// ``` -/// use std::collections::SmallIntMap; +/// use std::collections::VecMap; /// -/// let mut months = SmallIntMap::new(); +/// let mut months = VecMap::new(); /// months.insert(1, "Jan"); /// months.insert(2, "Feb"); /// months.insert(3, "Mar"); @@ -60,23 +60,23 @@ use hash::Hash; /// assert!(months.is_empty()); /// ``` #[deriving(PartialEq, Eq)] -pub struct SmallIntMap { +pub struct VecMap { v: Vec>, } -impl Default for SmallIntMap { +impl Default for VecMap { #[inline] - fn default() -> SmallIntMap { SmallIntMap::new() } + fn default() -> VecMap { VecMap::new() } } -impl Clone for SmallIntMap { +impl Clone for VecMap { #[inline] - fn clone(&self) -> SmallIntMap { - SmallIntMap { v: self.v.clone() } + fn clone(&self) -> VecMap { + VecMap { v: self.v.clone() } } #[inline] - fn clone_from(&mut self, source: &SmallIntMap) { + fn clone_from(&mut self, source: &VecMap) { self.v.reserve(source.v.len()); for (i, w) in self.v.iter_mut().enumerate() { *w = source.v[i].clone(); @@ -84,34 +84,34 @@ impl Clone for SmallIntMap { } } -impl > Hash for SmallIntMap { +impl > Hash for VecMap { fn hash(&self, state: &mut S) { self.v.hash(state) } } -impl SmallIntMap { - /// Creates an empty `SmallIntMap`. +impl VecMap { + /// Creates an empty `VecMap`. /// /// # Example /// /// ``` - /// use std::collections::SmallIntMap; - /// let mut map: SmallIntMap<&str> = SmallIntMap::new(); + /// use std::collections::VecMap; + /// let mut map: VecMap<&str> = VecMap::new(); /// ``` - pub fn new() -> SmallIntMap { SmallIntMap{v: vec!()} } + pub fn new() -> VecMap { VecMap{v: vec!()} } - /// Creates an empty `SmallIntMap` with space for at least `capacity` + /// Creates an empty `VecMap` with space for at least `capacity` /// elements before resizing. /// /// # Example /// /// ``` - /// use std::collections::SmallIntMap; - /// let mut map: SmallIntMap<&str> = SmallIntMap::with_capacity(10); + /// use std::collections::VecMap; + /// let mut map: VecMap<&str> = VecMap::with_capacity(10); /// ``` - pub fn with_capacity(capacity: uint) -> SmallIntMap { - SmallIntMap { v: Vec::with_capacity(capacity) } + pub fn with_capacity(capacity: uint) -> VecMap { + VecMap { v: Vec::with_capacity(capacity) } } /// Returns an iterator visiting all keys in ascending order by the keys. @@ -132,9 +132,9 @@ impl SmallIntMap { /// # Example /// /// ``` - /// use std::collections::SmallIntMap; + /// use std::collections::VecMap; /// - /// let mut map = SmallIntMap::new(); + /// let mut map = VecMap::new(); /// map.insert(1, "a"); /// map.insert(3, "c"); /// map.insert(2, "b"); @@ -159,9 +159,9 @@ impl SmallIntMap { /// # Example /// /// ``` - /// use std::collections::SmallIntMap; + /// use std::collections::VecMap; /// - /// let mut map = SmallIntMap::new(); + /// let mut map = VecMap::new(); /// map.insert(1, "a"); /// map.insert(2, "b"); /// map.insert(3, "c"); @@ -183,15 +183,15 @@ impl SmallIntMap { } /// Returns an iterator visiting all key-value pairs in ascending order by - /// the keys, emptying (but not consuming) the original `SmallIntMap`. + /// the keys, emptying (but not consuming) the original `VecMap`. /// The iterator's element type is `(uint, &'r V)`. /// /// # Example /// /// ``` - /// use std::collections::SmallIntMap; + /// use std::collections::VecMap; /// - /// let mut map = SmallIntMap::new(); + /// let mut map = VecMap::new(); /// map.insert(1, "a"); /// map.insert(3, "c"); /// map.insert(2, "b"); @@ -216,9 +216,9 @@ impl SmallIntMap { /// # Example /// /// ``` - /// use std::collections::SmallIntMap; + /// use std::collections::VecMap; /// - /// let mut a = SmallIntMap::new(); + /// let mut a = VecMap::new(); /// assert_eq!(a.len(), 0); /// a.insert(1, "a"); /// assert_eq!(a.len(), 1); @@ -232,9 +232,9 @@ impl SmallIntMap { /// # Example /// /// ``` - /// use std::collections::SmallIntMap; + /// use std::collections::VecMap; /// - /// let mut a = SmallIntMap::new(); + /// let mut a = VecMap::new(); /// assert!(a.is_empty()); /// a.insert(1, "a"); /// assert!(!a.is_empty()); @@ -248,9 +248,9 @@ impl SmallIntMap { /// # Example /// /// ``` - /// use std::collections::SmallIntMap; + /// use std::collections::VecMap; /// - /// let mut a = SmallIntMap::new(); + /// let mut a = VecMap::new(); /// a.insert(1, "a"); /// a.clear(); /// assert!(a.is_empty()); @@ -262,9 +262,9 @@ impl SmallIntMap { /// # Example /// /// ``` - /// use std::collections::SmallIntMap; + /// use std::collections::VecMap; /// - /// let mut map = SmallIntMap::new(); + /// let mut map = VecMap::new(); /// map.insert(1, "a"); /// assert_eq!(map.find(&1), Some(&"a")); /// assert_eq!(map.find(&2), None); @@ -285,9 +285,9 @@ impl SmallIntMap { /// # Example /// /// ``` - /// use std::collections::SmallIntMap; + /// use std::collections::VecMap; /// - /// let mut map = SmallIntMap::new(); + /// let mut map = VecMap::new(); /// map.insert(1, "a"); /// assert_eq!(map.contains_key(&1), true); /// assert_eq!(map.contains_key(&2), false); @@ -302,9 +302,9 @@ impl SmallIntMap { /// # Example /// /// ``` - /// use std::collections::SmallIntMap; + /// use std::collections::VecMap; /// - /// let mut map = SmallIntMap::new(); + /// let mut map = VecMap::new(); /// map.insert(1, "a"); /// match map.find_mut(&1) { /// Some(x) => *x = "b", @@ -330,9 +330,9 @@ impl SmallIntMap { /// # Example /// /// ``` - /// use std::collections::SmallIntMap; + /// use std::collections::VecMap; /// - /// let mut map = SmallIntMap::new(); + /// let mut map = VecMap::new(); /// assert_eq!(map.insert(2, "value"), true); /// assert_eq!(map.insert(2, "value2"), false); /// assert_eq!(map[2], "value2"); @@ -353,9 +353,9 @@ impl SmallIntMap { /// # Example /// /// ``` - /// use std::collections::SmallIntMap; + /// use std::collections::VecMap; /// - /// let mut map = SmallIntMap::new(); + /// let mut map = VecMap::new(); /// assert_eq!(map.remove(&1), false); /// map.insert(1, "a"); /// assert_eq!(map.remove(&1), true); @@ -370,9 +370,9 @@ impl SmallIntMap { /// # Example /// /// ``` - /// use std::collections::SmallIntMap; + /// use std::collections::VecMap; /// - /// let mut map = SmallIntMap::new(); + /// let mut map = VecMap::new(); /// assert_eq!(map.swap(37, "a"), None); /// assert_eq!(map.is_empty(), false); /// @@ -395,9 +395,9 @@ impl SmallIntMap { /// # Example /// /// ``` - /// use std::collections::SmallIntMap; + /// use std::collections::VecMap; /// - /// let mut map = SmallIntMap::new(); + /// let mut map = VecMap::new(); /// map.insert(1, "a"); /// assert_eq!(map.pop(&1), Some("a")); /// assert_eq!(map.pop(&1), None); @@ -410,7 +410,7 @@ impl SmallIntMap { } } -impl SmallIntMap { +impl VecMap { /// Updates a value in the map. If the key already exists in the map, /// modifies the value with `ff` taking `oldval, newval`. /// Otherwise, sets the value to `newval`. @@ -419,9 +419,9 @@ impl SmallIntMap { /// # Example /// /// ``` - /// use std::collections::SmallIntMap; + /// use std::collections::VecMap; /// - /// let mut map = SmallIntMap::new(); + /// let mut map = VecMap::new(); /// /// // Key does not exist, will do a simple insert /// assert!(map.update(1, vec![1i, 2], |mut old, new| { old.extend(new.into_iter()); old })); @@ -443,9 +443,9 @@ impl SmallIntMap { /// # Example /// /// ``` - /// use std::collections::SmallIntMap; + /// use std::collections::VecMap; /// - /// let mut map = SmallIntMap::new(); + /// let mut map = VecMap::new(); /// /// // Key does not exist, will do a simple insert /// assert!(map.update_with_key(7, 10, |key, old, new| (old + new) % key)); @@ -468,21 +468,21 @@ impl SmallIntMap { } } -impl PartialOrd for SmallIntMap { +impl PartialOrd for VecMap { #[inline] - fn partial_cmp(&self, other: &SmallIntMap) -> Option { + fn partial_cmp(&self, other: &VecMap) -> Option { iter::order::partial_cmp(self.iter(), other.iter()) } } -impl Ord for SmallIntMap { +impl Ord for VecMap { #[inline] - fn cmp(&self, other: &SmallIntMap) -> Ordering { + fn cmp(&self, other: &VecMap) -> Ordering { iter::order::cmp(self.iter(), other.iter()) } } -impl fmt::Show for SmallIntMap { +impl fmt::Show for VecMap { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(write!(f, "{{")); @@ -495,15 +495,15 @@ impl fmt::Show for SmallIntMap { } } -impl FromIterator<(uint, V)> for SmallIntMap { - fn from_iter>(iter: Iter) -> SmallIntMap { - let mut map = SmallIntMap::new(); +impl FromIterator<(uint, V)> for VecMap { + fn from_iter>(iter: Iter) -> VecMap { + let mut map = VecMap::new(); map.extend(iter); map } } -impl Extendable<(uint, V)> for SmallIntMap { +impl Extendable<(uint, V)> for VecMap { fn extend>(&mut self, mut iter: Iter) { for (k, v) in iter { self.insert(k, v); @@ -511,14 +511,14 @@ impl Extendable<(uint, V)> for SmallIntMap { } } -impl Index for SmallIntMap { +impl Index for VecMap { #[inline] fn index<'a>(&'a self, i: &uint) -> &'a V { self.find(i).expect("key not present") } } -impl IndexMut for SmallIntMap { +impl IndexMut for VecMap { #[inline] fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut V { self.find_mut(i).expect("key not present") @@ -612,11 +612,11 @@ mod test_map { use vec::Vec; use hash; - use super::SmallIntMap; + use super::VecMap; #[test] fn test_find_mut() { - let mut m = SmallIntMap::new(); + let mut m = VecMap::new(); assert!(m.insert(1, 12i)); assert!(m.insert(2, 8)); assert!(m.insert(5, 14)); @@ -629,7 +629,7 @@ mod test_map { #[test] fn test_len() { - let mut map = SmallIntMap::new(); + let mut map = VecMap::new(); assert_eq!(map.len(), 0); assert!(map.is_empty()); assert!(map.insert(5, 20i)); @@ -645,7 +645,7 @@ mod test_map { #[test] fn test_clear() { - let mut map = SmallIntMap::new(); + let mut map = VecMap::new(); assert!(map.insert(5, 20i)); assert!(map.insert(11, 12)); assert!(map.insert(14, 22)); @@ -658,7 +658,7 @@ mod test_map { #[test] fn test_insert_with_key() { - let mut map = SmallIntMap::new(); + let mut map = VecMap::new(); // given a new key, initialize it with this new count, // given an existing key, add more to its count @@ -688,7 +688,7 @@ mod test_map { #[test] fn test_swap() { - let mut m = SmallIntMap::new(); + let mut m = VecMap::new(); assert_eq!(m.swap(1, 2i), None); assert_eq!(m.swap(1, 3i), Some(2)); assert_eq!(m.swap(1, 4i), Some(3)); @@ -696,7 +696,7 @@ mod test_map { #[test] fn test_pop() { - let mut m = SmallIntMap::new(); + let mut m = VecMap::new(); m.insert(1, 2i); assert_eq!(m.pop(&1), Some(2)); assert_eq!(m.pop(&1), None); @@ -704,7 +704,7 @@ mod test_map { #[test] fn test_keys() { - let mut map = SmallIntMap::new(); + let mut map = VecMap::new(); map.insert(1, 'a'); map.insert(2, 'b'); map.insert(3, 'c'); @@ -717,7 +717,7 @@ mod test_map { #[test] fn test_values() { - let mut map = SmallIntMap::new(); + let mut map = VecMap::new(); map.insert(1, 'a'); map.insert(2, 'b'); map.insert(3, 'c'); @@ -730,7 +730,7 @@ mod test_map { #[test] fn test_iterator() { - let mut m = SmallIntMap::new(); + let mut m = VecMap::new(); assert!(m.insert(0, 1i)); assert!(m.insert(1, 2)); @@ -755,7 +755,7 @@ mod test_map { #[test] fn test_iterator_size_hints() { - let mut m = SmallIntMap::new(); + let mut m = VecMap::new(); assert!(m.insert(0, 1i)); assert!(m.insert(1, 2)); @@ -771,7 +771,7 @@ mod test_map { #[test] fn test_mut_iterator() { - let mut m = SmallIntMap::new(); + let mut m = VecMap::new(); assert!(m.insert(0, 1i)); assert!(m.insert(1, 2)); @@ -794,7 +794,7 @@ mod test_map { #[test] fn test_rev_iterator() { - let mut m = SmallIntMap::new(); + let mut m = VecMap::new(); assert!(m.insert(0, 1i)); assert!(m.insert(1, 2)); @@ -813,7 +813,7 @@ mod test_map { #[test] fn test_mut_rev_iterator() { - let mut m = SmallIntMap::new(); + let mut m = VecMap::new(); assert!(m.insert(0, 1i)); assert!(m.insert(1, 2)); @@ -836,7 +836,7 @@ mod test_map { #[test] fn test_move_iter() { - let mut m = SmallIntMap::new(); + let mut m = VecMap::new(); m.insert(1, box 2i); let mut called = false; for (k, v) in m.into_iter() { @@ -851,8 +851,8 @@ mod test_map { #[test] fn test_show() { - let mut map = SmallIntMap::new(); - let empty = SmallIntMap::::new(); + let mut map = VecMap::new(); + let empty = VecMap::::new(); map.insert(1, 2i); map.insert(3, 4i); @@ -865,7 +865,7 @@ mod test_map { #[test] fn test_clone() { - let mut a = SmallIntMap::new(); + let mut a = VecMap::new(); a.insert(1, 'x'); a.insert(4, 'y'); @@ -876,8 +876,8 @@ mod test_map { #[test] fn test_eq() { - let mut a = SmallIntMap::new(); - let mut b = SmallIntMap::new(); + let mut a = VecMap::new(); + let mut b = VecMap::new(); assert!(a == b); assert!(a.insert(0, 5i)); @@ -894,8 +894,8 @@ mod test_map { #[test] fn test_lt() { - let mut a = SmallIntMap::new(); - let mut b = SmallIntMap::new(); + let mut a = VecMap::new(); + let mut b = VecMap::new(); assert!(!(a < b) && !(b < a)); assert!(b.insert(2u, 5i)); @@ -912,8 +912,8 @@ mod test_map { #[test] fn test_ord() { - let mut a = SmallIntMap::new(); - let mut b = SmallIntMap::new(); + let mut a = VecMap::new(); + let mut b = VecMap::new(); assert!(a <= b && a >= b); assert!(a.insert(1u, 1i)); @@ -926,8 +926,8 @@ mod test_map { #[test] fn test_hash() { - let mut x = SmallIntMap::new(); - let mut y = SmallIntMap::new(); + let mut x = VecMap::new(); + let mut y = VecMap::new(); assert!(hash::hash(&x) == hash::hash(&y)); x.insert(1, 'a'); @@ -945,7 +945,7 @@ mod test_map { fn test_from_iter() { let xs: Vec<(uint, char)> = vec![(1u, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e')]; - let map: SmallIntMap = xs.iter().map(|&x| x).collect(); + let map: VecMap = xs.iter().map(|&x| x).collect(); for &(k, v) in xs.iter() { assert_eq!(map.find(&k), Some(&v)); @@ -954,7 +954,7 @@ mod test_map { #[test] fn test_index() { - let mut map: SmallIntMap = SmallIntMap::new(); + let mut map: VecMap = VecMap::new(); map.insert(1, 2); map.insert(2, 1); @@ -966,7 +966,7 @@ mod test_map { #[test] #[should_fail] fn test_index_nonexistent() { - let mut map: SmallIntMap = SmallIntMap::new(); + let mut map: VecMap = VecMap::new(); map.insert(1, 2); map.insert(2, 1); @@ -980,12 +980,12 @@ mod test_map { mod bench { extern crate test; use self::test::Bencher; - use super::SmallIntMap; + use super::VecMap; use bench::{insert_rand_n, insert_seq_n, find_rand_n, find_seq_n}; #[bench] pub fn insert_rand_100(b: &mut Bencher) { - let mut m : SmallIntMap = SmallIntMap::new(); + let mut m : VecMap = VecMap::new(); insert_rand_n(100, &mut m, b, |m, i| { m.insert(i, 1); }, |m, i| { m.remove(&i); }); @@ -993,7 +993,7 @@ mod bench { #[bench] pub fn insert_rand_10_000(b: &mut Bencher) { - let mut m : SmallIntMap = SmallIntMap::new(); + let mut m : VecMap = VecMap::new(); insert_rand_n(10_000, &mut m, b, |m, i| { m.insert(i, 1); }, |m, i| { m.remove(&i); }); @@ -1002,7 +1002,7 @@ mod bench { // Insert seq #[bench] pub fn insert_seq_100(b: &mut Bencher) { - let mut m : SmallIntMap = SmallIntMap::new(); + let mut m : VecMap = VecMap::new(); insert_seq_n(100, &mut m, b, |m, i| { m.insert(i, 1); }, |m, i| { m.remove(&i); }); @@ -1010,7 +1010,7 @@ mod bench { #[bench] pub fn insert_seq_10_000(b: &mut Bencher) { - let mut m : SmallIntMap = SmallIntMap::new(); + let mut m : VecMap = VecMap::new(); insert_seq_n(10_000, &mut m, b, |m, i| { m.insert(i, 1); }, |m, i| { m.remove(&i); }); @@ -1019,7 +1019,7 @@ mod bench { // Find rand #[bench] pub fn find_rand_100(b: &mut Bencher) { - let mut m : SmallIntMap = SmallIntMap::new(); + let mut m : VecMap = VecMap::new(); find_rand_n(100, &mut m, b, |m, i| { m.insert(i, 1); }, |m, i| { m.find(&i); }); @@ -1027,7 +1027,7 @@ mod bench { #[bench] pub fn find_rand_10_000(b: &mut Bencher) { - let mut m : SmallIntMap = SmallIntMap::new(); + let mut m : VecMap = VecMap::new(); find_rand_n(10_000, &mut m, b, |m, i| { m.insert(i, 1); }, |m, i| { m.find(&i); }); @@ -1036,7 +1036,7 @@ mod bench { // Find seq #[bench] pub fn find_seq_100(b: &mut Bencher) { - let mut m : SmallIntMap = SmallIntMap::new(); + let mut m : VecMap = VecMap::new(); find_seq_n(100, &mut m, b, |m, i| { m.insert(i, 1); }, |m, i| { m.find(&i); }); @@ -1044,7 +1044,7 @@ mod bench { #[bench] pub fn find_seq_10_000(b: &mut Bencher) { - let mut m : SmallIntMap = SmallIntMap::new(); + let mut m : VecMap = VecMap::new(); find_seq_n(10_000, &mut m, b, |m, i| { m.insert(i, 1); }, |m, i| { m.find(&i); }); diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 74b39a7058c0a..ddfbfa7850202 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -250,8 +250,8 @@ pub trait UpperExp for Sized? { fn fmt(&self, &mut Formatter) -> Result; } -// FIXME #11938 - UFCS would make us able call the above methods -// directly Show::show(x, fmt). +// NOTE(stage0): Remove macro after next snapshot +#[cfg(stage0)] macro_rules! uniform_fn_call_workaround { ($( $name: ident, $trait_: ident; )*) => { $( @@ -262,6 +262,8 @@ macro_rules! uniform_fn_call_workaround { )* } } +// NOTE(stage0): Remove macro after next snapshot +#[cfg(stage0)] uniform_fn_call_workaround! { secret_show, Show; secret_bool, Bool; @@ -568,36 +570,65 @@ pub fn argument<'a, T>(f: extern "Rust" fn(&T, &mut Formatter) -> Result, /// When the compiler determines that the type of an argument *must* be a string /// (such as for select), then it invokes this method. +// NOTE(stage0): remove function after a snapshot +#[cfg(stage0)] #[doc(hidden)] #[inline] pub fn argumentstr<'a>(s: &'a &str) -> Argument<'a> { argument(secret_string, s) } +/// When the compiler determines that the type of an argument *must* be a string +/// (such as for select), then it invokes this method. +#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot +#[doc(hidden)] #[inline] +pub fn argumentstr<'a>(s: &'a &str) -> Argument<'a> { + argument(String::fmt, s) +} + /// When the compiler determines that the type of an argument *must* be a uint /// (such as for plural), then it invokes this method. +// NOTE(stage0): remove function after a snapshot +#[cfg(stage0)] #[doc(hidden)] #[inline] pub fn argumentuint<'a>(s: &'a uint) -> Argument<'a> { argument(secret_unsigned, s) } +/// When the compiler determines that the type of an argument *must* be a uint +/// (such as for plural), then it invokes this method. +#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot +#[doc(hidden)] #[inline] +pub fn argumentuint<'a>(s: &'a uint) -> Argument<'a> { + argument(Unsigned::fmt, s) +} + // Implementations of the core formatting traits impl<'a, Sized? T: Show> Show for &'a T { - fn fmt(&self, f: &mut Formatter) -> Result { secret_show(*self, f) } + fn fmt(&self, f: &mut Formatter) -> Result { (**self).fmt(f) } } impl<'a, Sized? T: Show> Show for &'a mut T { - fn fmt(&self, f: &mut Formatter) -> Result { secret_show(&**self, f) } + fn fmt(&self, f: &mut Formatter) -> Result { (**self).fmt(f) } } impl<'a> Show for &'a Show+'a { fn fmt(&self, f: &mut Formatter) -> Result { (*self).fmt(f) } } +// NOTE(stage0): remove impl after a snapshot +#[cfg(stage0)] impl Bool for bool { fn fmt(&self, f: &mut Formatter) -> Result { secret_string(&(if *self {"true"} else {"false"}), f) } } +#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot +impl Bool for bool { + fn fmt(&self, f: &mut Formatter) -> Result { + String::fmt(if *self { "true" } else { "false" }, f) + } +} + impl String for T { fn fmt(&self, f: &mut Formatter) -> Result { f.pad(self.as_slice()) @@ -610,6 +641,8 @@ impl String for str { } } +// NOTE(stage0): remove impl after a snapshot +#[cfg(stage0)] impl Char for char { fn fmt(&self, f: &mut Formatter) -> Result { use char::Char; @@ -621,28 +654,80 @@ impl Char for char { } } +#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot +impl Char for char { + fn fmt(&self, f: &mut Formatter) -> Result { + use char::Char; + + let mut utf8 = [0u8, ..4]; + let amt = self.encode_utf8(utf8).unwrap_or(0); + let s: &str = unsafe { mem::transmute(utf8[..amt]) }; + String::fmt(s, f) + } +} + +// NOTE(stage0): remove impl after a snapshot +#[cfg(stage0)] impl Pointer for *const T { fn fmt(&self, f: &mut Formatter) -> Result { f.flags |= 1 << (rt::FlagAlternate as uint); secret_lower_hex::(&(*self as uint), f) } } + +#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot +impl Pointer for *const T { + fn fmt(&self, f: &mut Formatter) -> Result { + f.flags |= 1 << (rt::FlagAlternate as uint); + LowerHex::fmt(&(*self as uint), f) + } +} + +// NOTE(stage0): remove impl after a snapshot +#[cfg(stage0)] impl Pointer for *mut T { fn fmt(&self, f: &mut Formatter) -> Result { secret_pointer::<*const T>(&(*self as *const T), f) } } + +#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot +impl Pointer for *mut T { + fn fmt(&self, f: &mut Formatter) -> Result { + Pointer::fmt(&(*self as *const T), f) + } +} + +// NOTE(stage0): remove impl after a snapshot +#[cfg(stage0)] impl<'a, T> Pointer for &'a T { fn fmt(&self, f: &mut Formatter) -> Result { secret_pointer::<*const T>(&(&**self as *const T), f) } } + +#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot +impl<'a, T> Pointer for &'a T { + fn fmt(&self, f: &mut Formatter) -> Result { + Pointer::fmt(&(*self as *const T), f) + } +} + +// NOTE(stage0): remove impl after a snapshot +#[cfg(stage0)] impl<'a, T> Pointer for &'a mut T { fn fmt(&self, f: &mut Formatter) -> Result { secret_pointer::<*const T>(&(&**self as *const T), f) } } +#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot +impl<'a, T> Pointer for &'a mut T { + fn fmt(&self, f: &mut Formatter) -> Result { + Pointer::fmt(&(&**self as *const T), f) + } +} + macro_rules! floating(($ty:ident) => { impl Float for $ty { fn fmt(&self, fmt: &mut Formatter) -> Result { @@ -712,6 +797,8 @@ floating!(f64) // Implementation of Show for various core types +// NOTE(stage0): remove macro after a snapshot +#[cfg(stage0)] macro_rules! delegate(($ty:ty to $other:ident) => { impl Show for $ty { fn fmt(&self, f: &mut Formatter) -> Result { @@ -719,19 +806,60 @@ macro_rules! delegate(($ty:ty to $other:ident) => { } } }) + +// NOTE(stage0): remove these macros after a snapshot +#[cfg(stage0)] delegate!(str to string) +#[cfg(stage0)] delegate!(bool to bool) +#[cfg(stage0)] delegate!(char to char) +#[cfg(stage0)] delegate!(f32 to float) +#[cfg(stage0)] delegate!(f64 to float) +#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot +macro_rules! delegate(($ty:ty to $other:ident) => { + impl Show for $ty { + fn fmt(&self, f: &mut Formatter) -> Result { + $other::fmt(self, f) + } + } +}) +#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot +delegate!(str to String) +#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot +delegate!(bool to Bool) +#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot +delegate!(char to Char) +#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot +delegate!(f32 to Float) +#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot +delegate!(f64 to Float) + +// NOTE(stage0): remove impl after a snapshot +#[cfg(stage0)] impl Show for *const T { fn fmt(&self, f: &mut Formatter) -> Result { secret_pointer(self, f) } } + +#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot +impl Show for *const T { + fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(self, f) } +} + +// NOTE(stage0): remove impl after a snapshot +#[cfg(stage0)] impl Show for *mut T { fn fmt(&self, f: &mut Formatter) -> Result { secret_pointer(self, f) } } +#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot +impl Show for *mut T { + fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(self, f) } +} + macro_rules! peel(($name:ident, $($other:ident,)*) => (tuple!($($other,)*))) macro_rules! tuple ( diff --git a/src/libcore/str.rs b/src/libcore/str.rs index dd8c7e9660af7..3b29c25787292 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -1526,7 +1526,7 @@ pub trait StrSlice for Sized? { /// ``` fn ends_with(&self, needle: &str) -> bool; - /// Returns a string with characters that match `to_trim` removed. + /// Returns a string with characters that match `to_trim` removed from the left and the right. /// /// # Arguments /// diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index 906ca45fcc85e..a8a91283a1128 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -145,19 +145,19 @@ pub struct Opt { pub aliases: Vec, } -/// One group of options, e.g., both -h and --help, along with +/// One group of options, e.g., both `-h` and `--help`, along with /// their shared description and properties. #[deriving(Clone, PartialEq, Eq)] pub struct OptGroup { - /// Short Name of the `OptGroup` + /// Short name of the option, e.g. `h` for a `-h` option pub short_name: String, - /// Long Name of the `OptGroup` + /// Long name of the option, e.g. `help` for a `--help` option pub long_name: String, - /// Hint + /// Hint for argument, e.g. `FILE` for a `-o FILE` option pub hint: String, - /// Description + /// Description for usage help text pub desc: String, - /// Whether it has an argument + /// Whether option has an argument pub hasarg: HasArg, /// How often it can occur pub occur: Occur @@ -393,6 +393,12 @@ fn find_opt(opts: &[Opt], nm: Name) -> Option { } /// Create a long option that is required and takes an argument. +/// +/// * `short_name` - e.g. `"h"` for a `-h` option, or `""` for none +/// * `long_name` - e.g. `"help"` for a `--help` option, or `""` for none +/// * `desc` - Description for usage help +/// * `hint` - Hint that is used in place of the argument in the usage help, +/// e.g. `"FILE"` for a `-o FILE` option pub fn reqopt(short_name: &str, long_name: &str, desc: &str, hint: &str) -> OptGroup { let len = short_name.len(); assert!(len == 1 || len == 0); @@ -407,6 +413,12 @@ pub fn reqopt(short_name: &str, long_name: &str, desc: &str, hint: &str) -> OptG } /// Create a long option that is optional and takes an argument. +/// +/// * `short_name` - e.g. `"h"` for a `-h` option, or `""` for none +/// * `long_name` - e.g. `"help"` for a `--help` option, or `""` for none +/// * `desc` - Description for usage help +/// * `hint` - Hint that is used in place of the argument in the usage help, +/// e.g. `"FILE"` for a `-o FILE` option pub fn optopt(short_name: &str, long_name: &str, desc: &str, hint: &str) -> OptGroup { let len = short_name.len(); assert!(len == 1 || len == 0); @@ -421,6 +433,10 @@ pub fn optopt(short_name: &str, long_name: &str, desc: &str, hint: &str) -> OptG } /// Create a long option that is optional and does not take an argument. +/// +/// * `short_name` - e.g. `"h"` for a `-h` option, or `""` for none +/// * `long_name` - e.g. `"help"` for a `--help` option, or `""` for none +/// * `desc` - Description for usage help pub fn optflag(short_name: &str, long_name: &str, desc: &str) -> OptGroup { let len = short_name.len(); assert!(len == 1 || len == 0); @@ -436,6 +452,10 @@ pub fn optflag(short_name: &str, long_name: &str, desc: &str) -> OptGroup { /// Create a long option that can occur more than once and does not /// take an argument. +/// +/// * `short_name` - e.g. `"h"` for a `-h` option, or `""` for none +/// * `long_name` - e.g. `"help"` for a `--help` option, or `""` for none +/// * `desc` - Description for usage help pub fn optflagmulti(short_name: &str, long_name: &str, desc: &str) -> OptGroup { let len = short_name.len(); assert!(len == 1 || len == 0); @@ -450,6 +470,12 @@ pub fn optflagmulti(short_name: &str, long_name: &str, desc: &str) -> OptGroup { } /// Create a long option that is optional and takes an optional argument. +/// +/// * `short_name` - e.g. `"h"` for a `-h` option, or `""` for none +/// * `long_name` - e.g. `"help"` for a `--help` option, or `""` for none +/// * `desc` - Description for usage help +/// * `hint` - Hint that is used in place of the argument in the usage help, +/// e.g. `"FILE"` for a `-o FILE` option pub fn optflagopt(short_name: &str, long_name: &str, desc: &str, hint: &str) -> OptGroup { let len = short_name.len(); assert!(len == 1 || len == 0); @@ -465,6 +491,12 @@ pub fn optflagopt(short_name: &str, long_name: &str, desc: &str, hint: &str) -> /// Create a long option that is optional, takes an argument, and may occur /// multiple times. +/// +/// * `short_name` - e.g. `"h"` for a `-h` option, or `""` for none +/// * `long_name` - e.g. `"help"` for a `--help` option, or `""` for none +/// * `desc` - Description for usage help +/// * `hint` - Hint that is used in place of the argument in the usage help, +/// e.g. `"FILE"` for a `-o FILE` option pub fn optmulti(short_name: &str, long_name: &str, desc: &str, hint: &str) -> OptGroup { let len = short_name.len(); assert!(len == 1 || len == 0); diff --git a/src/librustc/driver/config.rs b/src/librustc/driver/config.rs index ace5ba26fdbaa..10c40a32da666 100644 --- a/src/librustc/driver/config.rs +++ b/src/librustc/driver/config.rs @@ -20,6 +20,7 @@ use back::write; use back::target_strs; use back::{arm, x86, x86_64, mips, mipsel}; use lint; +use metadata::cstore; use syntax::abi; use syntax::ast; @@ -31,7 +32,7 @@ use syntax::parse; use syntax::parse::token::InternedString; use std::collections::HashMap; -use std::collections::hashmap::{Occupied, Vacant}; +use std::collections::hash_map::{Occupied, Vacant}; use getopts::{optopt, optmulti, optflag, optflagopt}; use getopts; use std::cell::{RefCell}; @@ -78,6 +79,7 @@ pub struct Options { // parsed code. It remains mutable in case its replacements wants to use // this. pub addl_lib_search_paths: RefCell>, + pub libs: Vec<(String, cstore::NativeLibaryKind)>, pub maybe_sysroot: Option, pub target_triple: String, // User-specified cfg meta items. The compiler itself will add additional @@ -130,6 +132,7 @@ pub fn basic_options() -> Options { externs: HashMap::new(), crate_name: None, alt_std_name: None, + libs: Vec::new(), } } @@ -575,6 +578,10 @@ pub fn optgroups() -> Vec { optflag("h", "help", "Display this message"), optmulti("", "cfg", "Configure the compilation environment", "SPEC"), optmulti("L", "", "Add a directory to the library search path", "PATH"), + optmulti("l", "", "Link the generated crate(s) to the specified native + library NAME. The optional KIND can be one of, + static, dylib, or framework. If omitted, dylib is + assumed.", "NAME[:KIND]"), optmulti("", "crate-type", "Comma separated list of types of crates for the compiler to emit", "[bin|lib|rlib|dylib|staticlib]"), @@ -767,6 +774,23 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { Path::new(s.as_slice()) }).collect(); + let libs = matches.opt_strs("l").into_iter().map(|s| { + let mut parts = s.as_slice().rsplitn(1, ':'); + let kind = parts.next().unwrap(); + let (name, kind) = match (parts.next(), kind) { + (None, name) | + (Some(name), "dylib") => (name, cstore::NativeUnknown), + (Some(name), "framework") => (name, cstore::NativeFramework), + (Some(name), "static") => (name, cstore::NativeStatic), + (_, s) => { + early_error(format!("unknown library kind `{}`, expected \ + one of dylib, framework, or static", + s).as_slice()); + } + }; + (name.to_string(), kind) + }).collect(); + let cfg = parse_cfgspecs(matches.opt_strs("cfg")); let test = matches.opt_present("test"); let write_dependency_info = (matches.opt_present("dep-info"), @@ -843,7 +867,8 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { color: color, externs: externs, crate_name: crate_name, - alt_std_name: None + alt_std_name: None, + libs: libs, } } diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 76ef6206d6416..e52e1396b238f 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -37,7 +37,7 @@ use lint::{Context, LintPass, LintArray}; use std::cmp; use std::collections::HashMap; -use std::collections::hashmap::{Occupied, Vacant}; +use std::collections::hash_map::{Occupied, Vacant}; use std::slice; use std::{int, i8, i16, i32, i64, uint, u8, u16, u32, u64, f32, f64}; use syntax::abi; diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 92b2382ae64f4..797bc5814fc56 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -24,7 +24,7 @@ use plugin::load::PluginMetadata; use std::rc::Rc; use std::collections::HashMap; -use std::collections::hashmap::{Occupied, Vacant}; +use std::collections::hash_map::{Occupied, Vacant}; use syntax::ast; use syntax::abi; use syntax::attr; @@ -52,7 +52,11 @@ pub fn read_crates(sess: &Session, visit_crate(&e, krate); visit::walk_crate(&mut e, krate); dump_crates(&sess.cstore); - warn_if_multiple_versions(sess.diagnostic(), &sess.cstore) + warn_if_multiple_versions(sess.diagnostic(), &sess.cstore); + + for &(ref name, kind) in sess.opts.libs.iter() { + register_native_lib(sess, None, name.clone(), kind); + } } impl<'a, 'v> visit::Visitor<'v> for Env<'a> { @@ -233,15 +237,8 @@ fn visit_item(e: &Env, i: &ast::Item) { Some(k) => { if k.equiv(&("static")) { cstore::NativeStatic - } else if (e.sess.targ_cfg.os == abi::OsMacos || - e.sess.targ_cfg.os == abi::OsiOS) && - k.equiv(&("framework")) { - cstore::NativeFramework } else if k.equiv(&("framework")) { - e.sess.span_err(m.span, - "native frameworks are only available \ - on OSX targets"); - cstore::NativeUnknown + cstore::NativeFramework } else { e.sess.span_err(m.span, format!("unknown kind: `{}`", @@ -263,15 +260,8 @@ fn visit_item(e: &Env, i: &ast::Item) { InternedString::new("foo") } }; - if n.get().is_empty() { - e.sess.span_err(m.span, - "#[link(name = \"\")] given with \ - empty name"); - } else { - e.sess - .cstore - .add_used_library(n.get().to_string(), kind); - } + register_native_lib(e.sess, Some(m.span), + n.get().to_string(), kind); } None => {} } @@ -281,6 +271,32 @@ fn visit_item(e: &Env, i: &ast::Item) { } } +fn register_native_lib(sess: &Session, span: Option, name: String, + kind: cstore::NativeLibaryKind) { + if name.as_slice().is_empty() { + match span { + Some(span) => { + sess.span_err(span, "#[link(name = \"\")] given with \ + empty name"); + } + None => { + sess.err("empty library name given via `-l`"); + } + } + return + } + let is_osx = sess.targ_cfg.os == abi::OsMacos || + sess.targ_cfg.os == abi::OsiOS; + if kind == cstore::NativeFramework && !is_osx { + let msg = "native frameworks are only available on OSX targets"; + match span { + Some(span) => sess.span_err(span, msg), + None => sess.err(msg), + } + } + sess.cstore.add_used_library(name, kind); +} + fn existing_match(e: &Env, name: &str, hash: Option<&Svh>) -> Option { let mut ret = None; diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index e6a0363fcbf50..ff78491c2ad9d 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -31,7 +31,7 @@ use syntax::attr; use syntax::diagnostic::expect; use syntax::parse::token; -use std::collections::hashmap::HashMap; +use std::collections::hash_map::HashMap; pub struct MethodInfo { pub name: ast::Name, diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs index 1d1012d9e4f04..e8c5f6f4910e0 100644 --- a/src/librustc/metadata/cstore.rs +++ b/src/librustc/metadata/cstore.rs @@ -50,7 +50,7 @@ pub enum LinkagePreference { RequireStatic, } -#[deriving(PartialEq, FromPrimitive)] +#[deriving(PartialEq, FromPrimitive, Clone)] pub enum NativeLibaryKind { NativeStatic, // native static library (.a archive) NativeFramework, // OSX-specific diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 0df98bfb0b16d..20171ecfd99f7 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -34,7 +34,7 @@ use std::hash::Hash; use std::hash; use std::io::extensions::u64_from_be_bytes; use std::io; -use std::collections::hashmap::HashMap; +use std::collections::hash_map::HashMap; use std::rc::Rc; use std::u64; use rbml::reader; diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index 623a763bd7468..7b67def405176 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -237,7 +237,7 @@ use std::slice; use std::string; use std::collections::{HashMap, HashSet}; -use std::collections::hashmap::{Occupied, Vacant}; +use std::collections::hash_map::{Occupied, Vacant}; use flate; use time; diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 3d2bd763a1434..988f7d46f5f95 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -441,19 +441,13 @@ impl tr for def::Def { fn tr(&self, dcx: &DecodeContext) -> def::Def { match *self { def::DefFn(did, is_ctor) => def::DefFn(did.tr(dcx), is_ctor), - def::DefStaticMethod(did, wrapped_did2) => { - def::DefStaticMethod(did.tr(dcx), - match wrapped_did2 { - def::FromTrait(did2) => { - def::FromTrait(did2.tr(dcx)) - } - def::FromImpl(did2) => { - def::FromImpl(did2.tr(dcx)) - } - }) + def::DefStaticMethod(did, p) => { + def::DefStaticMethod(did.tr(dcx), p.map(|did2| did2.tr(dcx))) } def::DefMethod(did0, did1, p) => { - def::DefMethod(did0.tr(dcx), did1.map(|did1| did1.tr(dcx)), p) + def::DefMethod(did0.tr(dcx), + did1.map(|did1| did1.tr(dcx)), + p.map(|did2| did2.tr(dcx))) } def::DefSelfTy(nid) => { def::DefSelfTy(dcx.tr_id(nid)) } def::DefMod(did) => { def::DefMod(did.tr(dcx)) } diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index ad0040608ece8..ce91bd1b15388 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -28,7 +28,7 @@ use syntax::visit; use syntax::{ast, ast_map, ast_util, codemap}; use std::rc::Rc; -use std::collections::hashmap::Vacant; +use std::collections::hash_map::Vacant; // // This pass classifies expressions by their constant-ness. diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 80cef763d24e7..ec09706f97e80 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -51,7 +51,7 @@ struct MarkSymbolVisitor<'a, 'tcx: 'a> { tcx: &'a ty::ctxt<'tcx>, live_symbols: Box>, struct_has_extern_repr: bool, - ignore_paths: bool + ignore_non_const_paths: bool } impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { @@ -62,7 +62,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { tcx: tcx, live_symbols: box HashSet::new(), struct_has_extern_repr: false, - ignore_paths: false + ignore_non_const_paths: false } } @@ -76,6 +76,10 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { fn lookup_and_handle_definition(&mut self, id: &ast::NodeId) { self.tcx.def_map.borrow().find(id).map(|def| { match def { + &def::DefConst(_) => { + self.check_def_id(def.def_id()) + } + _ if self.ignore_non_const_paths => (), &def::DefPrimTy(_) => (), &def::DefVariant(enum_id, variant_id, _) => { self.check_def_id(enum_id); @@ -283,21 +287,19 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> { self.handle_field_pattern_match(pat, fields.as_slice()); } _ if pat_util::pat_is_const(def_map, pat) => { - // it might be the only use of a static: + // it might be the only use of a const self.lookup_and_handle_definition(&pat.id) } _ => () } - self.ignore_paths = true; + self.ignore_non_const_paths = true; visit::walk_pat(self, pat); - self.ignore_paths = false; + self.ignore_non_const_paths = false; } fn visit_path(&mut self, path: &ast::Path, id: ast::NodeId) { - if !self.ignore_paths { - self.lookup_and_handle_definition(&id); - } + self.lookup_and_handle_definition(&id); visit::walk_path(self, path); } diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs index a71f714a2efd7..160bb2238e7db 100644 --- a/src/librustc/middle/def.rs +++ b/src/librustc/middle/def.rs @@ -55,6 +55,15 @@ pub enum MethodProvenance { FromImpl(ast::DefId), } +impl MethodProvenance { + pub fn map(self, f: |ast::DefId| -> ast::DefId) -> MethodProvenance { + match self { + FromTrait(did) => FromTrait(f(did)), + FromImpl(did) => FromImpl(f(did)) + } + } +} + impl Def { pub fn def_id(&self) -> ast::DefId { match *self { diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index c297bdc6ca2e7..a2bea790c9f46 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -58,7 +58,7 @@ use syntax::visit; use syntax::visit::Visitor; use std::collections::{HashMap, HashSet}; -use std::collections::hashmap::{Occupied, Vacant}; +use std::collections::hash_map::{Occupied, Vacant}; use std::cell::{Cell, RefCell}; use std::mem::replace; use std::rc::{Rc, Weak}; diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index f8c1c37452b38..eb58c99e55925 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -29,7 +29,7 @@ use middle::typeck::infer; use middle::typeck::infer::{InferCtxt, TypeSkolemizer}; use middle::ty_fold::TypeFoldable; use std::cell::RefCell; -use std::collections::hashmap::HashMap; +use std::collections::hash_map::HashMap; use std::rc::Rc; use syntax::ast; use util::ppaux::Repr; @@ -1104,18 +1104,29 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { * Returns true if `candidate_i` should be dropped in favor of `candidate_j`. * This is generally true if either: * - candidate i and candidate j are equivalent; or, - * - candidate i is a where clause bound and candidate j is a concrete impl, + * - candidate i is a conrete impl and candidate j is a where clause bound, * and the concrete impl is applicable to the types in the where clause bound. * - * The last case basically occurs with blanket impls like - * `impl Foo for T`. In that case, a bound like `T:Foo` is - * kind of an "false" ambiguity -- both are applicable to any - * type, but in fact coherence requires that the bound will - * always be resolved to the impl anyway. + * The last case refers to cases where there are blanket impls (often conditional + * blanket impls) as well as a where clause. This can come down to one of two cases: + * + * - The impl is truly unconditional (it has no where clauses + * of its own), in which case the where clause is + * unnecessary, because coherence requires that we would + * pick that particular impl anyhow (at least so long as we + * don't have specialization). + * + * - The impl is conditional, in which case we may not have winnowed it out + * because we don't know if the conditions apply, but the where clause is basically + * telling us taht there is some impl, though not necessarily the one we see. + * + * In both cases we prefer to take the where clause, which is + * essentially harmless. See issue #18453 for more details of + * a case where doing the opposite caused us harm. */ match (candidate_i, candidate_j) { - (&ParamCandidate(ref vt), &ImplCandidate(impl_def_id)) => { + (&ImplCandidate(impl_def_id), &ParamCandidate(ref vt)) => { debug!("Considering whether to drop param {} in favor of impl {}", candidate_i.repr(self.tcx()), candidate_j.repr(self.tcx())); diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index 44613e85a82cb..decd238627c20 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -623,7 +623,7 @@ pub fn get_wrapper_for_bare_fn(ccx: &CrateContext, let retval = Call(bcx, fn_ptr, llargs.as_slice(), None); match f.sig.output { ty::FnConverging(output_type) => { - if type_is_zero_size(ccx, output_type) || fcx.llretslotptr.get().is_some() { + if return_type_is_void(ccx, output_type) || fcx.llretslotptr.get().is_some() { RetVoid(bcx); } else { Ret(bcx, retval); diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 60b107c049f41..8b5e82ecf9012 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -502,7 +502,11 @@ impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> { } fn node_method_ty(&self, method_call: typeck::MethodCall) -> Option { - self.tcx().method_map.borrow().find(&method_call).map(|method| method.ty) + self.tcx() + .method_map + .borrow() + .find(&method_call) + .map(|method| monomorphize_type(self, method.ty)) } fn adjustments<'a>(&'a self) -> &'a RefCell> { diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index f516c6106a991..a0ba2996334b9 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -745,18 +745,6 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // Translate index expression. let ix_datum = unpack_datum!(bcx, trans(bcx, idx)); - // Overloaded. Evaluate `trans_overloaded_op`, which will - // invoke the user's index() method, which basically yields - // a `&T` pointer. We can then proceed down the normal - // path (below) to dereference that `&T`. - let val = - unpack_result!(bcx, - trans_overloaded_op(bcx, - index_expr, - method_call, - base_datum, - vec![(ix_datum, idx.id)], - None)); let ref_ty = ty::ty_fn_ret(monomorphize_type(bcx, method_ty)).unwrap(); let elt_ty = match ty::deref(ref_ty, true) { None => { @@ -766,7 +754,25 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } Some(elt_tm) => elt_tm.ty, }; - Datum::new(val, elt_ty, LvalueExpr) + + // Overloaded. Evaluate `trans_overloaded_op`, which will + // invoke the user's index() method, which basically yields + // a `&T` pointer. We can then proceed down the normal + // path (below) to dereference that `&T`. + let scratch = rvalue_scratch_datum(bcx, ref_ty, "overloaded_index_elt"); + unpack_result!(bcx, + trans_overloaded_op(bcx, + index_expr, + method_call, + base_datum, + vec![(ix_datum, idx.id)], + Some(SaveIn(scratch.val)))); + let datum = scratch.to_expr_datum(); + if ty::type_is_sized(bcx.tcx(), elt_ty) { + Datum::new(datum.to_llscalarish(bcx), elt_ty, LvalueExpr) + } else { + Datum::new(datum.val, ty::mk_open(bcx.tcx(), elt_ty), LvalueExpr) + } } None => { let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index b9af31665a113..4c088e42243e1 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -43,7 +43,7 @@ use std::mem; use std::ops; use std::rc::Rc; use std::collections::{HashMap, HashSet}; -use std::collections::hashmap::{Occupied, Vacant}; +use std::collections::hash_map::{Occupied, Vacant}; use arena::TypedArena; use syntax::abi; use syntax::ast::{CrateNum, DefId, FnStyle, Ident, ItemTrait, LOCAL_CRATE}; diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index 66d4f73eacc87..dba1fe966f147 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -998,14 +998,14 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( Some(i as uint)), _ => { tcx.sess.span_fatal( - ast_ty.span, "expected constant expr for vector length"); + ast_ty.span, "expected constant expr for array length"); } } } Err(ref r) => { tcx.sess.span_fatal( ast_ty.span, - format!("expected constant expr for vector \ + format!("expected constant expr for array \ length: {}", *r).as_slice()); } diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index 97c6cf24f0e19..a686a5e72a0a7 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -19,7 +19,7 @@ use middle::typeck::require_same_types; use std::cmp; use std::collections::HashMap; -use std::collections::hashmap::{Occupied, Vacant}; +use std::collections::hash_map::{Occupied, Vacant}; use syntax::ast; use syntax::ast_util; use syntax::codemap::{Span, Spanned}; diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index f334d8016927d..c280474a076a0 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -118,7 +118,7 @@ use util::nodemap::{DefIdMap, FnvHashMap, NodeMap}; use std::cell::{Cell, Ref, RefCell}; use std::collections::HashMap; -use std::collections::hashmap::{Occupied, Vacant}; +use std::collections::hash_map::{Occupied, Vacant}; use std::mem::replace; use std::rc::Rc; use syntax::abi; diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index d0338333badee..acc3cf0307b96 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -142,7 +142,7 @@ use syntax::visit::Visitor; use std::cell::{RefCell}; use std::collections::HashMap; -use std::collections::hashmap::{Vacant, Occupied}; +use std::collections::hash_map::{Vacant, Occupied}; /////////////////////////////////////////////////////////////////////////// // PUBLIC ENTRY POINTS diff --git a/src/librustc/middle/typeck/check/regionmanip.rs b/src/librustc/middle/typeck/check/regionmanip.rs index 225a3162af904..91e9c18853c80 100644 --- a/src/librustc/middle/typeck/check/regionmanip.rs +++ b/src/librustc/middle/typeck/check/regionmanip.rs @@ -18,7 +18,7 @@ use middle::ty_fold::{TypeFolder, TypeFoldable}; use syntax::ast; use std::collections::HashMap; -use std::collections::hashmap::{Occupied, Vacant}; +use std::collections::hash_map::{Occupied, Vacant}; use util::ppaux::Repr; // Helper functions related to manipulating region types. diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index a17194f008565..87b0aed4ac49c 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -187,7 +187,11 @@ pub fn check_object_safety(tcx: &ty::ctxt, object_trait: &ty::TyTrait, span: Spa receiver through a trait object", method_name)) } - ty::StaticExplicitSelfCategory | + ty::StaticExplicitSelfCategory => { + // Static methods are always object-safe since they + // can't be called through a trait object + return msgs + } ty::ByReferenceExplicitSelfCategory(..) | ty::ByBoxExplicitSelfCategory => {} } diff --git a/src/librustc/middle/typeck/infer/skolemize.rs b/src/librustc/middle/typeck/infer/skolemize.rs index 0fe1e2b565bef..6e5e8d72839eb 100644 --- a/src/librustc/middle/typeck/infer/skolemize.rs +++ b/src/librustc/middle/typeck/infer/skolemize.rs @@ -44,7 +44,7 @@ use middle::ty; use middle::ty_fold; use middle::ty_fold::TypeFoldable; use middle::ty_fold::TypeFolder; -use std::collections::hashmap; +use std::collections::hash_map; use super::InferCtxt; use super::unify::InferCtxtMethodsForSimplyUnifiableTypes; @@ -52,7 +52,7 @@ use super::unify::InferCtxtMethodsForSimplyUnifiableTypes; pub struct TypeSkolemizer<'a, 'tcx:'a> { infcx: &'a InferCtxt<'a, 'tcx>, skolemization_count: uint, - skolemization_map: hashmap::HashMap, + skolemization_map: hash_map::HashMap, } impl<'a, 'tcx> TypeSkolemizer<'a, 'tcx> { @@ -60,7 +60,7 @@ impl<'a, 'tcx> TypeSkolemizer<'a, 'tcx> { TypeSkolemizer { infcx: infcx, skolemization_count: 0, - skolemization_map: hashmap::HashMap::new(), + skolemization_map: hash_map::HashMap::new(), } } @@ -76,8 +76,8 @@ impl<'a, 'tcx> TypeSkolemizer<'a, 'tcx> { } match self.skolemization_map.entry(key) { - hashmap::Occupied(entry) => *entry.get(), - hashmap::Vacant(entry) => { + hash_map::Occupied(entry) => *entry.get(), + hash_map::Vacant(entry) => { let index = self.skolemization_count; self.skolemization_count += 1; let t = ty::mk_infer(self.infcx.tcx, skolemizer(index)); diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index d1d9702a134f6..9af2b22adea45 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -34,7 +34,7 @@ //! both occur before the crate is rendered. use std::collections::{HashMap, HashSet}; -use std::collections::hashmap::{Occupied, Vacant}; +use std::collections::hash_map::{Occupied, Vacant}; use std::fmt; use std::io::fs::PathExtensions; use std::io::{fs, File, BufferedWriter, MemWriter, BufferedReader}; diff --git a/src/librustdoc/html/static/SourceSerifPro-Bold.woff b/src/librustdoc/html/static/SourceSerifPro-Bold.woff index 435a6f975c97c..ac1b1b3a0bb7a 100644 Binary files a/src/librustdoc/html/static/SourceSerifPro-Bold.woff and b/src/librustdoc/html/static/SourceSerifPro-Bold.woff differ diff --git a/src/librustdoc/html/static/main.css b/src/librustdoc/html/static/main.css index 7eec634405b72..7cc34798f9904 100644 --- a/src/librustdoc/html/static/main.css +++ b/src/librustdoc/html/static/main.css @@ -69,6 +69,10 @@ body { margin: 0; position: relative; padding: 10px 15px 20px 15px; + + -webkit-font-feature-settings: "kern", "liga"; + -moz-font-feature-settings: "kern", "liga"; + font-feature-settings: "kern", "liga"; } h1 { @@ -101,7 +105,7 @@ h3.impl, h3.method, h4.method { h3.impl, h3.method { margin-top: 15px; } -h1, h2, h3, h4, section.sidebar, a.source, .search-input, .content table a, .collapse-toggle { +h1, h2, h3, h4, section.sidebar, a.source, .search-input, .content table :not(code)>a, .collapse-toggle { font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; } @@ -177,7 +181,7 @@ nav.sub { color: #333; } -.location a:first-child { font-weight: bold; } +.location a:first-child { font-weight: 500; } .block { padding: 0 10px; @@ -494,7 +498,7 @@ pre.rust { position: relative; } } .collapse-toggle { - font-weight: 100; + font-weight: 300; position: absolute; left: 13px; color: #999; @@ -523,7 +527,6 @@ pre.rust { position: relative; } .toggle-label { color: #999; - font-style: italic; } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 5f404238beb30..bd3c618a5ed46 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -31,7 +31,7 @@ extern crate time; use std::io; use std::io::{File, MemWriter}; use std::collections::HashMap; -use std::collections::hashmap::{Occupied, Vacant}; +use std::collections::hash_map::{Occupied, Vacant}; use serialize::{json, Decodable, Encodable}; use externalfiles::ExternalHtml; diff --git a/src/librustrt/local_data.rs b/src/librustrt/local_data.rs index ee69f5f5235dc..7129f14720911 100644 --- a/src/librustrt/local_data.rs +++ b/src/librustrt/local_data.rs @@ -41,7 +41,7 @@ assert_eq!(*key_vector.get().unwrap(), vec![4]); use core::prelude::*; use alloc::heap; -use collections::treemap::TreeMap; +use collections::TreeMap; use core::cmp; use core::kinds::marker; use core::mem; diff --git a/src/libstd/collections/hashmap/bench.rs b/src/libstd/collections/hash/bench.rs similarity index 91% rename from src/libstd/collections/hashmap/bench.rs rename to src/libstd/collections/hash/bench.rs index 21bbb38f48936..62b93336a34bd 100644 --- a/src/libstd/collections/hashmap/bench.rs +++ b/src/libstd/collections/hash/bench.rs @@ -18,7 +18,7 @@ use iter::{range_inclusive}; #[bench] fn new_drop(b : &mut Bencher) { - use super::HashMap; + use super::map::HashMap; b.iter(|| { let m : HashMap = HashMap::new(); @@ -28,7 +28,7 @@ fn new_drop(b : &mut Bencher) { #[bench] fn new_insert_drop(b : &mut Bencher) { - use super::HashMap; + use super::map::HashMap; b.iter(|| { let mut m = HashMap::new(); @@ -39,7 +39,7 @@ fn new_insert_drop(b : &mut Bencher) { #[bench] fn grow_by_insertion(b: &mut Bencher) { - use super::HashMap; + use super::map::HashMap; let mut m = HashMap::new(); @@ -57,7 +57,7 @@ fn grow_by_insertion(b: &mut Bencher) { #[bench] fn find_existing(b: &mut Bencher) { - use super::HashMap; + use super::map::HashMap; let mut m = HashMap::new(); @@ -74,7 +74,7 @@ fn find_existing(b: &mut Bencher) { #[bench] fn find_nonexisting(b: &mut Bencher) { - use super::HashMap; + use super::map::HashMap; let mut m = HashMap::new(); @@ -91,7 +91,7 @@ fn find_nonexisting(b: &mut Bencher) { #[bench] fn hashmap_as_queue(b: &mut Bencher) { - use super::HashMap; + use super::map::HashMap; let mut m = HashMap::new(); @@ -110,7 +110,7 @@ fn hashmap_as_queue(b: &mut Bencher) { #[bench] fn find_pop_insert(b: &mut Bencher) { - use super::HashMap; + use super::map::HashMap; let mut m = HashMap::new(); diff --git a/src/libstd/collections/hashmap/map.rs b/src/libstd/collections/hash/map.rs similarity index 100% rename from src/libstd/collections/hashmap/map.rs rename to src/libstd/collections/hash/map.rs diff --git a/src/libstd/collections/hashmap/mod.rs b/src/libstd/collections/hash/mod.rs similarity index 52% rename from src/libstd/collections/hashmap/mod.rs rename to src/libstd/collections/hash/mod.rs index 6508d4609f147..ee3fc1e6ac362 100644 --- a/src/libstd/collections/hashmap/mod.rs +++ b/src/libstd/collections/hash/mod.rs @@ -10,24 +10,7 @@ //! Unordered containers, implemented as hash-tables -pub use self::map::HashMap; -pub use self::map::Entries; -pub use self::map::MutEntries; -pub use self::map::MoveEntries; -pub use self::map::Entry; -pub use self::map::Occupied; -pub use self::map::Vacant; -pub use self::map::OccupiedEntry; -pub use self::map::VacantEntry; -pub use self::map::Keys; -pub use self::map::Values; -pub use self::map::INITIAL_CAPACITY; -pub use self::set::HashSet; -pub use self::set::SetItems; -pub use self::set::SetMoveItems; -pub use self::set::SetAlgebraItems; - mod bench; -mod map; -mod set; +pub mod map; +pub mod set; mod table; diff --git a/src/libstd/collections/hashmap/set.rs b/src/libstd/collections/hash/set.rs similarity index 99% rename from src/libstd/collections/hashmap/set.rs rename to src/libstd/collections/hash/set.rs index 69f3812425f64..823bd49d7a663 100644 --- a/src/libstd/collections/hashmap/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -22,7 +22,7 @@ use iter; use option::{Some, None}; use result::{Ok, Err}; -use super::{HashMap, Entries, MoveEntries, INITIAL_CAPACITY}; +use super::map::{HashMap, Entries, MoveEntries, INITIAL_CAPACITY}; // Future Optimization (FIXME!) diff --git a/src/libstd/collections/hashmap/table.rs b/src/libstd/collections/hash/table.rs similarity index 100% rename from src/libstd/collections/hashmap/table.rs rename to src/libstd/collections/hash/table.rs diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs index be9e22ee9d14c..13486d4b8f84d 100644 --- a/src/libstd/collections/mod.rs +++ b/src/libstd/collections/mod.rs @@ -24,9 +24,9 @@ //! Rust's collections can be grouped into four major categories: //! //! * Sequences: `Vec`, `RingBuf`, `DList`, `BitV` -//! * Maps: `HashMap`, `BTreeMap`, `TreeMap`, `TrieMap`, `SmallIntMap`, `LruCache` +//! * Maps: `HashMap`, `BTreeMap`, `TreeMap`, `TrieMap`, `VecMap`, `LruCache` //! * Sets: `HashSet`, `BTreeSet`, `TreeSet`, `TrieSet`, `BitVSet`, `EnumSet` -//! * Misc: `PriorityQueue` +//! * Misc: `BinaryHeap` //! //! # When Should You Use Which Collection? //! @@ -74,7 +74,7 @@ //! * You want a `HashMap`, but with many potentially large `uint` keys. //! * You want a `BTreeMap`, but with potentially large `uint` keys. //! -//! ### Use a `SmallIntMap` when: +//! ### Use a `VecMap` when: //! * You want a `HashMap` but with known to be small `uint` keys. //! * You want a `BTreeMap`, but with known to be small `uint` keys. //! @@ -88,12 +88,12 @@ //! * You want a bitvector. //! //! ### Use a `BitVSet` when: -//! * You want a `SmallIntSet`. +//! * You want a `VecSet`. //! //! ### Use an `EnumSet` when: //! * You want a C-like enum, stored in a single `uint`. //! -//! ### Use a `PriorityQueue` when: +//! ### Use a `BinaryHeap` when: //! * You want to store a bunch of elements, but only ever want to process the "biggest" //! or "most important" one at any given time. //! * You want a priority queue. @@ -266,7 +266,7 @@ //! #### Counting the number of times each character in a string occurs //! //! ``` -//! use std::collections::btree::{BTreeMap, Occupied, Vacant}; +//! use std::collections::btree_map::{BTreeMap, Occupied, Vacant}; //! //! let mut count = BTreeMap::new(); //! let message = "she sells sea shells by the sea shore"; @@ -293,7 +293,7 @@ //! #### Tracking the inebriation of customers at a bar //! //! ``` -//! use std::collections::btree::{BTreeMap, Occupied, Vacant}; +//! use std::collections::btree_map::{BTreeMap, Occupied, Vacant}; //! //! // A client of the bar. They have an id and a blood alcohol level. //! struct Person { id: u32, blood_alcohol: f32 }; @@ -328,14 +328,27 @@ #![experimental] -pub use core_collections::{Bitv, BitvSet, BTreeMap, BTreeSet, DList, EnumSet}; -pub use core_collections::{PriorityQueue, RingBuf, SmallIntMap}; -pub use core_collections::{TreeMap, TreeSet, TrieMap, TrieSet}; -pub use core_collections::{bitv, btree, dlist, enum_set}; -pub use core_collections::{priority_queue, ringbuf, smallintmap, treemap, trie}; +pub use core_collections::{BinaryHeap, Bitv, BitvSet, BTreeMap, BTreeSet}; +pub use core_collections::{DList, EnumSet, RingBuf}; +pub use core_collections::{TreeMap, TreeSet, TrieMap, TrieSet, VecMap}; -pub use self::hashmap::{HashMap, HashSet}; +pub use core_collections::{binary_heap, bitv, bitv_set, btree_map, btree_set, dlist, enum_set}; +pub use core_collections::{ring_buf, tree_map, tree_set, trie_map, trie_set, vec_map}; + +pub use self::hash_map::HashMap; +pub use self::hash_set::HashSet; pub use self::lru_cache::LruCache; -pub mod hashmap; +mod hash; + +pub mod hash_map { + //! A hashmap + pub use super::hash::map::*; +} + +pub mod hash_set { + //! A hashset + pub use super::hash::set::*; +} + pub mod lru_cache; diff --git a/src/libstd/fmt.rs b/src/libstd/fmt.rs index 27451c91f3f5e..cb151dd9c0abf 100644 --- a/src/libstd/fmt.rs +++ b/src/libstd/fmt.rs @@ -424,14 +424,20 @@ pub use core::fmt::{Argument, Arguments, write, radix, Radix, RadixFmt}; #[doc(hidden)] pub use core::fmt::{argument, argumentstr, argumentuint}; +// NOTE(stage0): remove these imports after a snapshot +#[cfg(stage0)] #[doc(hidden)] pub use core::fmt::{secret_show, secret_string, secret_unsigned}; +#[cfg(stage0)] #[doc(hidden)] pub use core::fmt::{secret_signed, secret_lower_hex, secret_upper_hex}; +#[cfg(stage0)] #[doc(hidden)] pub use core::fmt::{secret_bool, secret_char, secret_octal, secret_binary}; +#[cfg(stage0)] #[doc(hidden)] pub use core::fmt::{secret_float, secret_upper_exp, secret_lower_exp}; +#[cfg(stage0)] #[doc(hidden)] pub use core::fmt::{secret_pointer}; diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index e641abbfeee64..152b89b86e7a6 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -675,26 +675,23 @@ pub fn check_zero_tts(cx: &ExtCtxt, /// Extract the string literal from the first token of `tts`. If this /// is not a string literal, emit an error and return None. -pub fn get_single_str_from_tts(cx: &ExtCtxt, +pub fn get_single_str_from_tts(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree], name: &str) -> Option { - if tts.len() != 1 { - cx.span_err(sp, format!("{} takes 1 argument.", name).as_slice()); - } else { - match tts[0] { - ast::TtToken(_, token::LitStr(ident)) => return Some(parse::str_lit(ident.as_str())), - ast::TtToken(_, token::LitStrRaw(ident, _)) => { - return Some(parse::raw_str_lit(ident.as_str())) - } - _ => { - cx.span_err(sp, - format!("{} requires a string.", name).as_slice()) - } - } + let mut p = cx.new_parser_from_tts(tts); + if p.token == token::Eof { + cx.span_err(sp, format!("{} takes 1 argument", name).as_slice()); + return None } - None + let ret = cx.expander().fold_expr(p.parse_expr()); + if p.token != token::Eof { + cx.span_err(sp, format!("{} takes 1 argument", name).as_slice()); + } + expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| { + s.get().to_string() + }) } /// Extract comma-separated expressions from `tts`. If there is a diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index 53d091db095be..486ce910e2b6f 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -663,28 +663,28 @@ impl<'a, 'b> Context<'a, 'b> { fn format_arg(ecx: &ExtCtxt, sp: Span, ty: &ArgumentType, arg: P) -> P { - let (krate, fmt_fn) = match *ty { + let trait_ = match *ty { Known(ref tyname) => { match tyname.as_slice() { - "" => ("std", "secret_show"), - "b" => ("std", "secret_bool"), - "c" => ("std", "secret_char"), - "d" | "i" => ("std", "secret_signed"), - "e" => ("std", "secret_lower_exp"), - "E" => ("std", "secret_upper_exp"), - "f" => ("std", "secret_float"), - "o" => ("std", "secret_octal"), - "p" => ("std", "secret_pointer"), - "s" => ("std", "secret_string"), - "t" => ("std", "secret_binary"), - "u" => ("std", "secret_unsigned"), - "x" => ("std", "secret_lower_hex"), - "X" => ("std", "secret_upper_hex"), + "" => "Show", + "b" => "Bool", + "c" => "Char", + "d" | "i" => "Signed", + "e" => "LowerExp", + "E" => "UpperExp", + "f" => "Float", + "o" => "Octal", + "p" => "Pointer", + "s" => "String", + "t" => "Binary", + "u" => "Unsigned", + "x" => "LowerHex", + "X" => "UpperHex", _ => { ecx.span_err(sp, format!("unknown format trait `{}`", *tyname).as_slice()); - ("std", "dummy") + "Dummy" } } } @@ -697,9 +697,10 @@ impl<'a, 'b> Context<'a, 'b> { }; let format_fn = ecx.path_global(sp, vec![ - ecx.ident_of(krate), + ecx.ident_of("std"), ecx.ident_of("fmt"), - ecx.ident_of(fmt_fn)]); + ecx.ident_of(trait_), + ecx.ident_of("fmt")]); ecx.expr_call_global(sp, vec![ ecx.ident_of("std"), ecx.ident_of("fmt"), diff --git a/src/libsyntax/ext/mtwt.rs b/src/libsyntax/ext/mtwt.rs index 840468176ab03..bebe16286c97a 100644 --- a/src/libsyntax/ext/mtwt.rs +++ b/src/libsyntax/ext/mtwt.rs @@ -20,7 +20,7 @@ use ast::{Ident, Mrk, Name, SyntaxContext}; use std::cell::RefCell; use std::rc::Rc; use std::collections::HashMap; -use std::collections::hashmap::{Occupied, Vacant}; +use std::collections::hash_map::{Occupied, Vacant}; /// The SCTable contains a table of SyntaxContext_'s. It /// represents a flattened tree structure, to avoid having diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index 41967b0680cff..f192308440998 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -9,14 +9,16 @@ // except according to those terms. use ast; -use codemap; use codemap::{Pos, Span}; +use codemap; use ext::base::*; use ext::base; use ext::build::AstBuilder; -use parse; use parse::token; +use parse; use print::pprust; +use ptr::P; +use util::small_vector::SmallVector; use std::io::File; use std::rc::Rc; @@ -82,14 +84,14 @@ pub fn expand_mod(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) /// include! : parse the given file as an expr /// This is generally a bad idea because it's going to behave /// unhygienically. -pub fn expand_include(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) - -> Box { +pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) + -> Box { let file = match get_single_str_from_tts(cx, sp, tts, "include!") { Some(f) => f, None => return DummyResult::expr(sp), }; // The file will be added to the code map by the parser - let mut p = + let p = parse::new_sub_parser_from_file(cx.parse_sess(), cx.cfg(), &res_rel_file(cx, @@ -98,7 +100,28 @@ pub fn expand_include(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) true, None, sp); - base::MacExpr::new(p.parse_expr()) + + struct ExpandResult<'a> { + p: parse::parser::Parser<'a>, + } + impl<'a> base::MacResult for ExpandResult<'a> { + fn make_expr(mut self: Box>) -> Option> { + Some(self.p.parse_expr()) + } + fn make_items(mut self: Box>) + -> Option>> { + let mut ret = SmallVector::zero(); + loop { + match self.p.parse_item_with_outer_attributes() { + Some(item) => ret.push(item), + None => break + } + } + Some(ret) + } + } + + box ExpandResult { p: p } } // include_str! : read the given file, insert it as a literal string expr diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index c1877c827a41f..54eaa3086588e 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -57,7 +57,7 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[ ("default_type_params", Active), ("quote", Active), ("linkage", Active), - ("struct_inherit", Active), + ("struct_inherit", Removed), ("overloaded_calls", Active), ("unboxed_closure_sugar", Active), diff --git a/src/libterm/win.rs b/src/libterm/win.rs index 7ce6fb658b56d..9a67ee8836bae 100644 --- a/src/libterm/win.rs +++ b/src/libterm/win.rs @@ -71,8 +71,7 @@ fn color_to_bits(color: color::Color) -> u16 { } fn bits_to_color(bits: u16) -> color::Color { - let bits = bits & 0x7; - let color = match bits { + let color = match bits & 0x7 { 0 => color::BLACK, 0x1 => color::BLUE, 0x2 => color::GREEN, @@ -84,11 +83,7 @@ fn bits_to_color(bits: u16) -> color::Color { _ => unreachable!() }; - if bits >= 8 { - color | 0x8 - } else { - color - } + color | (bits & 0x8) // copy the hi-intensity bit } impl WinConsole { diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs index 2cc694176de59..8c184ccbe43a8 100644 --- a/src/libtest/stats.rs +++ b/src/libtest/stats.rs @@ -10,8 +10,8 @@ #![allow(missing_docs)] -use std::collections::hashmap; -use std::collections::hashmap::{Occupied, Vacant}; +use std::collections::hash_map; +use std::collections::hash_map::{Occupied, Vacant}; use std::fmt::Show; use std::hash::Hash; use std::io; @@ -440,8 +440,8 @@ pub fn write_boxplot( /// Returns a HashMap with the number of occurrences of every element in the /// sequence that the iterator exposes. -pub fn freq_count, U: Eq+Hash>(mut iter: T) -> hashmap::HashMap { - let mut map: hashmap::HashMap = hashmap::HashMap::new(); +pub fn freq_count, U: Eq+Hash>(mut iter: T) -> hash_map::HashMap { + let mut map: hash_map::HashMap = hash_map::HashMap::new(); for elem in iter { match map.entry(elem) { Occupied(mut entry) => { *entry.get_mut() += 1; }, diff --git a/src/test/auxiliary/issue-18501.rs b/src/test/auxiliary/issue-18501.rs new file mode 100644 index 0000000000000..af3bc20378c39 --- /dev/null +++ b/src/test/auxiliary/issue-18501.rs @@ -0,0 +1,27 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "rlib"] +struct Foo; + +trait Tr { + fn tr(&self); +} + +impl Tr for Foo { + fn tr(&self) {} +} + +fn take_method(f: fn(&T), t: &T) {} + +#[inline] +pub fn pass_method() { + take_method(Tr::tr, &Foo); +} diff --git a/src/test/auxiliary/issue-18514.rs b/src/test/auxiliary/issue-18514.rs new file mode 100644 index 0000000000000..2a5e07a32855e --- /dev/null +++ b/src/test/auxiliary/issue-18514.rs @@ -0,0 +1,27 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "rlib"] + +pub trait Tr { + fn tr(&self); +} + +pub struct St(pub Vec); + +impl Tr for St { + fn tr(&self) { + match self { + &St(ref v) => { + v.iter(); + } + } + } +} diff --git a/src/test/auxiliary/macro-include-items-expr.rs b/src/test/auxiliary/macro-include-items-expr.rs new file mode 100644 index 0000000000000..aea3c749930b6 --- /dev/null +++ b/src/test/auxiliary/macro-include-items-expr.rs @@ -0,0 +1,13 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-test: this is not a test + +1 diff --git a/src/test/auxiliary/macro-include-items-item.rs b/src/test/auxiliary/macro-include-items-item.rs new file mode 100644 index 0000000000000..da72aaef80591 --- /dev/null +++ b/src/test/auxiliary/macro-include-items-item.rs @@ -0,0 +1,13 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-test: this is not a test + +fn foo() { bar() } diff --git a/src/test/bench/core-set.rs b/src/test/bench/core-set.rs index 4833467922b76..8151f2718e35c 100644 --- a/src/test/bench/core-set.rs +++ b/src/test/bench/core-set.rs @@ -14,7 +14,7 @@ extern crate collections; extern crate rand; extern crate time; -use std::collections::bitv::BitvSet; +use std::collections::BitvSet; use std::collections::TreeSet; use std::hash::Hash; use std::collections::HashSet; diff --git a/src/test/bench/std-smallintmap.rs b/src/test/bench/std-smallintmap.rs index 2086980b016fc..cdcb88d87c644 100644 --- a/src/test/bench/std-smallintmap.rs +++ b/src/test/bench/std-smallintmap.rs @@ -13,17 +13,17 @@ extern crate collections; extern crate time; -use std::collections::SmallIntMap; +use std::collections::VecMap; use std::os; use std::uint; -fn append_sequential(min: uint, max: uint, map: &mut SmallIntMap) { +fn append_sequential(min: uint, max: uint, map: &mut VecMap) { for i in range(min, max) { map.insert(i, i + 22u); } } -fn check_sequential(min: uint, max: uint, map: &SmallIntMap) { +fn check_sequential(min: uint, max: uint, map: &VecMap) { for i in range(min, max) { assert_eq!(map[i], i + 22u); } @@ -45,7 +45,7 @@ fn main() { let mut appendf = 0.0; for _ in range(0u, rep) { - let mut map = SmallIntMap::new(); + let mut map = VecMap::new(); let start = time::precise_time_s(); append_sequential(0u, max, &mut map); let mid = time::precise_time_s(); diff --git a/src/test/compile-fail/dst-index.rs b/src/test/compile-fail/dst-index.rs new file mode 100644 index 0000000000000..542562b69e6a7 --- /dev/null +++ b/src/test/compile-fail/dst-index.rs @@ -0,0 +1,40 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that overloaded index expressions with DST result types +// can't be used as rvalues + +use std::ops::Index; +use std::fmt::Show; + +struct S; + +impl Index for S { + fn index<'a>(&'a self, _: &uint) -> &'a str { + "hello" + } +} + +struct T; + +impl Index for T { + fn index<'a>(&'a self, idx: &uint) -> &'a Show + 'static { + static x: uint = 42; + &x + } +} + +fn main() { + S[0]; + //~^ ERROR E0161 + T[0]; + //~^ ERROR cannot move out of dereference + //~^^ ERROR E0161 +} diff --git a/src/test/compile-fail/extoption_env-not-string-literal.rs b/src/test/compile-fail/extoption_env-not-string-literal.rs index 10f6c34980e48..6371a5c711d6b 100644 --- a/src/test/compile-fail/extoption_env-not-string-literal.rs +++ b/src/test/compile-fail/extoption_env-not-string-literal.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn main() { option_env!(10); } //~ ERROR: requires a string +fn main() { option_env!(10); } //~ ERROR: argument must be a string literal diff --git a/src/test/compile-fail/manual-link-bad-form.rs b/src/test/compile-fail/manual-link-bad-form.rs new file mode 100644 index 0000000000000..bd2a3eba0b5b8 --- /dev/null +++ b/src/test/compile-fail/manual-link-bad-form.rs @@ -0,0 +1,17 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-l :static +// error-pattern: empty library name given via `-l` + +fn main() { +} + + diff --git a/src/test/compile-fail/manual-link-bad-kind.rs b/src/test/compile-fail/manual-link-bad-kind.rs new file mode 100644 index 0000000000000..4614440ddafd5 --- /dev/null +++ b/src/test/compile-fail/manual-link-bad-kind.rs @@ -0,0 +1,16 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-l foo:bar +// error-pattern: unknown library kind `bar`, expected one of dylib, framework, or static + +fn main() { +} + diff --git a/src/test/compile-fail/manual-link-framework.rs b/src/test/compile-fail/manual-link-framework.rs new file mode 100644 index 0000000000000..96cc35049ee40 --- /dev/null +++ b/src/test/compile-fail/manual-link-framework.rs @@ -0,0 +1,17 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-macos +// ignore-ios +// compile-flags:-l foo:framework +// error-pattern: native frameworks are only available on OSX targets + +fn main() { +} diff --git a/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs b/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs index 2a9a0358cc6c0..91551941c0656 100644 --- a/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs +++ b/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs @@ -13,6 +13,6 @@ fn main() { fn bar(n: int) { let _x: [int, ..n]; - //~^ ERROR expected constant expr for vector length: non-constant path in constant expr + //~^ ERROR expected constant expr for array length: non-constant path in constant expr } } diff --git a/src/test/run-fail/hashmap-capacity-overflow.rs b/src/test/run-fail/hashmap-capacity-overflow.rs index f68b511d0aa0d..c86f8a38f63c4 100644 --- a/src/test/run-fail/hashmap-capacity-overflow.rs +++ b/src/test/run-fail/hashmap-capacity-overflow.rs @@ -10,7 +10,7 @@ // error-pattern:capacity overflow -use std::collections::hashmap::HashMap; +use std::collections::hash_map::HashMap; use std::uint; use std::mem::size_of; diff --git a/src/test/run-make/manual-link/Makefile b/src/test/run-make/manual-link/Makefile new file mode 100644 index 0000000000000..d2a02adc9d4a4 --- /dev/null +++ b/src/test/run-make/manual-link/Makefile @@ -0,0 +1,7 @@ +-include ../tools.mk + +all: $(TMPDIR)/libbar.a + $(RUSTC) foo.rs -lbar:static + $(RUSTC) main.rs + $(call RUN,main) + diff --git a/src/test/run-make/manual-link/bar.c b/src/test/run-make/manual-link/bar.c new file mode 100644 index 0000000000000..e42599986781f --- /dev/null +++ b/src/test/run-make/manual-link/bar.c @@ -0,0 +1 @@ +void bar() {} diff --git a/src/test/run-make/manual-link/foo.c b/src/test/run-make/manual-link/foo.c new file mode 100644 index 0000000000000..e42599986781f --- /dev/null +++ b/src/test/run-make/manual-link/foo.c @@ -0,0 +1 @@ +void bar() {} diff --git a/src/test/run-make/manual-link/foo.rs b/src/test/run-make/manual-link/foo.rs new file mode 100644 index 0000000000000..d67a4057afbfc --- /dev/null +++ b/src/test/run-make/manual-link/foo.rs @@ -0,0 +1,19 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "rlib"] + +extern { + fn bar(); +} + +pub fn foo() { + unsafe { bar(); } +} diff --git a/src/test/run-make/manual-link/main.rs b/src/test/run-make/manual-link/main.rs new file mode 100644 index 0000000000000..756a47f386ae3 --- /dev/null +++ b/src/test/run-make/manual-link/main.rs @@ -0,0 +1,15 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate foo; + +fn main() { + foo::foo(); +} diff --git a/src/test/run-pass/auto-encode.rs b/src/test/run-pass/auto-encode.rs index 10c3df9388a01..44006a0039abd 100644 --- a/src/test/run-pass/auto-encode.rs +++ b/src/test/run-pass/auto-encode.rs @@ -17,7 +17,7 @@ extern crate time; // These tests used to be separate files, but I wanted to refactor all // the common code. -use std::hashmap::{HashMap, HashSet}; +use std::collections::{HashMap, HashSet}; use rbml::reader as EBReader; use rbml::writer as EBWriter; diff --git a/src/test/run-pass/dst-index.rs b/src/test/run-pass/dst-index.rs new file mode 100644 index 0000000000000..266f9bcba5f92 --- /dev/null +++ b/src/test/run-pass/dst-index.rs @@ -0,0 +1,37 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that overloaded index expressions with DST result types +// work and don't ICE. + +use std::ops::Index; +use std::fmt::Show; + +struct S; + +impl Index for S { + fn index<'a>(&'a self, _: &uint) -> &'a str { + "hello" + } +} + +struct T; + +impl Index for T { + fn index<'a>(&'a self, idx: &uint) -> &'a Show + 'static { + static x: uint = 42; + &x + } +} + +fn main() { + assert_eq!(&S[0], "hello"); + assert_eq!(format!("{}", &T[0]).as_slice(), "42"); +} diff --git a/src/test/run-pass/issue-10853.rs b/src/test/run-pass/issue-10853.rs index a696e0dbbe2e2..1717075885d7a 100644 --- a/src/test/run-pass/issue-10853.rs +++ b/src/test/run-pass/issue-10853.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![deny(missing_doc)] +#![deny(missing_docs)] #![doc="module"] #[doc="struct"] diff --git a/src/test/run-pass/issue-18464.rs b/src/test/run-pass/issue-18464.rs new file mode 100644 index 0000000000000..70217868a54b8 --- /dev/null +++ b/src/test/run-pass/issue-18464.rs @@ -0,0 +1,23 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-pretty + +#![deny(dead_code)] + +const LOW_RANGE: char = '0'; +const HIGH_RANGE: char = '9'; + +fn main() { + match '5' { + LOW_RANGE...HIGH_RANGE => (), + _ => () + }; +} diff --git a/src/test/run-pass/issue-18501.rs b/src/test/run-pass/issue-18501.rs new file mode 100644 index 0000000000000..ce026942948ca --- /dev/null +++ b/src/test/run-pass/issue-18501.rs @@ -0,0 +1,20 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we don't ICE when inlining a function from another +// crate that uses a trait method as a value due to incorrectly +// translating the def ID of the trait during AST decoding. + +// aux-build:issue-18501.rs +extern crate "issue-18501" as issue; + +fn main() { + issue::pass_method(); +} diff --git a/src/test/run-pass/issue-18514.rs b/src/test/run-pass/issue-18514.rs new file mode 100644 index 0000000000000..c75abd62deba6 --- /dev/null +++ b/src/test/run-pass/issue-18514.rs @@ -0,0 +1,24 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we don't ICE when translating a generic impl method from +// an extern crate that contains a match expression on a local +// variable lvalue where one of the match case bodies contains an +// expression that autoderefs through an overloaded generic deref +// impl. + +// aux-build:issue-18514.rs +extern crate "issue-18514" as ice; +use ice::{Tr, St}; + +fn main() { + let st: St<()> = St(vec![]); + st.tr(); +} diff --git a/src/test/run-pass/issue-18539.rs b/src/test/run-pass/issue-18539.rs new file mode 100644 index 0000000000000..90e20e30d109a --- /dev/null +++ b/src/test/run-pass/issue-18539.rs @@ -0,0 +1,23 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that coercing bare fn's that return a zero sized type to +// a closure doesn't cause an LLVM ERROR + +struct Foo; + +fn uint_to_foo(_: uint) -> Foo { + Foo +} + +#[allow(unused_must_use)] +fn main() { + range(0u, 10).map(uint_to_foo); +} diff --git a/src/test/run-pass/macro-include-items.rs b/src/test/run-pass/macro-include-items.rs new file mode 100644 index 0000000000000..0e7e6e247f5ab --- /dev/null +++ b/src/test/run-pass/macro-include-items.rs @@ -0,0 +1,20 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-pretty + +fn bar() {} + +include!(concat!("", "", "../auxiliary/", "macro-include-items-item.rs")) + +fn main() { + foo(); + assert_eq!(include!(concat!("", "../auxiliary/", "macro-include-items-expr.rs")), 1u); +} diff --git a/src/test/run-pass/trait-object-safety.rs b/src/test/run-pass/trait-object-safety.rs new file mode 100644 index 0000000000000..929cb9e7f1759 --- /dev/null +++ b/src/test/run-pass/trait-object-safety.rs @@ -0,0 +1,27 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that object-safe methods are identified as such. Also +// acts as a regression test for #18490 + +trait Tr { + // Static methods are always safe regardless of other rules + fn new() -> Self; +} + +struct St; + +impl Tr for St { + fn new() -> St { St } +} + +fn main() { + &St as &Tr; +} diff --git a/src/test/run-pass/trait-where-clause-vs-impl.rs b/src/test/run-pass/trait-where-clause-vs-impl.rs new file mode 100644 index 0000000000000..772310d47335f --- /dev/null +++ b/src/test/run-pass/trait-where-clause-vs-impl.rs @@ -0,0 +1,50 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that when there is a conditional (but blanket) impl and a +// where clause, we don't get confused in trait resolution. +// +// Issue #18453. + +use std::rc::Rc; + +pub trait Foo { + fn foo(&mut self, msg: M); +} + +pub trait Bar { + fn dummy(&self) -> M; +} + +impl> Foo for F { + fn foo(&mut self, msg: M) { + } +} + +pub struct Both { + inner: Rc<(M, F)>, +} + +impl> Clone for Both { + fn clone(&self) -> Both { + Both { inner: self.inner.clone() } + } +} + +fn repro1>(_both: Both) { +} + +fn repro2>(msg: M, foo: F) { + let both = Both { inner: Rc::new((msg, foo)) }; + repro1(both.clone()); // <--- This clone causes problem +} + +pub fn main() { +} diff --git a/src/test/run-pass/while-let.rs b/src/test/run-pass/while-let.rs index 41f54d47ad42c..449b3099dfa4d 100644 --- a/src/test/run-pass/while-let.rs +++ b/src/test/run-pass/while-let.rs @@ -10,10 +10,10 @@ #![feature(while_let)] -use std::collections::PriorityQueue; +use std::collections::BinaryHeap; -fn make_pq() -> PriorityQueue { - PriorityQueue::from_vec(vec![1i,2,3]) +fn make_pq() -> BinaryHeap { + BinaryHeap::from_vec(vec![1i,2,3]) } pub fn main() {