]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/src/docs/mutable_key_type.txt
Rollup merge of #101389 - lukaslueg:rcgetmutdocs, r=m-ou-se
[rust.git] / src / tools / clippy / src / docs / mutable_key_type.txt
1 ### What it does
2 Checks for sets/maps with mutable key types.
3
4 ### Why is this bad?
5 All of `HashMap`, `HashSet`, `BTreeMap` and
6 `BtreeSet` rely on either the hash or the order of keys be unchanging,
7 so having types with interior mutability is a bad idea.
8
9 ### Known problems
10
11 #### False Positives
12 It's correct to use a struct that contains interior mutability as a key, when its
13 implementation of `Hash` or `Ord` doesn't access any of the interior mutable types.
14 However, this lint is unable to recognize this, so it will often cause false positives in
15 theses cases.  The `bytes` crate is a great example of this.
16
17 #### False Negatives
18 For custom `struct`s/`enum`s, this lint is unable to check for interior mutability behind
19 indirection.  For example, `struct BadKey<'a>(&'a Cell<usize>)` will be seen as immutable
20 and cause a false negative if its implementation of `Hash`/`Ord` accesses the `Cell`.
21
22 This lint does check a few cases for indirection.  Firstly, using some standard library
23 types (`Option`, `Result`, `Box`, `Rc`, `Arc`, `Vec`, `VecDeque`, `BTreeMap` and
24 `BTreeSet`) directly as keys (e.g. in `HashMap<Box<Cell<usize>>, ()>`) **will** trigger the
25 lint, because the impls of `Hash`/`Ord` for these types directly call `Hash`/`Ord` on their
26 contained type.
27
28 Secondly, the implementations of `Hash` and `Ord` for raw pointers (`*const T` or `*mut T`)
29 apply only to the **address** of the contained value.  Therefore, interior mutability
30 behind raw pointers (e.g. in `HashSet<*mut Cell<usize>>`) can't impact the value of `Hash`
31 or `Ord`, and therefore will not trigger this link.  For more info, see issue
32 [#6745](https://github.com/rust-lang/rust-clippy/issues/6745).
33
34 ### Example
35 ```
36 use std::cmp::{PartialEq, Eq};
37 use std::collections::HashSet;
38 use std::hash::{Hash, Hasher};
39 use std::sync::atomic::AtomicUsize;
40
41 struct Bad(AtomicUsize);
42 impl PartialEq for Bad {
43     fn eq(&self, rhs: &Self) -> bool {
44          ..
45 ; unimplemented!();
46     }
47 }
48
49 impl Eq for Bad {}
50
51 impl Hash for Bad {
52     fn hash<H: Hasher>(&self, h: &mut H) {
53         ..
54 ; unimplemented!();
55     }
56 }
57
58 fn main() {
59     let _: HashSet<Bad> = HashSet::new();
60 }
61 ```