Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement entry interface with or_insert and tests succesfully #2

Merged
merged 9 commits into from
Sep 9, 2021

Conversation

gedkott
Copy link
Owner

@gedkott gedkott commented Sep 8, 2021

No description provided.

src/lib.rs Outdated
@@ -73,6 +73,38 @@ impl<K: std::hash::Hash + PartialEq, V> HashTable<K, V> {
}
}

pub fn insert_mut(&mut self, k: K, v: V) -> &mut V {
Copy link
Owner Author

Choose a reason for hiding this comment

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

Completely duplicates insert + reads the value back out of the table at the end just to get a mutable reference back...

Copy link
Owner Author

Choose a reason for hiding this comment

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

Fixed.

@@ -84,9 +116,45 @@ impl<K: std::hash::Hash + PartialEq, V> HashTable<K, V> {
None
}

pub fn get_mut(&mut self, k: &K) -> Option<&mut V> {
Copy link
Owner Author

Choose a reason for hiding this comment

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

Duplicates get just to get a mut reference which feels weird...

Copy link
Owner Author

Choose a reason for hiding this comment

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

I think this is how its meant to be. I am 85% confident.

src/lib.rs Outdated
}
}

self.buckets = new_buckets;
}

// then add the new item (give up ownership late so we can easily access the value for returning)
let hash = self.hasher.hash(&k);
Copy link
Owner Author

Choose a reason for hiding this comment

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

hash is computed twice for calls from insert (insert_mut is not necessary anymore either; certainly not as a pub fn).

Copy link
Owner Author

Choose a reason for hiding this comment

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

Fixed.

src/lib.rs Outdated
}
match to_remove {
Some(index) => {
let (_, ov) = self.buckets[bucket_index].swap_remove(index);
Copy link
Owner Author

Choose a reason for hiding this comment

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

Do we need to do it like this? Can we just swap the key-value pairs entirely and just skip any of _insert?

Copy link
Owner Author

Choose a reason for hiding this comment

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

Yes and done.

@gedkott gedkott merged commit ef12623 into master Sep 9, 2021
@gedkott gedkott deleted the entry branch September 9, 2021 04:02
pub fn capacity(&self) -> usize {
self.buckets.len()
}

pub fn entry(&mut self, k: K) -> Entry<'_, K, V, H> {
if self.get_mut(&k).is_some() {
Copy link
Owner Author

Choose a reason for hiding this comment

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

It is very silly that I call get_mut twice: once here to check which entry type to return and then again when borrowing the value during a call to entry's or_insert. I tried borrowing the value mutably for occupied entries and for vacant entries, borrowing self. I thought that since they were divergent paths this should have been fine, but it wasn't and the compiler was unhappy:

pub enum Entry<'a, K, V, H>
where
    K: Hash,
    H: SimpleHasher<K>,
{
    Occupied {
        v: &'a mut V,
    },
    Vacant {
        ht: &'a mut HashTable<K, V, H>,
        k: K,
    },
}

error[E0499]: cannot borrow `*self` as mutable more than once at a time
   --> src/lib.rs:180:40
    |
175 |     pub fn entry(&mut self, k: K) -> Entry<'_, K, V, H> {
    |                  - let's call the lifetime of this reference `'1`
176 |         let v = self.get_mut(&k);
    |                 ---- first mutable borrow occurs here
177 |         if let Some(ov) = v {
178 |             return Entry::Occupied { v: ov };
    |                    ------------------------- returning this value requires that `*self` is borrowed for `'1`
179 |         } else {
180 |             return Entry::Vacant { ht: self, k };
    |                                        ^^^^ second mutable borrow occurs here

I think this is related to the non lexical lifetime issues since my exact case is provided here: rust-lang/rust#21906 (comment)
For now, we will just need to call get_mut twice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant