mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-29 10:13:54 +00:00
auto merge of #18575 : alexcrichton/rust/rollup, r=alexcrichton
This commit is contained in:
commit
b11b706545
@ -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<T>(&self, _: || -> T) {} } let b = X;
|
||||
|
@ -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
|
||||
|
@ -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>(_: T){}
|
||||
# fn bar(map: HashMap<String, uint>, set: hashmap::HashSet<String>){}
|
||||
fn foo<T>(_: T){}
|
||||
fn bar(map1: HashMap<String, uint>, map2: hash_map::HashMap<String, uint>){}
|
||||
|
||||
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
|
||||
|
@ -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 {
|
||||
|
@ -34,7 +34,7 @@ preamble = '''// Copyright 2012-2014 The Rust Project Developers. See the COPYRI
|
||||
|
||||
// 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:
|
||||
|
@ -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<T> {
|
||||
pub struct BinaryHeap<T> {
|
||||
data: Vec<T>,
|
||||
}
|
||||
|
||||
impl<T: Ord> Default for PriorityQueue<T> {
|
||||
impl<T: Ord> Default for BinaryHeap<T> {
|
||||
#[inline]
|
||||
fn default() -> PriorityQueue<T> { PriorityQueue::new() }
|
||||
fn default() -> BinaryHeap<T> { BinaryHeap::new() }
|
||||
}
|
||||
|
||||
impl<T: Ord> PriorityQueue<T> {
|
||||
/// Creates an empty `PriorityQueue` as a max-heap.
|
||||
impl<T: Ord> BinaryHeap<T> {
|
||||
/// Creates an empty `BinaryHeap` as a max-heap.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::PriorityQueue;
|
||||
/// let pq: PriorityQueue<uint> = PriorityQueue::new();
|
||||
/// use std::collections::BinaryHeap;
|
||||
/// let pq: BinaryHeap<uint> = BinaryHeap::new();
|
||||
/// ```
|
||||
pub fn new() -> PriorityQueue<T> { PriorityQueue{data: vec!(),} }
|
||||
pub fn new() -> BinaryHeap<T> { 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<uint> = PriorityQueue::with_capacity(10u);
|
||||
/// use std::collections::BinaryHeap;
|
||||
/// let pq: BinaryHeap<uint> = BinaryHeap::with_capacity(10u);
|
||||
/// ```
|
||||
pub fn with_capacity(capacity: uint) -> PriorityQueue<T> {
|
||||
PriorityQueue { data: Vec::with_capacity(capacity) }
|
||||
pub fn with_capacity(capacity: uint) -> BinaryHeap<T> {
|
||||
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<T>) -> PriorityQueue<T> {
|
||||
let mut q = PriorityQueue{data: xs,};
|
||||
pub fn from_vec(xs: Vec<T>) -> BinaryHeap<T> {
|
||||
let mut q = BinaryHeap{data: xs,};
|
||||
let mut n = q.len() / 2;
|
||||
while n > 0 {
|
||||
n -= 1;
|
||||
@ -226,8 +226,8 @@ impl<T: Ord> PriorityQueue<T> {
|
||||
/// # 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<T: Ord> PriorityQueue<T> {
|
||||
/// # 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<T: Ord> PriorityQueue<T> {
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::PriorityQueue;
|
||||
/// use std::collections::BinaryHeap;
|
||||
///
|
||||
/// let pq: PriorityQueue<uint> = PriorityQueue::with_capacity(100u);
|
||||
/// let pq: BinaryHeap<uint> = 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<uint> = PriorityQueue::new();
|
||||
/// let mut pq: BinaryHeap<uint> = 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<uint> = PriorityQueue::new();
|
||||
/// let mut pq: BinaryHeap<uint> = BinaryHeap::new();
|
||||
/// pq.reserve(100u);
|
||||
/// assert!(pq.capacity() >= 100u);
|
||||
/// ```
|
||||
@ -306,9 +306,9 @@ impl<T: Ord> PriorityQueue<T> {
|
||||
/// # 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<T: Ord> PriorityQueue<T> {
|
||||
/// # 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<T: Ord> PriorityQueue<T> {
|
||||
/// # 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<T: Ord> PriorityQueue<T> {
|
||||
/// # 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<T: Ord> PriorityQueue<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// 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<T: Ord> PriorityQueue<T> {
|
||||
/// println!("{}", x);
|
||||
/// }
|
||||
/// ```
|
||||
pub fn into_vec(self) -> Vec<T> { let PriorityQueue{data: v} = self; v }
|
||||
pub fn into_vec(self) -> Vec<T> { 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<T: Ord> PriorityQueue<T> {
|
||||
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<uint>) { self.iter.size_hint() }
|
||||
}
|
||||
|
||||
impl<T: Ord> FromIterator<T> for PriorityQueue<T> {
|
||||
fn from_iter<Iter: Iterator<T>>(mut iter: Iter) -> PriorityQueue<T> {
|
||||
impl<T: Ord> FromIterator<T> for BinaryHeap<T> {
|
||||
fn from_iter<Iter: Iterator<T>>(mut iter: Iter) -> BinaryHeap<T> {
|
||||
let vec: Vec<T> = iter.collect();
|
||||
PriorityQueue::from_vec(vec)
|
||||
BinaryHeap::from_vec(vec)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Ord> Extendable<T> for PriorityQueue<T> {
|
||||
impl<T: Ord> Extendable<T> for BinaryHeap<T> {
|
||||
fn extend<Iter: Iterator<T>>(&mut self, mut iter: Iter) {
|
||||
let (lower, _) = iter.size_hint();
|
||||
|
||||
@ -541,14 +541,14 @@ impl<T: Ord> Extendable<T> for PriorityQueue<T> {
|
||||
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<int>) {
|
||||
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<int> = PriorityQueue::new();
|
||||
let mut heap: BinaryHeap<int> = BinaryHeap::new();
|
||||
assert!(heap.pop().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_top() {
|
||||
let empty: PriorityQueue<int> = PriorityQueue::new();
|
||||
let empty: BinaryHeap<int> = BinaryHeap::new();
|
||||
assert!(empty.top().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_replace() {
|
||||
let mut heap: PriorityQueue<int> = PriorityQueue::new();
|
||||
let mut heap: BinaryHeap<int> = 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<uint> = xs.as_slice().iter().rev().map(|&x| x).collect();
|
||||
let mut q: BinaryHeap<uint> = xs.as_slice().iter().rev().map(|&x| x).collect();
|
||||
|
||||
for &x in xs.iter() {
|
||||
assert_eq!(q.pop().unwrap(), x);
|
@ -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;
|
||||
|
@ -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.
|
||||
///
|
||||
|
@ -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;
|
||||
|
@ -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};
|
||||
|
@ -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)]
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
File diff suppressed because it is too large
Load Diff
36
src/libcollections/tree/mod.rs
Normal file
36
src/libcollections/tree/mod.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! 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;
|
950
src/libcollections/tree/set.rs
Normal file
950
src/libcollections/tree/set.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
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<Ordering> {
|
||||
/// 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<T> {
|
||||
map: TreeMap<T, ()>
|
||||
}
|
||||
|
||||
impl<T: PartialEq + Ord> PartialEq for TreeSet<T> {
|
||||
#[inline]
|
||||
fn eq(&self, other: &TreeSet<T>) -> bool { self.map == other.map }
|
||||
}
|
||||
|
||||
impl<T: Eq + Ord> Eq for TreeSet<T> {}
|
||||
|
||||
impl<T: Ord> PartialOrd for TreeSet<T> {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &TreeSet<T>) -> Option<Ordering> {
|
||||
self.map.partial_cmp(&other.map)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Ord> Ord for TreeSet<T> {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &TreeSet<T>) -> Ordering {
|
||||
iter::order::cmp(self.iter(), other.iter())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Ord + Show> Show for TreeSet<T> {
|
||||
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<T: Ord> Default for TreeSet<T> {
|
||||
#[inline]
|
||||
fn default() -> TreeSet<T> { TreeSet::new() }
|
||||
}
|
||||
|
||||
impl<T: Ord> TreeSet<T> {
|
||||
/// Creates an empty `TreeSet`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::TreeSet;
|
||||
/// let mut set: TreeSet<int> = TreeSet::new();
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn new() -> TreeSet<T> { 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<int> = [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<int> = [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<int> = [1i, 4, 3, 5, 2].iter().map(|&x| x).collect();
|
||||
///
|
||||
/// // Not possible with a regular `.iter()`
|
||||
/// let v: Vec<int> = set.into_iter().collect();
|
||||
/// assert_eq!(v, vec![1, 2, 3, 4, 5]);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn into_iter(self) -> MoveSetItems<T> {
|
||||
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<int> = [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<int> = [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<int> = [1, 2, 3].iter().map(|&x| x).collect();
|
||||
/// let b: TreeSet<int> = [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<int> = 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<int> = 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<T>) -> 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<int> = [1, 2, 3].iter().map(|&x| x).collect();
|
||||
/// let b: TreeSet<int> = [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<int> = a.symmetric_difference(&b).map(|&x| x).collect();
|
||||
/// let diff2: TreeSet<int> = 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<T>)
|
||||
-> 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<int> = [1, 2, 3].iter().map(|&x| x).collect();
|
||||
/// let b: TreeSet<int> = [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<int> = 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<T>)
|
||||
-> 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<int> = [1, 2, 3].iter().map(|&x| x).collect();
|
||||
/// let b: TreeSet<int> = [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<int> = 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<T>) -> 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<int> = [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<int> = [1i, 2, 3].iter().map(|&x| x).collect();
|
||||
/// let mut b: TreeSet<int> = 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<T>) -> 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<int> = [1i, 2, 3].iter().map(|&x| x).collect();
|
||||
/// let mut set: TreeSet<int> = 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<T>) -> 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<int> = [1i, 2].iter().map(|&x| x).collect();
|
||||
/// let mut set: TreeSet<int> = 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<T>) -> 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<T> = iter::Map<'static, (T, ()), T, MoveEntries<T, ()>>;
|
||||
|
||||
/// 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<T: Ord>(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<T: Ord> FromIterator<T> for TreeSet<T> {
|
||||
fn from_iter<Iter: Iterator<T>>(iter: Iter) -> TreeSet<T> {
|
||||
let mut set = TreeSet::new();
|
||||
set.extend(iter);
|
||||
set
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Ord> Extendable<T> for TreeSet<T> {
|
||||
#[inline]
|
||||
fn extend<Iter: Iterator<T>>(&mut self, mut iter: Iter) {
|
||||
for elem in iter {
|
||||
self.insert(elem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Writer, T: Ord + Hash<S>> Hash<S> for TreeSet<T> {
|
||||
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<int> = 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<int> = 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<int>, &TreeSet<int>, 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<int> = xs.iter().map(|&x| x).collect();
|
||||
|
||||
for x in xs.iter() {
|
||||
assert!(set.contains(x));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_show() {
|
||||
let mut set: TreeSet<int> = TreeSet::new();
|
||||
let empty: TreeSet<int> = 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());
|
||||
}
|
||||
}
|
@ -654,335 +654,6 @@ impl<T> IndexMut<uint, T> for TrieMap<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// 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<uint> for TrieSet {
|
||||
fn from_iter<Iter: Iterator<uint>>(iter: Iter) -> TrieSet {
|
||||
let mut set = TrieSet::new();
|
||||
set.extend(iter);
|
||||
set
|
||||
}
|
||||
}
|
||||
|
||||
impl Extendable<uint> for TrieSet {
|
||||
fn extend<Iter: Iterator<uint>>(&mut self, mut iter: Iter) {
|
||||
for elem in iter {
|
||||
self.insert(elem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct TrieNode<T> {
|
||||
count: uint,
|
||||
children: [Child<T>, ..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<uint> for SetItems<'a> {
|
||||
fn next(&mut self) -> Option<uint> {
|
||||
self.iter.next().map(|(key, _)| key)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
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);
|
||||
}
|
||||
}
|
20
src/libcollections/trie/mod.rs
Normal file
20
src/libcollections/trie/mod.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! 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;
|
457
src/libcollections/trie/set.rs
Normal file
457
src/libcollections/trie/set.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
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<uint> for TrieSet {
|
||||
fn from_iter<Iter: Iterator<uint>>(iter: Iter) -> TrieSet {
|
||||
let mut set = TrieSet::new();
|
||||
set.extend(iter);
|
||||
set
|
||||
}
|
||||
}
|
||||
|
||||
impl Extendable<uint> for TrieSet {
|
||||
fn extend<Iter: Iterator<uint>>(&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<uint> for SetItems<'a> {
|
||||
fn next(&mut self) -> Option<uint> {
|
||||
self.iter.next().map(|(key, _)| key)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
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);
|
||||
}
|
||||
}
|
@ -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<T> {
|
||||
pub struct VecMap<T> {
|
||||
v: Vec<Option<T>>,
|
||||
}
|
||||
|
||||
impl<V> Default for SmallIntMap<V> {
|
||||
impl<V> Default for VecMap<V> {
|
||||
#[inline]
|
||||
fn default() -> SmallIntMap<V> { SmallIntMap::new() }
|
||||
fn default() -> VecMap<V> { VecMap::new() }
|
||||
}
|
||||
|
||||
impl<V:Clone> Clone for SmallIntMap<V> {
|
||||
impl<V:Clone> Clone for VecMap<V> {
|
||||
#[inline]
|
||||
fn clone(&self) -> SmallIntMap<V> {
|
||||
SmallIntMap { v: self.v.clone() }
|
||||
fn clone(&self) -> VecMap<V> {
|
||||
VecMap { v: self.v.clone() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn clone_from(&mut self, source: &SmallIntMap<V>) {
|
||||
fn clone_from(&mut self, source: &VecMap<V>) {
|
||||
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<V:Clone> Clone for SmallIntMap<V> {
|
||||
}
|
||||
}
|
||||
|
||||
impl <S: hash::Writer, T: Hash<S>> Hash<S> for SmallIntMap<T> {
|
||||
impl <S: hash::Writer, T: Hash<S>> Hash<S> for VecMap<T> {
|
||||
fn hash(&self, state: &mut S) {
|
||||
self.v.hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> SmallIntMap<V> {
|
||||
/// Creates an empty `SmallIntMap`.
|
||||
impl<V> VecMap<V> {
|
||||
/// 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<V> { SmallIntMap{v: vec!()} }
|
||||
pub fn new() -> VecMap<V> { 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<V> {
|
||||
SmallIntMap { v: Vec::with_capacity(capacity) }
|
||||
pub fn with_capacity(capacity: uint) -> VecMap<V> {
|
||||
VecMap { v: Vec::with_capacity(capacity) }
|
||||
}
|
||||
|
||||
/// Returns an iterator visiting all keys in ascending order by the keys.
|
||||
@ -132,9 +132,9 @@ impl<V> SmallIntMap<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");
|
||||
@ -159,9 +159,9 @@ impl<V> SmallIntMap<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(2, "b");
|
||||
/// map.insert(3, "c");
|
||||
@ -183,15 +183,15 @@ impl<V> SmallIntMap<V> {
|
||||
}
|
||||
|
||||
/// 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<V> SmallIntMap<V> {
|
||||
/// # 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<V> SmallIntMap<V> {
|
||||
/// # 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<V> SmallIntMap<V> {
|
||||
/// # 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<V> SmallIntMap<V> {
|
||||
/// # 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<V> SmallIntMap<V> {
|
||||
/// # 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<V> SmallIntMap<V> {
|
||||
/// # 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<V> SmallIntMap<V> {
|
||||
/// # 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<V> SmallIntMap<V> {
|
||||
/// # 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<V> SmallIntMap<V> {
|
||||
/// # 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<V> SmallIntMap<V> {
|
||||
/// # 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<V> SmallIntMap<V> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<V:Clone> SmallIntMap<V> {
|
||||
impl<V:Clone> VecMap<V> {
|
||||
/// 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<V:Clone> SmallIntMap<V> {
|
||||
/// # 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<V:Clone> SmallIntMap<V> {
|
||||
/// # 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<V:Clone> SmallIntMap<V> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: PartialOrd> PartialOrd for SmallIntMap<V> {
|
||||
impl<V: PartialOrd> PartialOrd for VecMap<V> {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &SmallIntMap<V>) -> Option<Ordering> {
|
||||
fn partial_cmp(&self, other: &VecMap<V>) -> Option<Ordering> {
|
||||
iter::order::partial_cmp(self.iter(), other.iter())
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Ord> Ord for SmallIntMap<V> {
|
||||
impl<V: Ord> Ord for VecMap<V> {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &SmallIntMap<V>) -> Ordering {
|
||||
fn cmp(&self, other: &VecMap<V>) -> Ordering {
|
||||
iter::order::cmp(self.iter(), other.iter())
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: fmt::Show> fmt::Show for SmallIntMap<V> {
|
||||
impl<V: fmt::Show> fmt::Show for VecMap<V> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
try!(write!(f, "{{"));
|
||||
|
||||
@ -495,15 +495,15 @@ impl<V: fmt::Show> fmt::Show for SmallIntMap<V> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> FromIterator<(uint, V)> for SmallIntMap<V> {
|
||||
fn from_iter<Iter: Iterator<(uint, V)>>(iter: Iter) -> SmallIntMap<V> {
|
||||
let mut map = SmallIntMap::new();
|
||||
impl<V> FromIterator<(uint, V)> for VecMap<V> {
|
||||
fn from_iter<Iter: Iterator<(uint, V)>>(iter: Iter) -> VecMap<V> {
|
||||
let mut map = VecMap::new();
|
||||
map.extend(iter);
|
||||
map
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Extendable<(uint, V)> for SmallIntMap<V> {
|
||||
impl<V> Extendable<(uint, V)> for VecMap<V> {
|
||||
fn extend<Iter: Iterator<(uint, V)>>(&mut self, mut iter: Iter) {
|
||||
for (k, v) in iter {
|
||||
self.insert(k, v);
|
||||
@ -511,14 +511,14 @@ impl<V> Extendable<(uint, V)> for SmallIntMap<V> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Index<uint, V> for SmallIntMap<V> {
|
||||
impl<V> Index<uint, V> for VecMap<V> {
|
||||
#[inline]
|
||||
fn index<'a>(&'a self, i: &uint) -> &'a V {
|
||||
self.find(i).expect("key not present")
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> IndexMut<uint, V> for SmallIntMap<V> {
|
||||
impl<V> IndexMut<uint, V> for VecMap<V> {
|
||||
#[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::<int>::new();
|
||||
let mut map = VecMap::new();
|
||||
let empty = VecMap::<int>::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<char> = xs.iter().map(|&x| x).collect();
|
||||
let map: VecMap<char> = 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<int> = SmallIntMap::new();
|
||||
let mut map: VecMap<int> = 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<int> = SmallIntMap::new();
|
||||
let mut map: VecMap<int> = 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<uint> = SmallIntMap::new();
|
||||
let mut m : VecMap<uint> = 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<uint> = SmallIntMap::new();
|
||||
let mut m : VecMap<uint> = 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<uint> = SmallIntMap::new();
|
||||
let mut m : VecMap<uint> = 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<uint> = SmallIntMap::new();
|
||||
let mut m : VecMap<uint> = 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<uint> = SmallIntMap::new();
|
||||
let mut m : VecMap<uint> = 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<uint> = SmallIntMap::new();
|
||||
let mut m : VecMap<uint> = 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<uint> = SmallIntMap::new();
|
||||
let mut m : VecMap<uint> = 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<uint> = SmallIntMap::new();
|
||||
let mut m : VecMap<uint> = VecMap::new();
|
||||
find_seq_n(10_000, &mut m, b,
|
||||
|m, i| { m.insert(i, 1); },
|
||||
|m, i| { m.find(&i); });
|
@ -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<T: str::Str> 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<T> Pointer for *const T {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||
f.flags |= 1 << (rt::FlagAlternate as uint);
|
||||
secret_lower_hex::<uint>(&(*self as uint), f)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
|
||||
impl<T> 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<T> 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<T> 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<T> 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<T> 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<T> 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<T> 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 (
|
||||
|
@ -145,19 +145,19 @@ pub struct Opt {
|
||||
pub aliases: Vec<Opt>,
|
||||
}
|
||||
|
||||
/// 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<uint> {
|
||||
}
|
||||
|
||||
/// 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);
|
||||
|
@ -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<Vec<Path>>,
|
||||
pub libs: Vec<(String, cstore::NativeLibaryKind)>,
|
||||
pub maybe_sysroot: Option<Path>,
|
||||
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<getopts::OptGroup> {
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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<Span>, 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<ast::CrateNum> {
|
||||
let mut ret = None;
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)) }
|
||||
|
@ -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.
|
||||
|
@ -51,7 +51,7 @@ struct MarkSymbolVisitor<'a, 'tcx: 'a> {
|
||||
tcx: &'a ty::ctxt<'tcx>,
|
||||
live_symbols: Box<HashSet<ast::NodeId>>,
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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};
|
||||
|
@ -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<T> 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()));
|
||||
|
@ -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);
|
||||
|
@ -502,7 +502,11 @@ impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> {
|
||||
}
|
||||
|
||||
fn node_method_ty(&self, method_call: typeck::MethodCall) -> Option<ty::t> {
|
||||
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<NodeMap<ty::AutoAdjustment>> {
|
||||
|
@ -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,
|
||||
|
@ -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};
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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};
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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 => {}
|
||||
}
|
||||
|
@ -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<ty::InferTy, ty::t>,
|
||||
skolemization_map: hash_map::HashMap<ty::InferTy, ty::t>,
|
||||
}
|
||||
|
||||
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));
|
||||
|
@ -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};
|
||||
|
Binary file not shown.
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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<int, int> = 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();
|
||||
|
@ -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;
|
@ -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!)
|
@ -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;
|
||||
|
@ -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};
|
||||
|
||||
|
@ -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<String> {
|
||||
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
|
||||
|
@ -663,28 +663,28 @@ impl<'a, 'b> Context<'a, 'b> {
|
||||
fn format_arg(ecx: &ExtCtxt, sp: Span,
|
||||
ty: &ArgumentType, arg: P<ast::Expr>)
|
||||
-> P<ast::Expr> {
|
||||
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"),
|
||||
|
@ -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
|
||||
|
@ -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<base::MacResult+'static> {
|
||||
pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
-> Box<base::MacResult+'cx> {
|
||||
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<ExpandResult<'a>>) -> Option<P<ast::Expr>> {
|
||||
Some(self.p.parse_expr())
|
||||
}
|
||||
fn make_items(mut self: Box<ExpandResult<'a>>)
|
||||
-> Option<SmallVector<P<ast::Item>>> {
|
||||
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
|
||||
|
@ -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),
|
||||
|
||||
|
@ -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<T: Writer+Send> WinConsole<T> {
|
||||
|
@ -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<T: Float + Show + FromPrimitive>(
|
||||
|
||||
/// Returns a HashMap with the number of occurrences of every element in the
|
||||
/// sequence that the iterator exposes.
|
||||
pub fn freq_count<T: Iterator<U>, U: Eq+Hash>(mut iter: T) -> hashmap::HashMap<U, uint> {
|
||||
let mut map: hashmap::HashMap<U,uint> = hashmap::HashMap::new();
|
||||
pub fn freq_count<T: Iterator<U>, U: Eq+Hash>(mut iter: T) -> hash_map::HashMap<U, uint> {
|
||||
let mut map: hash_map::HashMap<U,uint> = hash_map::HashMap::new();
|
||||
for elem in iter {
|
||||
match map.entry(elem) {
|
||||
Occupied(mut entry) => { *entry.get_mut() += 1; },
|
||||
|
27
src/test/auxiliary/issue-18501.rs
Normal file
27
src/test/auxiliary/issue-18501.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![crate_type = "rlib"]
|
||||
struct Foo;
|
||||
|
||||
trait Tr {
|
||||
fn tr(&self);
|
||||
}
|
||||
|
||||
impl Tr for Foo {
|
||||
fn tr(&self) {}
|
||||
}
|
||||
|
||||
fn take_method<T>(f: fn(&T), t: &T) {}
|
||||
|
||||
#[inline]
|
||||
pub fn pass_method() {
|
||||
take_method(Tr::tr, &Foo);
|
||||
}
|
27
src/test/auxiliary/issue-18514.rs
Normal file
27
src/test/auxiliary/issue-18514.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![crate_type = "rlib"]
|
||||
|
||||
pub trait Tr {
|
||||
fn tr(&self);
|
||||
}
|
||||
|
||||
pub struct St<V>(pub Vec<V>);
|
||||
|
||||
impl<V> Tr for St<V> {
|
||||
fn tr(&self) {
|
||||
match self {
|
||||
&St(ref v) => {
|
||||
v.iter();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
13
src/test/auxiliary/macro-include-items-expr.rs
Normal file
13
src/test/auxiliary/macro-include-items-expr.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// ignore-test: this is not a test
|
||||
|
||||
1
|
13
src/test/auxiliary/macro-include-items-item.rs
Normal file
13
src/test/auxiliary/macro-include-items-item.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// ignore-test: this is not a test
|
||||
|
||||
fn foo() { bar() }
|
@ -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;
|
||||
|
@ -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<uint>) {
|
||||
fn append_sequential(min: uint, max: uint, map: &mut VecMap<uint>) {
|
||||
for i in range(min, max) {
|
||||
map.insert(i, i + 22u);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_sequential(min: uint, max: uint, map: &SmallIntMap<uint>) {
|
||||
fn check_sequential(min: uint, max: uint, map: &VecMap<uint>) {
|
||||
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();
|
||||
|
40
src/test/compile-fail/dst-index.rs
Normal file
40
src/test/compile-fail/dst-index.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// 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<uint, str> for S {
|
||||
fn index<'a>(&'a self, _: &uint) -> &'a str {
|
||||
"hello"
|
||||
}
|
||||
}
|
||||
|
||||
struct T;
|
||||
|
||||
impl Index<uint, Show + 'static> 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
|
||||
}
|
@ -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
|
||||
|
17
src/test/compile-fail/manual-link-bad-form.rs
Normal file
17
src/test/compile-fail/manual-link-bad-form.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags:-l :static
|
||||
// error-pattern: empty library name given via `-l`
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
||||
|
16
src/test/compile-fail/manual-link-bad-kind.rs
Normal file
16
src/test/compile-fail/manual-link-bad-kind.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags:-l foo:bar
|
||||
// error-pattern: unknown library kind `bar`, expected one of dylib, framework, or static
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
17
src/test/compile-fail/manual-link-framework.rs
Normal file
17
src/test/compile-fail/manual-link-framework.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// ignore-macos
|
||||
// ignore-ios
|
||||
// compile-flags:-l foo:framework
|
||||
// error-pattern: native frameworks are only available on OSX targets
|
||||
|
||||
fn main() {
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
7
src/test/run-make/manual-link/Makefile
Normal file
7
src/test/run-make/manual-link/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
-include ../tools.mk
|
||||
|
||||
all: $(TMPDIR)/libbar.a
|
||||
$(RUSTC) foo.rs -lbar:static
|
||||
$(RUSTC) main.rs
|
||||
$(call RUN,main)
|
||||
|
1
src/test/run-make/manual-link/bar.c
Normal file
1
src/test/run-make/manual-link/bar.c
Normal file
@ -0,0 +1 @@
|
||||
void bar() {}
|
1
src/test/run-make/manual-link/foo.c
Normal file
1
src/test/run-make/manual-link/foo.c
Normal file
@ -0,0 +1 @@
|
||||
void bar() {}
|
19
src/test/run-make/manual-link/foo.rs
Normal file
19
src/test/run-make/manual-link/foo.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![crate_type = "rlib"]
|
||||
|
||||
extern {
|
||||
fn bar();
|
||||
}
|
||||
|
||||
pub fn foo() {
|
||||
unsafe { bar(); }
|
||||
}
|
15
src/test/run-make/manual-link/main.rs
Normal file
15
src/test/run-make/manual-link/main.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
extern crate foo;
|
||||
|
||||
fn main() {
|
||||
foo::foo();
|
||||
}
|
@ -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;
|
||||
|
37
src/test/run-pass/dst-index.rs
Normal file
37
src/test/run-pass/dst-index.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// 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<uint, str> for S {
|
||||
fn index<'a>(&'a self, _: &uint) -> &'a str {
|
||||
"hello"
|
||||
}
|
||||
}
|
||||
|
||||
struct T;
|
||||
|
||||
impl Index<uint, Show + 'static> 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");
|
||||
}
|
@ -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"]
|
||||
|
23
src/test/run-pass/issue-18464.rs
Normal file
23
src/test/run-pass/issue-18464.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// ignore-pretty
|
||||
|
||||
#![deny(dead_code)]
|
||||
|
||||
const LOW_RANGE: char = '0';
|
||||
const HIGH_RANGE: char = '9';
|
||||
|
||||
fn main() {
|
||||
match '5' {
|
||||
LOW_RANGE...HIGH_RANGE => (),
|
||||
_ => ()
|
||||
};
|
||||
}
|
20
src/test/run-pass/issue-18501.rs
Normal file
20
src/test/run-pass/issue-18501.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// 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();
|
||||
}
|
24
src/test/run-pass/issue-18514.rs
Normal file
24
src/test/run-pass/issue-18514.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// 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();
|
||||
}
|
23
src/test/run-pass/issue-18539.rs
Normal file
23
src/test/run-pass/issue-18539.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// 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);
|
||||
}
|
20
src/test/run-pass/macro-include-items.rs
Normal file
20
src/test/run-pass/macro-include-items.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// 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);
|
||||
}
|
27
src/test/run-pass/trait-object-safety.rs
Normal file
27
src/test/run-pass/trait-object-safety.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// 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;
|
||||
}
|
50
src/test/run-pass/trait-where-clause-vs-impl.rs
Normal file
50
src/test/run-pass/trait-where-clause-vs-impl.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// 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<M> {
|
||||
fn foo(&mut self, msg: M);
|
||||
}
|
||||
|
||||
pub trait Bar<M> {
|
||||
fn dummy(&self) -> M;
|
||||
}
|
||||
|
||||
impl<M, F: Bar<M>> Foo<M> for F {
|
||||
fn foo(&mut self, msg: M) {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Both<M, F> {
|
||||
inner: Rc<(M, F)>,
|
||||
}
|
||||
|
||||
impl<M, F: Foo<M>> Clone for Both<M, F> {
|
||||
fn clone(&self) -> Both<M, F> {
|
||||
Both { inner: self.inner.clone() }
|
||||
}
|
||||
}
|
||||
|
||||
fn repro1<M, F: Foo<M>>(_both: Both<M, F>) {
|
||||
}
|
||||
|
||||
fn repro2<M, F: Foo<M>>(msg: M, foo: F) {
|
||||
let both = Both { inner: Rc::new((msg, foo)) };
|
||||
repro1(both.clone()); // <--- This clone causes problem
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
}
|
@ -10,10 +10,10 @@
|
||||
|
||||
#![feature(while_let)]
|
||||
|
||||
use std::collections::PriorityQueue;
|
||||
use std::collections::BinaryHeap;
|
||||
|
||||
fn make_pq() -> PriorityQueue<int> {
|
||||
PriorityQueue::from_vec(vec![1i,2,3])
|
||||
fn make_pq() -> BinaryHeap<int> {
|
||||
BinaryHeap::from_vec(vec![1i,2,3])
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
|
Loading…
Reference in New Issue
Block a user