From 4ca2f7a0f6e5a00ac75752dd0a3fc775e52b04aa Mon Sep 17 00:00:00 2001 From: Jared Roesch Date: Tue, 30 Jun 2015 21:35:14 -0700 Subject: [PATCH 1/5] Deprecate EnumSet and remove its final use in rustc --- src/libcollections/enum_set.rs | 7 ++- src/libcollections/lib.rs | 1 + src/librustc/lib.rs | 1 - src/librustc/middle/traits/select.rs | 4 +- src/librustc/middle/ty.rs | 94 +++++++++++++++++++--------- src/libserialize/collection_impls.rs | 3 + 6 files changed, 76 insertions(+), 34 deletions(-) diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index e90e6c065a2c2..16ad2a46ff942 100644 --- a/src/libcollections/enum_set.rs +++ b/src/libcollections/enum_set.rs @@ -13,10 +13,11 @@ //! This module defines a container which uses an efficient bit mask //! representation to hold C-like enum variants. +#![deprecated(reason = "EnumSet has been deprecated", + since = "1.2.0")] #![unstable(feature = "enumset", - reason = "matches collection reform specification, \ - waiting for dust to settle")] - + reason = "deprecated")] +#![allow(deprecated)] use core::prelude::*; use core::marker; use core::fmt; diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 8d0f57de4c595..6523d32bf2255 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -82,6 +82,7 @@ pub use bit_set::BitSet; pub use btree_map::BTreeMap; pub use btree_set::BTreeSet; pub use linked_list::LinkedList; +#[allow(deprecated)] pub use enum_set::EnumSet; pub use vec_deque::VecDeque; pub use string::String; diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 2cec42b76bce3..c7a6956a8985c 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -35,7 +35,6 @@ #![feature(duration)] #![feature(duration_span)] #![feature(dynamic_lib)] -#![feature(enumset)] #![feature(fs_canonicalize)] #![feature(hash_default)] #![feature(hashmap_hasher)] diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index ae15c8aa8e028..55e8554b17918 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -1343,7 +1343,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::TyTrait(ref data) => { match self.tcx().lang_items.to_builtin_kind(obligation.predicate.def_id()) { Some(bound @ ty::BoundSend) | Some(bound @ ty::BoundSync) => { - if data.bounds.builtin_bounds.contains(&bound) { + if data.bounds.builtin_bounds.contains(bound) { debug!("assemble_candidates_from_object_ty: matched builtin bound, \ pushing candidate"); candidates.vec.push(BuiltinObjectCandidate); @@ -1632,7 +1632,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match bound { ty::BoundSized => Err(Unimplemented), ty::BoundCopy => { - if data.bounds.builtin_bounds.contains(&bound) { + if data.bounds.builtin_bounds.contains(bound) { ok_if(Vec::new()) } else { // Recursively check all supertraits to find out if any further diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index fe52fba49c6e5..3119d77dae640 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -76,11 +76,9 @@ use std::cell::{Cell, RefCell, Ref}; use std::cmp; use std::fmt; use std::hash::{Hash, SipHasher, Hasher}; -use std::mem; use std::ops; use std::rc::Rc; use std::vec::IntoIter; -use collections::enum_set::{self, EnumSet, CLike}; use std::collections::{HashMap, HashSet}; use syntax::abi; use syntax::ast::{CrateNum, DefId, ItemImpl, ItemTrait, LOCAL_CRATE}; @@ -2059,18 +2057,44 @@ pub struct ExistentialBounds<'tcx> { pub projection_bounds: Vec>, } -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] -pub struct BuiltinBounds(EnumSet); +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +pub struct BuiltinBounds { + bits: u8 +} impl BuiltinBounds { - pub fn empty() -> BuiltinBounds { - BuiltinBounds(EnumSet::new()) + pub fn empty() -> BuiltinBounds { + BuiltinBounds { bits: 0 } + } + + pub fn insert(&mut self, bound: BuiltinBound) { + self.bits = match bound { + BuiltinBound::Send => self.bits | 0b0000_0001, + BuiltinBound::Sized => self.bits | 0b0000_0010, + BuiltinBound::Copy => self.bits | 0b0000_0100, + BuiltinBound::Sync => self.bits | 0b0000_1000, + } + } + + pub fn contains(&self, bound: BuiltinBound) -> bool { + let bit = match bound { + BuiltinBound::Send => self.bits, + BuiltinBound::Sized => self.bits >> 1, + BuiltinBound::Copy => self.bits >> 2, + BuiltinBound::Sync => self.bits >> 3 + }; + + (bit & 0b0000_0001) == 1 } - pub fn iter(&self) -> enum_set::Iter { + pub fn iter(&self) -> BuiltinBoundsIter { self.into_iter() } + fn is_empty(&self) -> bool { + self.bits == 0 + } + pub fn to_predicates<'tcx>(&self, tcx: &ty::ctxt<'tcx>, self_ty: Ty<'tcx>) -> Vec> { @@ -2081,28 +2105,51 @@ impl BuiltinBounds { } ).collect() } + + pub fn is_superset(&self, other: &BuiltinBounds) -> bool { + (self.bits & other.bits) == other.bits + } } -impl ops::Deref for BuiltinBounds { - type Target = EnumSet; - fn deref(&self) -> &Self::Target { &self.0 } +pub struct BuiltinBoundsIter { + bounds: BuiltinBounds, + index: u8 } -impl ops::DerefMut for BuiltinBounds { - fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } +impl Iterator for BuiltinBoundsIter { + type Item = BuiltinBound; + + fn next(&mut self) -> Option { + while self.index < 4 { + let result = match self.index { + 0 if self.bounds.contains(BuiltinBound::Send) => Some(BuiltinBound::Send), + 1 if self.bounds.contains(BuiltinBound::Sized) => Some(BuiltinBound::Sized), + 2 if self.bounds.contains(BuiltinBound::Copy) => Some(BuiltinBound::Copy), + 3 if self.bounds.contains(BuiltinBound::Sync) => Some(BuiltinBound::Sync), + _ => None + }; + + self.index += 1; + + if result.is_some() { + return result; + } + } + + return None; + } } impl<'a> IntoIterator for &'a BuiltinBounds { type Item = BuiltinBound; - type IntoIter = enum_set::Iter; - fn into_iter(self) -> Self::IntoIter { - (**self).into_iter() + type IntoIter = BuiltinBoundsIter; + + fn into_iter(self) -> BuiltinBoundsIter { + BuiltinBoundsIter { bounds: self.clone(), index: 0 } } } -#[derive(Clone, RustcEncodable, PartialEq, Eq, RustcDecodable, Hash, - Debug, Copy)] -#[repr(usize)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcDecodable, RustcEncodable, Hash, Debug)] pub enum BuiltinBound { Send, Sized, @@ -2110,15 +2157,6 @@ pub enum BuiltinBound { Sync, } -impl CLike for BuiltinBound { - fn to_usize(&self) -> usize { - *self as usize - } - fn from_usize(v: usize) -> BuiltinBound { - unsafe { mem::transmute(v) } - } -} - #[derive(Clone, Copy, PartialEq, Eq, Hash)] pub struct TyVid { pub index: u32 @@ -5707,7 +5745,7 @@ impl<'tcx> ctxt<'tcx> { pub fn try_add_builtin_trait(&self, trait_def_id: ast::DefId, - builtin_bounds: &mut EnumSet) + builtin_bounds: &mut BuiltinBounds) -> bool { //! Checks whether `trait_ref` refers to one of the builtin diff --git a/src/libserialize/collection_impls.rs b/src/libserialize/collection_impls.rs index e7430f698e9c9..75ca1ad168cf1 100644 --- a/src/libserialize/collection_impls.rs +++ b/src/libserialize/collection_impls.rs @@ -17,6 +17,7 @@ use std::collections::hash_state::HashState; use {Decodable, Encodable, Decoder, Encoder}; use std::collections::{LinkedList, VecDeque, BTreeMap, BTreeSet, HashMap, HashSet, VecMap}; +#[allow(deprecated)] use collections::enum_set::{EnumSet, CLike}; impl< @@ -130,6 +131,7 @@ impl< } } +#[allow(deprecated)] impl< T: Encodable + CLike > Encodable for EnumSet { @@ -142,6 +144,7 @@ impl< } } +#[allow(deprecated)] impl< T: Decodable + CLike > Decodable for EnumSet { From 2b0f13fde449e1e6d0d0e210b68371149b658a06 Mon Sep 17 00:00:00 2001 From: Jared Roesch Date: Wed, 1 Jul 2015 13:16:25 -0700 Subject: [PATCH 2/5] Address nits --- src/libcollections/enum_set.rs | 283 ------------------ src/libcollections/lib.rs | 3 - src/librustc/middle/ty.rs | 16 +- src/libserialize/collection_impls.rs | 32 -- src/libserialize/lib.rs | 2 - .../sync-send-iterators-in-libcollections.rs | 5 +- 6 files changed, 3 insertions(+), 338 deletions(-) delete mode 100644 src/libcollections/enum_set.rs diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs deleted file mode 100644 index 16ad2a46ff942..0000000000000 --- a/src/libcollections/enum_set.rs +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! A structure for holding a set of enum variants. -//! -//! This module defines a container which uses an efficient bit mask -//! representation to hold C-like enum variants. - -#![deprecated(reason = "EnumSet has been deprecated", - since = "1.2.0")] -#![unstable(feature = "enumset", - reason = "deprecated")] -#![allow(deprecated)] -use core::prelude::*; -use core::marker; -use core::fmt; -use core::iter::{FromIterator}; -use core::ops::{Sub, BitOr, BitAnd, BitXor}; - -// FIXME(contentions): implement union family of methods? (general design may be -// wrong here) - -/// A specialized set implementation to use enum types. -/// -/// It is a logic error for an item to be modified in such a way that the -/// transformation of the item to or from a `usize`, as determined by the -/// `CLike` trait, changes while the item is in the set. This is normally only -/// possible through `Cell`, `RefCell`, global state, I/O, or unsafe code. -#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct EnumSet { - // We must maintain the invariant that no bits are set - // for which no variant exists - bits: usize, - marker: marker::PhantomData, -} - -impl Copy for EnumSet {} - -impl Clone for EnumSet { - fn clone(&self) -> EnumSet { *self } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for EnumSet { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - try!(write!(fmt, "{{")); - let mut first = true; - for e in self { - if !first { - try!(write!(fmt, ", ")); - } - try!(write!(fmt, "{:?}", e)); - first = false; - } - write!(fmt, "}}") - } -} - -/// An interface for casting C-like enum to usize and back. -/// A typically implementation is as below. -/// -/// ```{rust,ignore} -/// #[repr(usize)] -/// enum Foo { -/// A, B, C -/// } -/// -/// impl CLike for Foo { -/// fn to_usize(&self) -> usize { -/// *self as usize -/// } -/// -/// fn from_usize(v: usize) -> Foo { -/// unsafe { mem::transmute(v) } -/// } -/// } -/// ``` -pub trait CLike { - /// Converts a C-like enum to a `usize`. - fn to_usize(&self) -> usize; - /// Converts a `usize` to a C-like enum. - fn from_usize(usize) -> Self; -} - -fn bit(e: &E) -> usize { - use core::usize; - let value = e.to_usize(); - assert!(value < usize::BITS, - "EnumSet only supports up to {} variants.", usize::BITS - 1); - 1 << value -} - -impl EnumSet { - /// Returns an empty `EnumSet`. - pub fn new() -> EnumSet { - EnumSet {bits: 0, marker: marker::PhantomData} - } - - /// Returns the number of elements in the given `EnumSet`. - pub fn len(&self) -> usize { - self.bits.count_ones() as usize - } - - /// Returns true if the `EnumSet` is empty. - pub fn is_empty(&self) -> bool { - self.bits == 0 - } - - pub fn clear(&mut self) { - self.bits = 0; - } - - /// Returns `false` if the `EnumSet` contains any enum of the given `EnumSet`. - pub fn is_disjoint(&self, other: &EnumSet) -> bool { - (self.bits & other.bits) == 0 - } - - /// Returns `true` if a given `EnumSet` is included in this `EnumSet`. - pub fn is_superset(&self, other: &EnumSet) -> bool { - (self.bits & other.bits) == other.bits - } - - /// Returns `true` if this `EnumSet` is included in the given `EnumSet`. - pub fn is_subset(&self, other: &EnumSet) -> bool { - other.is_superset(self) - } - - /// Returns the union of both `EnumSets`. - pub fn union(&self, e: EnumSet) -> EnumSet { - EnumSet {bits: self.bits | e.bits, - marker: marker::PhantomData} - } - - /// Returns the intersection of both `EnumSets`. - pub fn intersection(&self, e: EnumSet) -> EnumSet { - EnumSet {bits: self.bits & e.bits, - marker: marker::PhantomData} - } - - /// Adds an enum to the `EnumSet`, and returns `true` if it wasn't there before - pub fn insert(&mut self, e: E) -> bool { - let result = !self.contains(&e); - self.bits |= bit(&e); - result - } - - /// Removes an enum from the EnumSet - pub fn remove(&mut self, e: &E) -> bool { - let result = self.contains(e); - self.bits &= !bit(e); - result - } - - /// Returns `true` if an `EnumSet` contains a given enum. - pub fn contains(&self, e: &E) -> bool { - (self.bits & bit(e)) != 0 - } - - /// Returns an iterator over an `EnumSet`. - pub fn iter(&self) -> Iter { - Iter::new(self.bits) - } -} - -impl Sub for EnumSet { - type Output = EnumSet; - - fn sub(self, e: EnumSet) -> EnumSet { - EnumSet {bits: self.bits & !e.bits, marker: marker::PhantomData} - } -} - -impl BitOr for EnumSet { - type Output = EnumSet; - - fn bitor(self, e: EnumSet) -> EnumSet { - EnumSet {bits: self.bits | e.bits, marker: marker::PhantomData} - } -} - -impl BitAnd for EnumSet { - type Output = EnumSet; - - fn bitand(self, e: EnumSet) -> EnumSet { - EnumSet {bits: self.bits & e.bits, marker: marker::PhantomData} - } -} - -impl BitXor for EnumSet { - type Output = EnumSet; - - fn bitxor(self, e: EnumSet) -> EnumSet { - EnumSet {bits: self.bits ^ e.bits, marker: marker::PhantomData} - } -} - -/// An iterator over an EnumSet -pub struct Iter { - index: usize, - bits: usize, - marker: marker::PhantomData, -} - -// FIXME(#19839) Remove in favor of `#[derive(Clone)]` -impl Clone for Iter { - fn clone(&self) -> Iter { - Iter { - index: self.index, - bits: self.bits, - marker: marker::PhantomData, - } - } -} - -impl Iter { - fn new(bits: usize) -> Iter { - Iter { index: 0, bits: bits, marker: marker::PhantomData } - } -} - -impl Iterator for Iter { - type Item = E; - - fn next(&mut self) -> Option { - if self.bits == 0 { - return None; - } - - while (self.bits & 1) == 0 { - self.index += 1; - self.bits >>= 1; - } - let elem = CLike::from_usize(self.index); - self.index += 1; - self.bits >>= 1; - Some(elem) - } - - fn size_hint(&self) -> (usize, Option) { - let exact = self.bits.count_ones() as usize; - (exact, Some(exact)) - } -} - -impl FromIterator for EnumSet { - fn from_iter>(iter: I) -> EnumSet { - let mut ret = EnumSet::new(); - ret.extend(iter); - ret - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, E> IntoIterator for &'a EnumSet where E: CLike { - type Item = E; - type IntoIter = Iter; - - fn into_iter(self) -> Iter { - self.iter() - } -} - -impl Extend for EnumSet { - fn extend>(&mut self, iter: I) { - for element in iter { - self.insert(element); - } - } -} - -#[stable(feature = "extend_ref", since = "1.2.0")] -impl<'a, E: 'a + CLike + Copy> Extend<&'a E> for EnumSet { - fn extend>(&mut self, iter: I) { - self.extend(iter.into_iter().cloned()); - } -} diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 6523d32bf2255..236457fa1c265 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -82,8 +82,6 @@ pub use bit_set::BitSet; pub use btree_map::BTreeMap; pub use btree_set::BTreeSet; pub use linked_list::LinkedList; -#[allow(deprecated)] -pub use enum_set::EnumSet; pub use vec_deque::VecDeque; pub use string::String; pub use vec::Vec; @@ -99,7 +97,6 @@ pub mod binary_heap; mod bit; mod btree; pub mod borrow; -pub mod enum_set; pub mod fmt; pub mod linked_list; pub mod range; diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 3119d77dae640..9fc17e458a7a0 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -2068,23 +2068,11 @@ impl BuiltinBounds { } pub fn insert(&mut self, bound: BuiltinBound) { - self.bits = match bound { - BuiltinBound::Send => self.bits | 0b0000_0001, - BuiltinBound::Sized => self.bits | 0b0000_0010, - BuiltinBound::Copy => self.bits | 0b0000_0100, - BuiltinBound::Sync => self.bits | 0b0000_1000, - } + self.bits |= 1 << (bound as u8); } pub fn contains(&self, bound: BuiltinBound) -> bool { - let bit = match bound { - BuiltinBound::Send => self.bits, - BuiltinBound::Sized => self.bits >> 1, - BuiltinBound::Copy => self.bits >> 2, - BuiltinBound::Sync => self.bits >> 3 - }; - - (bit & 0b0000_0001) == 1 + ((self.bits >> (bound as u8)) & 1) == 1 } pub fn iter(&self) -> BuiltinBoundsIter { diff --git a/src/libserialize/collection_impls.rs b/src/libserialize/collection_impls.rs index 75ca1ad168cf1..859c2de616f00 100644 --- a/src/libserialize/collection_impls.rs +++ b/src/libserialize/collection_impls.rs @@ -10,15 +10,12 @@ //! Implementations of serialization for structures found in libcollections -use std::usize; use std::default::Default; use std::hash::Hash; use std::collections::hash_state::HashState; use {Decodable, Encodable, Decoder, Encoder}; use std::collections::{LinkedList, VecDeque, BTreeMap, BTreeSet, HashMap, HashSet, VecMap}; -#[allow(deprecated)] -use collections::enum_set::{EnumSet, CLike}; impl< T: Encodable @@ -131,35 +128,6 @@ impl< } } -#[allow(deprecated)] -impl< - T: Encodable + CLike -> Encodable for EnumSet { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - let mut bits = 0; - for item in self { - bits |= item.to_usize(); - } - s.emit_uint(bits) - } -} - -#[allow(deprecated)] -impl< - T: Decodable + CLike -> Decodable for EnumSet { - fn decode(d: &mut D) -> Result, D::Error> { - let bits = try!(d.read_uint()); - let mut set = EnumSet::new(); - for bit in 0..usize::BITS { - if bits & (1 << bit) != 0 { - set.insert(CLike::from_usize(1 << bit)); - } - } - Ok(set) - } -} - impl Encodable for HashMap where K: Encodable + Hash + Eq, V: Encodable, diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index e7d9751cf4bc6..305a9604c0a58 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -29,9 +29,7 @@ Core encoding and decoding interfaces. #![feature(box_syntax)] #![feature(collections)] -#![feature(enumset)] #![feature(hashmap_hasher)] -#![feature(num_bits_bytes)] #![feature(rustc_private)] #![feature(staged_api)] #![feature(str_char)] diff --git a/src/test/run-pass/sync-send-iterators-in-libcollections.rs b/src/test/run-pass/sync-send-iterators-in-libcollections.rs index 0ee04c4463b0f..b14bb223195d6 100644 --- a/src/test/run-pass/sync-send-iterators-in-libcollections.rs +++ b/src/test/run-pass/sync-send-iterators-in-libcollections.rs @@ -12,14 +12,13 @@ #![allow(warnings)] #![feature(collections)] -#![feature(drain, enumset, collections_bound, btree_range, vecmap)] +#![feature(drain, collections_bound, btree_range, vecmap)] extern crate collections; use collections::BinaryHeap; use collections::{BitSet, BitVec}; use collections::{BTreeMap, BTreeSet}; -use collections::EnumSet; use collections::LinkedList; use collections::String; use collections::Vec; @@ -27,7 +26,6 @@ use collections::VecDeque; use collections::VecMap; use collections::Bound::Included; -use collections::enum_set::CLike; use std::mem; fn is_sync(_: T) where T: Sync {} @@ -92,7 +90,6 @@ fn main() { unsafe { mem::transmute(v) } } } - all_sync_send!(EnumSet::::new(), iter); all_sync_send!(VecDeque::::new(), iter, iter_mut, drain, into_iter); From 2c8ab28cc1f12195f7ca6f1efff1c7f4e9c10bd5 Mon Sep 17 00:00:00 2001 From: Jared Roesch Date: Wed, 1 Jul 2015 18:55:36 -0700 Subject: [PATCH 3/5] Move BuiltinBounds underlying implementation to the data structure crate --- src/librustc/middle/ty.rs | 39 ++++------- src/librustc_data_structures/bitset.rs | 96 ++++++++++++++++++++++++++ src/librustc_data_structures/lib.rs | 2 + 3 files changed, 111 insertions(+), 26 deletions(-) create mode 100644 src/librustc_data_structures/bitset.rs diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 9fc17e458a7a0..c704fdb4a3c57 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -70,12 +70,15 @@ use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet}; use util::nodemap::FnvHashMap; use util::num::ToPrimitive; +use rustc_data_structures::bitset::{U8BitSet, BitSet, BitSetIter}; + use arena::TypedArena; use std::borrow::{Borrow, Cow}; use std::cell::{Cell, RefCell, Ref}; use std::cmp; use std::fmt; use std::hash::{Hash, SipHasher, Hasher}; +use std::mem; use std::ops; use std::rc::Rc; use std::vec::IntoIter; @@ -2059,20 +2062,20 @@ pub struct ExistentialBounds<'tcx> { #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub struct BuiltinBounds { - bits: u8 + bit_set: U8BitSet } impl BuiltinBounds { pub fn empty() -> BuiltinBounds { - BuiltinBounds { bits: 0 } + BuiltinBounds { bit_set: BitSet::empty() } } pub fn insert(&mut self, bound: BuiltinBound) { - self.bits |= 1 << (bound as u8); + self.bit_set.insert(bound as u8) } pub fn contains(&self, bound: BuiltinBound) -> bool { - ((self.bits >> (bound as u8)) & 1) == 1 + self.bit_set.contains(bound as u8) } pub fn iter(&self) -> BuiltinBoundsIter { @@ -2080,7 +2083,7 @@ impl BuiltinBounds { } fn is_empty(&self) -> bool { - self.bits == 0 + self.bit_set.is_empty() } pub fn to_predicates<'tcx>(&self, @@ -2095,36 +2098,19 @@ impl BuiltinBounds { } pub fn is_superset(&self, other: &BuiltinBounds) -> bool { - (self.bits & other.bits) == other.bits + self.bit_set.is_superset(other.bit_set) } } pub struct BuiltinBoundsIter { - bounds: BuiltinBounds, - index: u8 + bit_set: BitSetIter } impl Iterator for BuiltinBoundsIter { type Item = BuiltinBound; fn next(&mut self) -> Option { - while self.index < 4 { - let result = match self.index { - 0 if self.bounds.contains(BuiltinBound::Send) => Some(BuiltinBound::Send), - 1 if self.bounds.contains(BuiltinBound::Sized) => Some(BuiltinBound::Sized), - 2 if self.bounds.contains(BuiltinBound::Copy) => Some(BuiltinBound::Copy), - 3 if self.bounds.contains(BuiltinBound::Sync) => Some(BuiltinBound::Sync), - _ => None - }; - - self.index += 1; - - if result.is_some() { - return result; - } - } - - return None; + self.bit_set.next().map(|b| unsafe { mem::transmute(b) }) } } @@ -2133,10 +2119,11 @@ impl<'a> IntoIterator for &'a BuiltinBounds { type IntoIter = BuiltinBoundsIter; fn into_iter(self) -> BuiltinBoundsIter { - BuiltinBoundsIter { bounds: self.clone(), index: 0 } + BuiltinBoundsIter { bit_set: self.bit_set.into_iter() } } } +#[repr(u8)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcDecodable, RustcEncodable, Hash, Debug)] pub enum BuiltinBound { Send, diff --git a/src/librustc_data_structures/bitset.rs b/src/librustc_data_structures/bitset.rs new file mode 100644 index 0000000000000..ffd2e9f99a227 --- /dev/null +++ b/src/librustc_data_structures/bitset.rs @@ -0,0 +1,96 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::ops::{Add, Sub, Shl, Shr, BitAnd, BitOr}; +use std::num::{Zero, One}; +use std::cmp::PartialEq; + +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +pub struct BitSet { + bits: N +} + +pub trait UnsignedInt : Zero + + One + + Add + + Sub + + Shl + + Shr + + BitAnd + + BitOr + + PartialEq + + PartialOrd + + Copy {} + +impl UnsignedInt for u8 {} + +pub type U8BitSet = BitSet; + +impl BitSet { + pub fn empty() -> BitSet { + BitSet { bits: Zero::zero() } + } + + pub fn insert(&mut self, value: N) { + self.bits = self.bits | (N::one() << value); + } + + pub fn contains(&self, value: N) -> bool { + ((self.bits >> value) & N::one()) == N::one() + } + + pub fn iter(&self) -> BitSetIter { + self.into_iter() + } + + pub fn is_empty(&self) -> bool { + self.bits == N::zero() + } + + pub fn is_superset(&self, other: BitSet) -> bool { + (self.bits & other.bits) == other.bits + } +} + +pub struct BitSetIter { + bits: N, + index: N +} + +impl Iterator for BitSetIter { + type Item = N; + + fn next(&mut self) -> Option { + if self.bits == N::zero() { + return None; + } + + while (self.bits & N::one()) == N::zero() { + self.index = self.index + N::one(); + self.bits = self.bits >> N::one(); + } + + let result = self.index; + + self.index = self.index + N::one(); + self.bits = self.bits >> N::one(); + Some(result) + } +} + + +impl<'a, N: UnsignedInt> IntoIterator for &'a BitSet { + type Item = N; + type IntoIter = BitSetIter; + + fn into_iter(self) -> BitSetIter { + BitSetIter { bits: self.bits, index: N::zero() } + } +} diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 1f8f7694ff90d..ac6821fa8e28c 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -28,6 +28,7 @@ html_root_url = "http://doc.rust-lang.org/nightly/")] #![feature(rustc_private, staged_api)] +#![feature(zero_one)] #![cfg_attr(test, feature(test))] #[macro_use] extern crate log; @@ -36,4 +37,5 @@ extern crate serialize as rustc_serialize; // used by deriving pub mod snapshot_vec; pub mod graph; pub mod bitvec; +pub mod bitset; pub mod unify; From f4ff8ef716856eaa84bd2f3dc3f627cb9d79fa4c Mon Sep 17 00:00:00 2001 From: Jared Roesch Date: Wed, 8 Jul 2015 01:47:09 -0700 Subject: [PATCH 4/5] Remove test that mentions CLike --- src/libcollectionstest/enum_set.rs | 266 ------------------ .../sync-send-iterators-in-libcollections.rs | 9 - 2 files changed, 275 deletions(-) delete mode 100644 src/libcollectionstest/enum_set.rs diff --git a/src/libcollectionstest/enum_set.rs b/src/libcollectionstest/enum_set.rs deleted file mode 100644 index b073c2f3ae4dd..0000000000000 --- a/src/libcollectionstest/enum_set.rs +++ /dev/null @@ -1,266 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::mem; - -use collections::enum_set::{CLike, EnumSet}; - -use self::Foo::*; - -#[derive(Copy, Clone, PartialEq, Debug)] -#[repr(usize)] -enum Foo { - A, B, C -} - -impl CLike for Foo { - fn to_usize(&self) -> usize { - *self as usize - } - - fn from_usize(v: usize) -> Foo { - unsafe { mem::transmute(v) } - } -} - -#[test] -fn test_new() { - let e: EnumSet = EnumSet::new(); - assert!(e.is_empty()); -} - -#[test] -fn test_show() { - let mut e = EnumSet::new(); - assert!(format!("{:?}", e) == "{}"); - e.insert(A); - assert!(format!("{:?}", e) == "{A}"); - e.insert(C); - assert!(format!("{:?}", e) == "{A, C}"); -} - -#[test] -fn test_len() { - let mut e = EnumSet::new(); - assert_eq!(e.len(), 0); - e.insert(A); - e.insert(B); - e.insert(C); - assert_eq!(e.len(), 3); - e.remove(&A); - assert_eq!(e.len(), 2); - e.clear(); - assert_eq!(e.len(), 0); -} - -/////////////////////////////////////////////////////////////////////////// -// intersect - -#[test] -fn test_two_empties_do_not_intersect() { - let e1: EnumSet = EnumSet::new(); - let e2: EnumSet = EnumSet::new(); - assert!(e1.is_disjoint(&e2)); -} - -#[test] -fn test_empty_does_not_intersect_with_full() { - let e1: EnumSet = EnumSet::new(); - - let mut e2: EnumSet = EnumSet::new(); - e2.insert(A); - e2.insert(B); - e2.insert(C); - - assert!(e1.is_disjoint(&e2)); -} - -#[test] -fn test_disjoint_intersects() { - let mut e1: EnumSet = EnumSet::new(); - e1.insert(A); - - let mut e2: EnumSet = EnumSet::new(); - e2.insert(B); - - assert!(e1.is_disjoint(&e2)); -} - -#[test] -fn test_overlapping_intersects() { - let mut e1: EnumSet = EnumSet::new(); - e1.insert(A); - - let mut e2: EnumSet = EnumSet::new(); - e2.insert(A); - e2.insert(B); - - assert!(!e1.is_disjoint(&e2)); -} - -/////////////////////////////////////////////////////////////////////////// -// contains and contains_elem - -#[test] -fn test_superset() { - let mut e1: EnumSet = EnumSet::new(); - e1.insert(A); - - let mut e2: EnumSet = EnumSet::new(); - e2.insert(A); - e2.insert(B); - - let mut e3: EnumSet = EnumSet::new(); - e3.insert(C); - - assert!(e1.is_subset(&e2)); - assert!(e2.is_superset(&e1)); - assert!(!e3.is_superset(&e2)); - assert!(!e2.is_superset(&e3)) -} - -#[test] -fn test_contains() { - let mut e1: EnumSet = EnumSet::new(); - e1.insert(A); - assert!(e1.contains(&A)); - assert!(!e1.contains(&B)); - assert!(!e1.contains(&C)); - - e1.insert(A); - e1.insert(B); - assert!(e1.contains(&A)); - assert!(e1.contains(&B)); - assert!(!e1.contains(&C)); -} - -/////////////////////////////////////////////////////////////////////////// -// iter - -#[test] -fn test_iterator() { - let mut e1: EnumSet = EnumSet::new(); - - let elems: Vec = e1.iter().collect(); - assert!(elems.is_empty()); - - e1.insert(A); - let elems: Vec<_> = e1.iter().collect(); - assert_eq!(elems, [A]); - - e1.insert(C); - let elems: Vec<_> = e1.iter().collect(); - assert_eq!(elems, [A,C]); - - e1.insert(C); - let elems: Vec<_> = e1.iter().collect(); - assert_eq!(elems, [A,C]); - - e1.insert(B); - let elems: Vec<_> = e1.iter().collect(); - assert_eq!(elems, [A,B,C]); -} - -/////////////////////////////////////////////////////////////////////////// -// operators - -#[test] -fn test_operators() { - let mut e1: EnumSet = EnumSet::new(); - e1.insert(A); - e1.insert(C); - - let mut e2: EnumSet = EnumSet::new(); - e2.insert(B); - e2.insert(C); - - let e_union = e1 | e2; - let elems: Vec<_> = e_union.iter().collect(); - assert_eq!(elems, [A,B,C]); - - let e_intersection = e1 & e2; - let elems: Vec<_> = e_intersection.iter().collect(); - assert_eq!(elems, [C]); - - // Another way to express intersection - let e_intersection = e1 - (e1 - e2); - let elems: Vec<_> = e_intersection.iter().collect(); - assert_eq!(elems, [C]); - - let e_subtract = e1 - e2; - let elems: Vec<_> = e_subtract.iter().collect(); - assert_eq!(elems, [A]); - - // Bitwise XOR of two sets, aka symmetric difference - let e_symmetric_diff = e1 ^ e2; - let elems: Vec<_> = e_symmetric_diff.iter().collect(); - assert_eq!(elems, [A,B]); - - // Another way to express symmetric difference - let e_symmetric_diff = (e1 - e2) | (e2 - e1); - let elems: Vec<_> = e_symmetric_diff.iter().collect(); - assert_eq!(elems, [A,B]); - - // Yet another way to express symmetric difference - let e_symmetric_diff = (e1 | e2) - (e1 & e2); - let elems: Vec<_> = e_symmetric_diff.iter().collect(); - assert_eq!(elems, [A,B]); -} - -#[test] -#[should_panic] -fn test_overflow() { - #[allow(dead_code)] - #[derive(Copy, Clone)] - #[repr(usize)] - enum Bar { - V00, V01, V02, V03, V04, V05, V06, V07, V08, V09, - V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, - V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, - V30, V31, V32, V33, V34, V35, V36, V37, V38, V39, - V40, V41, V42, V43, V44, V45, V46, V47, V48, V49, - V50, V51, V52, V53, V54, V55, V56, V57, V58, V59, - V60, V61, V62, V63, V64, V65, V66, V67, V68, V69, - } - - impl CLike for Bar { - fn to_usize(&self) -> usize { - *self as usize - } - - fn from_usize(v: usize) -> Bar { - unsafe { mem::transmute(v) } - } - } - let mut set = EnumSet::new(); - set.insert(Bar::V64); -} - -#[test] -fn test_extend_ref() { - let mut a = EnumSet::new(); - a.insert(A); - - a.extend(&[A, C]); - - assert_eq!(a.len(), 2); - assert!(a.contains(&A)); - assert!(a.contains(&C)); - - let mut b = EnumSet::new(); - b.insert(B); - - a.extend(&b); - - assert_eq!(a.len(), 3); - assert!(a.contains(&A)); - assert!(a.contains(&B)); - assert!(a.contains(&C)); -} diff --git a/src/test/run-pass/sync-send-iterators-in-libcollections.rs b/src/test/run-pass/sync-send-iterators-in-libcollections.rs index b14bb223195d6..f3e491a873823 100644 --- a/src/test/run-pass/sync-send-iterators-in-libcollections.rs +++ b/src/test/run-pass/sync-send-iterators-in-libcollections.rs @@ -81,15 +81,6 @@ fn main() { #[repr(usize)] #[allow(dead_code)] enum Foo { A, B, C } - impl CLike for Foo { - fn to_usize(&self) -> usize { - *self as usize - } - - fn from_usize(v: usize) -> Foo { - unsafe { mem::transmute(v) } - } - } all_sync_send!(VecDeque::::new(), iter, iter_mut, drain, into_iter); From 775df8803aa079e2b0c5832b9c035ad8a4fe57a9 Mon Sep 17 00:00:00 2001 From: Jared Roesch Date: Mon, 20 Jul 2015 12:12:32 -0700 Subject: [PATCH 5/5] Fix final test failure --- src/libcollectionstest/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs index ba1b4964b49a3..beef4242f9c30 100644 --- a/src/libcollectionstest/lib.rs +++ b/src/libcollectionstest/lib.rs @@ -65,7 +65,6 @@ extern crate rustc_unicode; mod binary_heap; mod bit; mod btree; -mod enum_set; mod fmt; mod linked_list; mod slice;