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;