1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
use ahash::{HashMap, HashMapExt};
/// To make the comparison easier, we assign a monotonically increasing unique id to all
/// unassigned generic parameters.
/// If the ids match, we know that the two sequences of unassigned generic parameters are equivalent.
pub(crate) struct UnassignedIdGenerator<'a> {
next_id: usize,
known_ids: HashMap<&'a str, usize>,
}
impl<'a> UnassignedIdGenerator<'a> {
pub(crate) fn new() -> Self {
Self {
next_id: 0,
known_ids: HashMap::new(),
}
}
pub(crate) fn id<'b>(&'b mut self, name: &'a str) -> usize
where
'a: 'b,
{
if let Some(id) = self.known_ids.get(&name) {
*id
} else {
let id = self.next_id;
self.next_id += 1;
self.known_ids.insert(name, id);
id
}
}
/// Iterate over the known ids, sorted by their assigned ID (i.e. insertion order).
///
/// This is important because `HashMap` iteration order is arbitrary,
/// and callers rely on pairing entries by position across two generators.
pub(crate) fn into_sorted_iter(self) -> impl Iterator<Item = (&'a str, usize)> {
let mut entries: Vec<_> = self.known_ids.into_iter().collect();
entries.sort_by_key(|(_, id)| *id);
entries.into_iter()
}
}