Skip to content

Commit

Permalink
collections: Enable IndexMut for some collections
Browse files Browse the repository at this point in the history
This commit enables implementations of IndexMut for a number of collections,
including Vec, RingBuf, SmallIntMap, TrieMap, TreeMap, and HashMap. At the same
time this deprecates the `get_mut` methods on vectors in favor of using the
indexing notation.

cc rust-lang#18424
  • Loading branch information
alexcrichton committed Oct 30, 2014
1 parent 18a3db6 commit 1d35662
Show file tree
Hide file tree
Showing 46 changed files with 165 additions and 271 deletions.
2 changes: 1 addition & 1 deletion src/compiletest/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1013,7 +1013,7 @@ fn check_expected_errors(expected_errors: Vec<errors::ExpectedError> ,
if prefix_matches(line, prefixes[i].as_slice()) &&
line.contains(ee.kind.as_slice()) &&
line.contains(ee.msg.as_slice()) {
*found_flags.get_mut(i) = true;
found_flags[i] = true;
was_expected = true;
break;
}
Expand Down
21 changes: 11 additions & 10 deletions src/libcollections/bitv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ impl Bitv {
let used_bits = bitv.nbits % u32::BITS;
if init && used_bits != 0 {
let largest_used_word = (bitv.nbits + u32::BITS - 1) / u32::BITS - 1;
*bitv.storage.get_mut(largest_used_word) &= (1 << used_bits) - 1;
bitv.storage[largest_used_word] &= (1 << used_bits) - 1;
}

bitv
Expand Down Expand Up @@ -297,8 +297,9 @@ impl Bitv {
let w = i / u32::BITS;
let b = i % u32::BITS;
let flag = 1 << b;
*self.storage.get_mut(w) = if x { self.storage[w] | flag }
else { self.storage[w] & !flag };
let val = if x { self.storage[w] | flag }
else { self.storage[w] & !flag };
self.storage[w] = val;
}

/// Sets all bits to 1.
Expand Down Expand Up @@ -617,7 +618,7 @@ impl Bitv {
self.storage.truncate(word_len);
if len % u32::BITS > 0 {
let mask = (1 << len % u32::BITS) - 1;
*self.storage.get_mut(word_len - 1) &= mask;
self.storage[word_len - 1] &= mask;
}
}
}
Expand Down Expand Up @@ -681,15 +682,15 @@ impl Bitv {
let overhang = self.nbits % u32::BITS; // # of already-used bits
let mask = !((1 << overhang) - 1); // e.g. 5 unused bits => 111110....0
if value {
*self.storage.get_mut(old_last_word) |= mask;
self.storage[old_last_word] |= mask;
} else {
*self.storage.get_mut(old_last_word) &= !mask;
self.storage[old_last_word] &= !mask;
}
}
// Fill in words after the old tail word
let stop_idx = cmp::min(self.storage.len(), new_nwords);
for idx in range(old_last_word + 1, stop_idx) {
*self.storage.get_mut(idx) = full_value;
self.storage[idx] = full_value;
}
// Allocate new words, if needed
if new_nwords > self.storage.len() {
Expand All @@ -700,7 +701,7 @@ impl Bitv {
if value {
let tail_word = new_nwords - 1;
let used_bits = new_nbits % u32::BITS;
*self.storage.get_mut(tail_word) &= (1 << used_bits) - 1;
self.storage[tail_word] &= (1 << used_bits) - 1;
}
}
// Adjust internal bit count
Expand Down Expand Up @@ -728,7 +729,7 @@ impl Bitv {
let ret = self.get(self.nbits - 1);
// If we are unusing a whole word, make sure it is zeroed out
if self.nbits % u32::BITS == 1 {
*self.storage.get_mut(self.nbits / u32::BITS) = 0;
self.storage[self.nbits / u32::BITS] = 0;
}
self.nbits -= 1;
ret
Expand Down Expand Up @@ -1184,7 +1185,7 @@ impl BitvSet {
for (i, w) in other_words {
let old = self_bitv.storage[i];
let new = f(old, w);
*self_bitv.storage.get_mut(i) = new;
self_bitv.storage[i] = new;
}
}

Expand Down
6 changes: 6 additions & 0 deletions src/libcollections/btree/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,12 @@ impl<K: Ord, V> Index<K, V> for BTreeMap<K, V> {
}
}

impl<K: Ord, V> IndexMut<K, V> for BTreeMap<K, V> {
fn index_mut(&mut self, key: &K) -> &mut V {
self.find_mut(key).expect("no entry found for key")
}
}

/// Genericises over how to get the correct type of iterator from the correct type
/// of Node ownership.
trait Traverse<N> {
Expand Down
26 changes: 13 additions & 13 deletions src/libcollections/priority_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
//! let mut pq = PriorityQueue::new();
//!
//! // We're at `start`, with a zero cost
//! *dist.get_mut(start) = 0u;
//! dist[start] = 0u;
//! pq.push(State { cost: 0u, position: start });
//!
//! // Examine the frontier with lower cost nodes first (min-heap)
Expand All @@ -96,7 +96,7 @@
//! if next.cost < dist[next.position] {
//! pq.push(next);
//! // Relaxation, we have now found a better way
//! *dist.get_mut(next.position) = next.cost;
//! dist[next.position] = next.cost;
//! }
//! }
//! }
Expand Down Expand Up @@ -330,7 +330,7 @@ impl<T: Ord> PriorityQueue<T> {
None => { None }
Some(mut item) => {
if !self.is_empty() {
swap(&mut item, self.data.get_mut(0));
swap(&mut item, &mut self.data[0]);
self.siftdown(0);
}
Some(item)
Expand Down Expand Up @@ -378,7 +378,7 @@ impl<T: Ord> PriorityQueue<T> {
/// ```
pub fn push_pop(&mut self, mut item: T) -> T {
if !self.is_empty() && *self.top().unwrap() > item {
swap(&mut item, self.data.get_mut(0));
swap(&mut item, &mut self.data[0]);
self.siftdown(0);
}
item
Expand All @@ -402,7 +402,7 @@ impl<T: Ord> PriorityQueue<T> {
/// ```
pub fn replace(&mut self, mut item: T) -> Option<T> {
if !self.is_empty() {
swap(&mut item, self.data.get_mut(0));
swap(&mut item, &mut self.data[0]);
self.siftdown(0);
Some(item)
} else {
Expand Down Expand Up @@ -462,40 +462,40 @@ impl<T: Ord> PriorityQueue<T> {
// compared to using swaps, which involves twice as many moves.
fn siftup(&mut self, start: uint, mut pos: uint) {
unsafe {
let new = replace(self.data.get_mut(pos), zeroed());
let new = replace(&mut self.data[pos], zeroed());

while pos > start {
let parent = (pos - 1) >> 1;
if new > self.data[parent] {
let x = replace(self.data.get_mut(parent), zeroed());
ptr::write(self.data.get_mut(pos), x);
let x = replace(&mut self.data[parent], zeroed());
ptr::write(&mut self.data[pos], x);
pos = parent;
continue
}
break
}
ptr::write(self.data.get_mut(pos), new);
ptr::write(&mut self.data[pos], new);
}
}

fn siftdown_range(&mut self, mut pos: uint, end: uint) {
unsafe {
let start = pos;
let new = replace(self.data.get_mut(pos), zeroed());
let new = replace(&mut self.data[pos], zeroed());

let mut child = 2 * pos + 1;
while child < end {
let right = child + 1;
if right < end && !(self.data[child] > self.data[right]) {
child = right;
}
let x = replace(self.data.get_mut(child), zeroed());
ptr::write(self.data.get_mut(pos), x);
let x = replace(&mut self.data[child], zeroed());
ptr::write(&mut self.data[pos], x);
pos = child;
child = 2 * pos + 1;
}

ptr::write(self.data.get_mut(pos), new);
ptr::write(&mut self.data[pos], new);
self.siftup(start, pos);
}
}
Expand Down
33 changes: 17 additions & 16 deletions src/libcollections/ringbuf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ impl<T> Deque<T> for RingBuf<T> {

/// Returns a mutable reference to the first element in the `RingBuf`.
fn front_mut<'a>(&'a mut self) -> Option<&'a mut T> {
if self.nelts > 0 { Some(self.get_mut(0)) } else { None }
if self.nelts > 0 { Some(&mut self[0]) } else { None }
}

/// Returns a reference to the last element in the `RingBuf`.
Expand All @@ -69,13 +69,13 @@ impl<T> Deque<T> for RingBuf<T> {
/// Returns a mutable reference to the last element in the `RingBuf`.
fn back_mut<'a>(&'a mut self) -> Option<&'a mut T> {
let nelts = self.nelts;
if nelts > 0 { Some(self.get_mut(nelts - 1)) } else { None }
if nelts > 0 { Some(&mut self[nelts - 1]) } else { None }
}

/// Removes and returns the first element in the `RingBuf`, or `None` if it
/// is empty.
fn pop_front(&mut self) -> Option<T> {
let result = self.elts.get_mut(self.lo).take();
let result = self.elts[self.lo].take();
if result.is_some() {
self.lo = (self.lo + 1u) % self.elts.len();
self.nelts -= 1u;
Expand All @@ -91,7 +91,7 @@ impl<T> Deque<T> for RingBuf<T> {
if self.lo == 0u {
self.lo = self.elts.len() - 1u;
} else { self.lo -= 1u; }
*self.elts.get_mut(self.lo) = Some(t);
self.elts[self.lo] = Some(t);
self.nelts += 1u;
}
}
Expand All @@ -102,14 +102,14 @@ impl<T> MutableSeq<T> for RingBuf<T> {
grow(self.nelts, &mut self.lo, &mut self.elts);
}
let hi = self.raw_index(self.nelts);
*self.elts.get_mut(hi) = Some(t);
self.elts[hi] = Some(t);
self.nelts += 1u;
}
fn pop(&mut self) -> Option<T> {
if self.nelts > 0 {
self.nelts -= 1;
let hi = self.raw_index(self.nelts);
self.elts.get_mut(hi).take()
self.elts[hi].take()
} else {
None
}
Expand Down Expand Up @@ -140,6 +140,7 @@ impl<T> RingBuf<T> {
/// # Example
///
/// ```rust
/// # #![allow(deprecated)]
/// use std::collections::RingBuf;
///
/// let mut buf = RingBuf::new();
Expand All @@ -149,12 +150,9 @@ impl<T> RingBuf<T> {
/// *buf.get_mut(1) = 7;
/// assert_eq!(buf[1], 7);
/// ```
#[deprecated = "use indexing instead: `buf[index] = value`"]
pub fn get_mut<'a>(&'a mut self, i: uint) -> &'a mut T {
let idx = self.raw_index(i);
match *self.elts.get_mut(idx) {
None => panic!(),
Some(ref mut v) => v
}
&mut self[i]
}

/// Swaps elements at indices `i` and `j`.
Expand Down Expand Up @@ -466,13 +464,16 @@ impl<A> Index<uint, A> for RingBuf<A> {
}
}

// FIXME(#12825) Indexing will always try IndexMut first and that causes issues.
/*impl<A> IndexMut<uint, A> for RingBuf<A> {
impl<A> IndexMut<uint, A> for RingBuf<A> {
#[inline]
fn index_mut<'a>(&'a mut self, index: &uint) -> &'a mut A {
self.get_mut(*index)
fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut A {
let idx = self.raw_index(*i);
match *(&mut self.elts[idx]) {
None => panic!(),
Some(ref mut v) => v
}
}
}*/
}

impl<A> FromIterator<A> for RingBuf<A> {
fn from_iter<T: Iterator<A>>(iterator: T) -> RingBuf<A> {
Expand Down
11 changes: 5 additions & 6 deletions src/libcollections/smallintmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ impl<V> MutableMap<uint, V> for SmallIntMap<V> {
/// Returns a mutable reference to the value corresponding to the key.
fn find_mut<'a>(&'a mut self, key: &uint) -> Option<&'a mut V> {
if *key < self.v.len() {
match *self.v.get_mut(*key) {
match *self.v.index_mut(key) {
Some(ref mut value) => Some(value),
None => None
}
Expand All @@ -118,7 +118,7 @@ impl<V> MutableMap<uint, V> for SmallIntMap<V> {
if len <= key {
self.v.grow_fn(key - len + 1, |_| None);
}
*self.v.get_mut(key) = Some(value);
self.v[key] = Some(value);
!exists
}

Expand All @@ -145,7 +145,7 @@ impl<V> MutableMap<uint, V> for SmallIntMap<V> {
if *key >= self.v.len() {
return None;
}
self.v.get_mut(*key).take()
self.v[*key].take()
}
}

Expand Down Expand Up @@ -405,13 +405,12 @@ impl<V> Index<uint, V> for SmallIntMap<V> {
}
}

// FIXME(#12825) Indexing will always try IndexMut first and that causes issues.
/*impl<V> IndexMut<uint, V> for SmallIntMap<V> {
impl<V> IndexMut<uint, V> for SmallIntMap<V> {
#[inline]
fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut V {
self.find_mut(i).expect("key not present")
}
}*/
}

macro_rules! iterator {
(impl $name:ident -> $elem:ty, $($getter:ident),+) => {
Expand Down
8 changes: 4 additions & 4 deletions src/libcollections/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -692,17 +692,17 @@ pub trait StrAllocating: Str {
for (i, sc) in me.chars().enumerate() {

let mut current = i;
*dcol.get_mut(0) = current + 1;
dcol[0] = current + 1;

for (j, tc) in t.chars().enumerate() {

let next = dcol[j + 1];

if sc == tc {
*dcol.get_mut(j + 1) = current;
dcol[j + 1] = current;
} else {
*dcol.get_mut(j + 1) = cmp::min(current, next);
*dcol.get_mut(j + 1) = cmp::min(dcol[j + 1], dcol[j]) + 1;
dcol[j + 1] = cmp::min(current, next);
dcol[j + 1] = cmp::min(dcol[j + 1], dcol[j]) + 1;
}

current = next;
Expand Down
4 changes: 2 additions & 2 deletions src/libcollections/treemap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,12 +257,12 @@ impl<K: Ord, V> Index<K, V> for TreeMap<K, V> {
}
}

/*impl<K: Ord, V> IndexMut<K, V> for TreeMap<K, V> {
impl<K: Ord, V> IndexMut<K, V> for TreeMap<K, V> {
#[inline]
fn index_mut<'a>(&'a mut self, i: &K) -> &'a mut V {
self.find_mut(i).expect("no entry found for key")
}
}*/
}

impl<K: Ord, V> TreeMap<K, V> {
/// Creates an empty `TreeMap`.
Expand Down
5 changes: 2 additions & 3 deletions src/libcollections/trie.rs
Original file line number Diff line number Diff line change
Expand Up @@ -515,13 +515,12 @@ impl<T> Index<uint, T> for TrieMap<T> {
}
}

// FIXME(#12825) Indexing will always try IndexMut first and that causes issues.
/*impl<T> IndexMut<uint, T> for TrieMap<T> {
impl<T> IndexMut<uint, T> for TrieMap<T> {
#[inline]
fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut T {
self.find_mut(i).expect("key not present")
}
}*/
}

/// A set implemented as a radix trie.
///
Expand Down
Loading

1 comment on commit 1d35662

@alexcrichton
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r=sfackler

Please sign in to comment.