Change:
<ins> // 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-lexer-test FIXME #15883 use clone::Clone; use cmp::{Eq, Equiv, PartialEq}; use collections::{Collection, Mutable, Set, MutableSet, Map, MutableMap}; use default::Default; use fmt::Show; use fmt; use hash::{Hash, Hasher, RandomSipHasher}; use iter::{Iterator, FromIterator, FilterMap, Chain, Repeat, Zip, Extendable}; use iter; use option::{Some, None}; use result::{Ok, Err}; use super::{HashMap, Entries, MoveEntries, INITIAL_CAPACITY}; // Future Optimization (FIXME!) // ============================= // // Iteration over zero sized values is a noop. There is no need // for `bucket.val` in the case of HashSet. I suppose we would need HKT // to get rid of it properly. /// An implementation of a hash set using the underlying representation of a /// HashMap where the value is (). As with the `HashMap` type, a `HashSet` /// requires that the elements implement the `Eq` and `Hash` traits. /// /// # Example /// /// ``` /// use std::collections::HashSet; /// // Type inference lets us omit an explicit type signature (which /// // would be `HashSet<&str>` in this example). /// let mut books = HashSet::new(); /// /// // Add some books. /// books.insert("A Dance With Dragons"); /// books.insert("To Kill a Mockingbird"); /// books.insert("The Odyssey"); /// books.insert("The Great Gatsby"); /// /// // Check for a specific one. /// if !books.contains(&("The Winds of Winter")) { ///     println!("We have {} books, but The Winds of Winter ain't one.", ///              books.len()); /// } /// /// // Remove a book. /// books.remove(&"The Odyssey"); /// /// // Iterate over everything. /// for book in books.iter() { ///     println!("{}", *book); /// } /// ``` /// /// The easiest way to use `HashSet` with a custom type is to derive /// `Eq` and `Hash`. We must also derive `PartialEq`, this will in the /// future be implied by `Eq`. /// /// ``` /// use std::collections::HashSet; /// #[deriving(Hash, Eq, PartialEq, Show)] /// struct Viking<'a> { ///     name: &'a str, ///     power: uint, /// } /// /// let mut vikings = HashSet::new(); /// /// vikings.insert(Viking { name: "Einar", power: 9u }); /// vikings.insert(Viking { name: "Einar", power: 9u }); /// vikings.insert(Viking { name: "Olaf", power: 4u }); /// vikings.insert(Viking { name: "Harald", power: 8u }); /// /// // Use derived implementation to print the vikings. /// for x in vikings.iter() { ///     println!("{}", x); /// } /// ``` #[deriving(Clone)] pub struct HashSet<T, H = RandomSipHasher> { map: HashMap<T, (), H> } impl<T: Hash + Eq> HashSet<T, RandomSipHasher> { /// Create an empty HashSet. /// /// # Example /// /// ``` /// use std::collections::HashSet; /// let mut set: HashSet<int> = HashSet::new(); /// ``` #[inline] pub fn new() -> HashSet<T, RandomSipHasher> { HashSet::with_capacity(INITIAL_CAPACITY) } /// Create an empty HashSet with space for at least `n` elements in /// the hash table. /// /// # Example /// /// ``` /// use std::collections::HashSet; /// let mut set: HashSet<int> = HashSet::with_capacity(10); /// ``` #[inline] pub fn with_capacity(capacity: uint) -> HashSet<T, RandomSipHasher> { HashSet { map: HashMap::with_capacity(capacity) } } } impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> { /// Creates a new empty hash set which will use the given hasher to hash /// keys. /// /// The hash set is also created with the default initial capacity. /// /// # Example /// /// ``` /// use std::collections::HashSet; /// use std::hash::sip::SipHasher; /// /// let h = SipHasher::new(); /// let mut set = HashSet::with_hasher(h); /// set.insert(2u); /// ``` #[inline] pub fn with_hasher(hasher: H) -> HashSet<T, H> { HashSet::with_capacity_and_hasher(INITIAL_CAPACITY, hasher) } /// Create an empty HashSet with space for at least `capacity` /// elements in the hash table, using `hasher` to hash the keys. /// /// Warning: `hasher` is normally randomly generated, and /// is designed to allow `HashSet`s to be resistant to attacks that /// cause many collisions and very poor performance. Setting it /// manually using this function can expose a DoS attack vector. /// /// # Example /// /// ``` /// use std::collections::HashSet; /// use std::hash::sip::SipHasher; /// /// let h = SipHasher::new(); /// let mut set = HashSet::with_capacity_and_hasher(10u, h); /// set.insert(1i); /// ``` #[inline] pub fn with_capacity_and_hasher(capacity: uint, hasher: H) -> HashSet<T, H> { HashSet { map: HashMap::with_capacity_and_hasher(capacity, hasher) } } /// Reserve space for at least `n` elements in the hash table. /// /// # Example /// /// ``` /// use std::collections::HashSet; /// let mut set: HashSet<int> = HashSet::new(); /// set.reserve(10); /// ``` pub fn reserve(&mut self, n: uint) { self.map.reserve(n) } /// Returns true if the hash set contains a value equivalent to the /// given query value. /// /// # Example /// /// This is a slightly silly example where we define the number's /// parity as the equivilance class. It is important that the /// values hash the same, which is why we implement `Hash`. /// /// ``` /// use std::collections::HashSet; /// use std::hash::Hash; /// use std::hash::sip::SipState; /// /// #[deriving(Eq, PartialEq)] /// struct EvenOrOdd { ///     num: uint /// }; /// /// impl Hash for EvenOrOdd { ///     fn hash(&self, state: &mut SipState) { ///         let parity = self.num % 2; ///         parity.hash(state); ///     } /// } /// /// impl Equiv<EvenOrOdd> for EvenOrOdd { ///     fn equiv(&self, other: &EvenOrOdd) -> bool { ///         self.num % 2 == other.num % 2 ///     } /// } /// /// let mut set = HashSet::new(); /// set.insert(EvenOrOdd { num: 3u }); /// /// assert!(set.contains_equiv(&EvenOrOdd { num: 3u })); /// assert!(set.contains_equiv(&EvenOrOdd { num: 5u })); /// assert!(!set.contains_equiv(&EvenOrOdd { num: 4u })); /// assert!(!set.contains_equiv(&EvenOrOdd { num: 2u })); /// /// ``` pub fn contains_equiv<Q: Hash<S> + Equiv<T>>(&self, value: &Q) -> bool { self.map.contains_key_equiv(value) } /// An iterator visiting all elements in arbitrary order. /// Iterator element type is &'a T. /// /// # Example /// /// ``` /// use std::collections::HashSet; /// let mut set = HashSet::new(); /// set.insert("a"); /// set.insert("b"); /// /// // Will print in an arbitrary order. /// for x in set.iter() { ///     println!("{}", x); /// } /// ``` pub fn iter<'a>(&'a self) -> SetItems<'a, T> { self.map.keys() } /// Creates a consuming iterator, that is, one that moves each value out /// of the set in arbitrary order. The set cannot be used after calling /// this. /// /// # Example /// /// ``` /// use std::collections::HashSet; /// let mut set = HashSet::new(); /// set.insert("a".to_string()); /// set.insert("b".to_string()); /// /// // Not possible to collect to a Vec<String> with a regular `.iter()`. /// let v: Vec<String> = set.move_iter().collect(); /// /// // Will print in an arbitrary order. /// for x in v.iter() { ///     println!("{}", x); /// } /// ``` pub fn move_iter(self) -> SetMoveItems<T> { self.map.move_iter().map(|(k, _)| k) } /// Visit the values representing the difference. /// /// # Example /// /// ``` /// use std::collections::HashSet; /// let a: HashSet<int> = [1i, 2, 3].iter().map(|&x| x).collect(); /// let b: HashSet<int> = [4i, 2, 3, 4].iter().map(|&x| x).collect(); /// /// // Can be seen as `a - b`. /// for x in a.difference(&b) { ///     println!("{}", x); // Print 1 /// } /// /// let diff: HashSet<int> = a.difference(&b).map(|&x| x).collect(); /// assert_eq!(diff, [1i].iter().map(|&x| x).collect()); /// /// // Note that difference is not symmetric, /// // and `b - a` means something else: /// let diff: HashSet<int> = b.difference(&a).map(|&x| x).collect(); /// assert_eq!(diff, [4i].iter().map(|&x| x).collect()); /// ``` pub fn difference<'a>(&'a self, other: &'a HashSet<T, H>) -> SetAlgebraItems<'a, T, H> { Repeat::new(other).zip(self.iter()) .filter_map(|(other, elt)| { if !other.contains(elt) { Some(elt) } else { None } }) } /// Visit the values representing the symmetric difference. /// /// # Example /// /// ``` /// use std::collections::HashSet; /// let a: HashSet<int> = [1i, 2, 3].iter().map(|&x| x).collect(); /// let b: HashSet<int> = [4i, 2, 3, 4].iter().map(|&x| x).collect(); /// /// // Print 1, 4 in arbitrary order. /// for x in a.symmetric_difference(&b) { ///     println!("{}", x); /// } /// /// let diff1: HashSet<int> = a.symmetric_difference(&b).map(|&x| x).collect(); /// let diff2: HashSet<int> = b.symmetric_difference(&a).map(|&x| x).collect(); /// /// assert_eq!(diff1, diff2); /// assert_eq!(diff1, [1i, 4].iter().map(|&x| x).collect()); /// ``` pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T, H>) -> Chain<SetAlgebraItems<'a, T, H>, SetAlgebraItems<'a, T, H>> { self.difference(other).chain(other.difference(self)) } /// Visit the values representing the intersection. /// /// # Example /// /// ``` /// use std::collections::HashSet; /// let a: HashSet<int> = [1i, 2, 3].iter().map(|&x| x).collect(); /// let b: HashSet<int> = [4i, 2, 3, 4].iter().map(|&x| x).collect(); /// /// // Print 2, 3 in arbitrary order. /// for x in a.intersection(&b) { ///     println!("{}", x); /// } /// /// let diff: HashSet<int> = a.intersection(&b).map(|&x| x).collect(); /// assert_eq!(diff, [2i, 3].iter().map(|&x| x).collect()); /// ``` pub fn intersection<'a>(&'a self, other: &'a HashSet<T, H>) -> SetAlgebraItems<'a, T, H> { Repeat::new(other).zip(self.iter()) .filter_map(|(other, elt)| { if other.contains(elt) { Some(elt) } else { None } }) } /// Visit the values representing the union. /// /// # Example /// /// ``` /// use std::collections::HashSet; /// let a: HashSet<int> = [1i, 2, 3].iter().map(|&x| x).collect(); /// let b: HashSet<int> = [4i, 2, 3, 4].iter().map(|&x| x).collect(); /// /// // Print 1, 2, 3, 4 in arbitrary order. /// for x in a.union(&b) { ///     println!("{}", x); /// } /// /// let diff: HashSet<int> = a.union(&b).map(|&x| x).collect(); /// assert_eq!(diff, [1i, 2, 3, 4].iter().map(|&x| x).collect()); /// ``` pub fn union<'a>(&'a self, other: &'a HashSet<T, H>) -> Chain<SetItems<'a, T>, SetAlgebraItems<'a, T, H>> { self.iter().chain(other.difference(self)) } } impl<T: Eq + Hash<S>, S, H: Hasher<S>> PartialEq for HashSet<T, H> { fn eq(&self, other: &HashSet<T, H>) -> bool { if self.len() != other.len() { return false; } self.iter().all(|key| other.contains(key)) } } impl<T: Eq + Hash<S>, S, H: Hasher<S>> Eq for HashSet<T, H> {} impl<T: Eq + Hash<S>, S, H: Hasher<S>> Collection for HashSet<T, H> { fn len(&self) -> uint { self.map.len() } } impl<T: Eq + Hash<S>, S, H: Hasher<S>> Mutable for HashSet<T, H> { fn clear(&mut self) { self.map.clear() } } impl<T: Eq + Hash<S>, S, H: Hasher<S>> Set<T> for HashSet<T, H> { fn contains(&self, value: &T) -> bool { self.map.contains_key(value) } fn is_disjoint(&self, other: &HashSet<T, H>) -> bool { self.iter().all(|v| !other.contains(v)) } fn is_subset(&self, other: &HashSet<T, H>) -> bool { self.iter().all(|v| other.contains(v)) } } impl<T: Eq + Hash<S>, S, H: Hasher<S>> MutableSet<T> for HashSet<T, H> { fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()) } fn remove(&mut self, value: &T) -> bool { self.map.remove(value) } } impl<T: Eq + Hash<S> + fmt::Show, S, H: Hasher<S>> fmt::Show for HashSet<T, H> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(write!(f, "{{")); for (i, x) in self.iter().enumerate() { if i != 0 { try!(write!(f, ", ")); } try!(write!(f, "{}", *x)); } write!(f, "}}") } } impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> FromIterator<T> for HashSet<T, H> { fn from_iter<I: Iterator<T>>(iter: I) -> HashSet<T, H> { let (lower, _) = iter.size_hint(); let mut set = HashSet::with_capacity_and_hasher(lower, Default::default()); set.extend(iter); set } } impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Extendable<T> for HashSet<T, H> { fn extend<I: Iterator<T>>(&mut self, mut iter: I) { for k in iter { self.insert(k); } } } impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Default for HashSet<T, H> { fn default() -> HashSet<T, H> { HashSet::with_hasher(Default::default()) } } /// HashSet iterator pub type SetItems<'a, K> = iter::Map<'static, (&'a K, &'a ()), &'a K, Entries<'a, K, ()>>; /// HashSet move iterator pub type SetMoveItems<K> = iter::Map<'static, (K, ()), K, MoveEntries<K, ()>>; // `Repeat` is used to feed the filter closure an explicit capture // of a reference to the other set /// Set operations iterator pub type SetAlgebraItems<'a, T, H> = FilterMap<'static, (&'a HashSet<T, H>, &'a T), &'a T, Zip<Repeat<&'a HashSet<T, H>>, SetItems<'a, T>>>; #[cfg(test)] mod test_set { use prelude::*; use super::HashSet; use slice::ImmutablePartialEqSlice; use collections::Collection; #[test] fn test_disjoint() { let mut xs = HashSet::new(); let mut ys = HashSet::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 = HashSet::new(); assert!(a.insert(0i)); assert!(a.insert(5)); assert!(a.insert(11)); assert!(a.insert(7)); let mut b = HashSet::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_iterate() { let mut a = HashSet::new(); for i in range(0u, 32) { assert!(a.insert(i)); } let mut observed: u32 = 0; for k in a.iter() { observed |= 1 << *k; } assert_eq!(observed, 0xFFFF_FFFF); } #[test] fn test_intersection() { let mut a = HashSet::new(); let mut b = HashSet::new(); assert!(a.insert(11i)); assert!(a.insert(1)); assert!(a.insert(3)); assert!(a.insert(77)); assert!(a.insert(103)); assert!(a.insert(5)); assert!(a.insert(-5)); assert!(b.insert(2i)); assert!(b.insert(11)); assert!(b.insert(77)); assert!(b.insert(-9)); assert!(b.insert(-42)); assert!(b.insert(5)); assert!(b.insert(3)); let mut i = 0; let expected = [3, 5, 11, 77]; for x in a.intersection(&b) { assert!(expected.contains(x)); i += 1 } assert_eq!(i, expected.len()); } #[test] fn test_difference() { let mut a = HashSet::new(); let mut b = HashSet::new(); assert!(a.insert(1i)); assert!(a.insert(3)); assert!(a.insert(5)); assert!(a.insert(9)); assert!(a.insert(11)); assert!(b.insert(3i)); assert!(b.insert(9)); let mut i = 0; let expected = [1, 5, 11]; for x in a.difference(&b) { assert!(expected.contains(x)); i += 1 } assert_eq!(i, expected.len()); } #[test] fn test_symmetric_difference() { let mut a = HashSet::new(); let mut b = HashSet::new(); assert!(a.insert(1i)); assert!(a.insert(3)); assert!(a.insert(5)); assert!(a.insert(9)); assert!(a.insert(11)); assert!(b.insert(-2i)); assert!(b.insert(3)); assert!(b.insert(9)); assert!(b.insert(14)); assert!(b.insert(22)); let mut i = 0; let expected = [-2, 1, 5, 11, 14, 22]; for x in a.symmetric_difference(&b) { assert!(expected.contains(x)); i += 1 } assert_eq!(i, expected.len()); } #[test] fn test_union() { let mut a = HashSet::new(); let mut b = HashSet::new(); assert!(a.insert(1i)); assert!(a.insert(3)); assert!(a.insert(5)); assert!(a.insert(9)); assert!(a.insert(11)); assert!(a.insert(16)); assert!(a.insert(19)); assert!(a.insert(24)); assert!(b.insert(-2i)); assert!(b.insert(1)); assert!(b.insert(5)); assert!(b.insert(9)); assert!(b.insert(13)); assert!(b.insert(19)); let mut i = 0; let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]; for x in a.union(&b) { assert!(expected.contains(x)); i += 1 } assert_eq!(i, expected.len()); } #[test] fn test_from_iter() { let xs = [1i, 2, 3, 4, 5, 6, 7, 8, 9]; let set: HashSet<int> = xs.iter().map(|&x| x).collect(); for x in xs.iter() { assert!(set.contains(x)); } } #[test] fn test_move_iter() { let hs = { let mut hs = HashSet::new(); hs.insert('a'); hs.insert('b'); hs }; let v = hs.move_iter().collect::<Vec<char>>(); assert!(['a', 'b'] == v.as_slice() || ['b', 'a'] == v.as_slice()); } #[test] fn test_eq() { // These constants once happened to expose a bug in insert(). // I'm keeping them around to prevent a regression. let mut s1 = HashSet::new(); s1.insert(1i); s1.insert(2); s1.insert(3); let mut s2 = HashSet::new(); s2.insert(1i); s2.insert(2); assert!(s1 != s2); s2.insert(3); assert_eq!(s1, s2); } #[test] fn test_show() { let mut set: HashSet<int> = HashSet::new(); let empty: HashSet<int> = HashSet::new(); set.insert(1i); set.insert(2); let set_str = format!("{}", set); assert!(set_str == "{1, 2}".to_string() || set_str == "{2, 1}".to_string()); assert_eq!(format!("{}", empty), "{}".to_string()); } } </ins>

Discussion:
The recent attempts to improve hashmap seem to have exposed a bug in regionck where it fails to link the lifetimes of ref bindings in some situations. A mostly minimized test case is here: This test fails to compile but (I believe) should succeed. The problem is that the lifetime of the binding inside the callback from is not "linked" (in regionck terminology) to the lifetime , and hence region inference infers a lifetime for that is too small. It was not immediately obvious what the best way is to fix this -- the code around handling ref bindings seems a bit ... off in regionck, so I need to think about it some. Perturbing the code in various ways can workaround the issue, which is bad for making minimized test cases but good for landing the hasmap patch in the meantime!
I've run into (I think) another manifestation of this issue that forces the destructuring of a reference to a tuple from the arguments to the closure body: This works, but this does not
I think this is the original problem, updated to current syntax: error: Actually, maybe this should be using something other than Box... ugh old closures.
If you use a boxed closure, remember to box it: This runs on modern rustc.
Ah duh. Thanks!