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

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

Closed
Dretch opened this issue Feb 10, 2013 · 5 comments

Comments

@Dretch
Copy link
Contributor

Dretch commented Feb 10, 2013

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.

@Dretch
Copy link
Contributor Author

Dretch commented Feb 11, 2013

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 ?

@thestinger
Copy link
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.

@Dretch
Copy link
Contributor Author

Dretch commented Feb 11, 2013

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?

@thestinger
Copy link
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.

@catamorphism
Copy link
Contributor

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

lnicola pushed a commit to lnicola/rust that referenced this issue Aug 13, 2024
docs: add msvc note to manual

Added note for Windows users to have the latest MSVC to minimize setup issues.

Closes rust-lang#4870
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

No branches or pull requests

3 participants