Skip to content

Interior mutability can cause inconsistency in collections #23327

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

Closed
apasel422 opened this issue Mar 13, 2015 · 4 comments · Fixed by #23342
Closed

Interior mutability can cause inconsistency in collections #23327

apasel422 opened this issue Mar 13, 2015 · 4 comments · Fixed by #23342

Comments

@apasel422
Copy link
Contributor

Collections that perform lookups based on a given property (e.g. a hash or an ordering) can be put into an inconsistent state when the property changes while its corresponding item is in the collection. This is normally not a problem, because such collections (at least those in std) do not provide mutable access to the type from which the property is derived (keys in the case of maps, items in the case of sets), but types with interior mutability can induce this behavior in safe code:

#[test]
fn test() {
    use std::cell::Cell;
    use std::collections::HashSet;
    use std::hash;

    #[derive(PartialEq)]
    struct Foo(Cell<u32>);

    impl Eq for Foo {}

    impl hash::Hash for Foo {
        fn hash<H: hash::Hasher>(&self, h: &mut H) { self.0.get().hash(h); }
    }

    let mut set = HashSet::new();
    set.insert(Foo(Cell::new(0)));
    set.insert(Foo(Cell::new(1)));

    for foo in &set {
        foo.0.set(2);
        break;
    }

    assert!(set.contains(&Foo(Cell::new(2))));
}

Output:

thread 'test' panicked at 'assertion failed: set.contains(&Foo(Cell::new(2)))'

This is obvious from the definition of interior mutability, but it's definitely a footgun. If the use of such keys cannot be prevented with the type system, the collections should at least document that the property must remain constant for the duration of the item's presence in the collection.

For example, Java's Map interface documentation contains the following note:

great care must be exercised if mutable objects are used as map keys. The behavior of a map is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is a key in the map.

@alexcrichton
Copy link
Member

This is a dupe of #13438, which was previously closed for reasons in the thread itself.

I believe the gist of the conversion was that yes, this can happen. Our implementations should ensure that this does not cause memory unsafety, but otherwise these sorts of "odd assertions" are ok to happen as this should be quite a rare occurrence anyway.

@apasel422
Copy link
Contributor Author

I still think the collection documentation needs to identify this problem.

On Friday, March 13, 2015, Alex Crichton [email protected] wrote:

Closed #23327 #23327.


Reply to this email directly or view it on GitHub
#23327 (comment).

@alexcrichton
Copy link
Member

Hm good point! I've added an appropriate tag.

@alexcrichton alexcrichton reopened this Mar 13, 2015
@apasel422
Copy link
Contributor Author

@alexcrichton I'm working on a patch to document this.

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 a pull request may close this issue.

2 participants