Skip to content

The clear method in std::oldmap::HashMap now takes &mut self - and this leads to illegal borrow unless pure errors #4870

Closed

Description

@Dretch

std::oldmap::HashMap now takes &mut self:

impl<K: Eq IterBytes Hash, V> T<K, V>: Mutable {
    fn clear(&mut self) {
        self.count = 0u;
        self.chains = chains(initial_capacity);
    }
}

I am finding this rather awkward because HashMap also has methods like insert and remove that do not take mutable self, but are also non-pure. What this means is that I can't make my field of type std::oldmap::HashMap mut, because then rustc complains about illegal borrow unless pure when calling insert/remove, and I can't make it non-mut because then I can't call clear on it...

Does it make sense for HashMap to implement Mutable? AFAICT HashMap doesn't need mutable self because it mutates by changing its internal fields, not by creating a new instance of itself.

Activity

  1. Dretch commented on Feb 11, 2013

    @Dretch
    ContributorAuthor

    Hopefully this clarifies why I think HashMap.clear taking &mut self is undesirable:

    This is a program that, before the change, compiled and ran:

    extern mod std;
    
    struct MyStruct {
        map: std::oldmap::HashMap<int, int>
    }
    
    fn f(ms: &MyStruct) {
        ms.map.insert(1, 2);
        ms.map.clear();
    }
    
    fn main() {}
    

    Since the change, rustc now complains due to the illegal borrow it contains calling ms.map.clear():

    bad-hashmap-clear.rs:10:8: 10:14 error: illegal borrow: creating mutable alias to immutable field
    bad-hashmap-clear.rs:10         ms.map.clear();
                                    ^~~~~~
    

    I tried to fix the issue by making map a mut field... but that caused rustc to complain about an illegal borrow calling ms.map.insert(...):

    bad-hashmap-clear.rs:9:8: 9:14 error: illegal borrow unless pure: creating immutable alias to mutable field
    bad-hashmap-clear.rs:9         ms.map.insert(1, 2);
                                   ^~~~~~
    bad-hashmap-clear.rs:9:8: 9:28 note: impure due to access to impure function
    bad-hashmap-clear.rs:9         ms.map.insert(1, 2);
                                   ^~~~~~~~~~~~~~~~~~~~
    

    I can't see any way to avoid both illegal borrow errors at the same time.

    Does this make sense to anyone else? @thestinger ?

  2. thestinger commented on Feb 11, 2013

    @thestinger
    Contributor

    @Dretch: In order to mutate an object, the owner needs to be a mutable variable or @mut. You have to pass it into the function with &mut self, because using & means the object is immutable.

    The use case for mutable fields is hidden internal state that cannot be observed externally like locks. Using them the way HashMap does is misuse of the feature. Mutable fields are currently being removed from the language because in addition to being widely misunderstood, they don't play well with the improved borrow checking semantics.

    The methods that don't use explicit self are unsound and should be updated, but it's a lot of work to update the calling code. As a whole std::oldmap is going to be removed as soon as possible so I doubt updating it is actually going to happen - it will be easier to just port code over to core::hashmap which is sane, sendable, faster and has a better API.

  3. Dretch commented on Feb 11, 2013

    @Dretch
    ContributorAuthor

    If I understand you correctly, then in future idiomatic rust, methods will have to expose in their type signature whether or not they mutate the externally-observable-internal-state of the self value?

  4. thestinger commented on Feb 11, 2013

    @thestinger
    Contributor

    @Dretch: They will always be able to use unsafe to break the rules like that. I can't think of very many actual use cases though other than locks - which already have to use unsafe code.

  5. catamorphism commented on Feb 14, 2013

    @catamorphism
    Contributor

    Closing since oldmap is going to be removed. If I misunderstood something, please let me know!

  6. added a commit that references this issue on Aug 13, 2024
    56fe166
  7. added a commit that references this issue on Mar 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions