|
1 |
| -use crate::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX}; |
2 |
| -use crate::hir::{self, intravisit, HirId, ItemLocalId}; |
3 |
| -use crate::hir::itemlikevisit::ItemLikeVisitor; |
4 |
| -use rustc_data_structures::fx::FxHashSet; |
| 1 | +use crate::hir::def_id::{DefId, DefIndex}; |
| 2 | +use crate::hir::{self, HirId}; |
5 | 3 | use rustc_data_structures::sync::{Lock, ParallelIterator, par_iter};
|
| 4 | +use std::collections::BTreeMap; |
6 | 5 |
|
7 | 6 | pub fn check_crate(hir_map: &hir::map::Map<'_>) {
|
8 | 7 | hir_map.dep_graph.assert_ignored();
|
9 | 8 |
|
10 | 9 | let errors = Lock::new(Vec::new());
|
11 | 10 |
|
12 |
| - par_iter(&hir_map.krate().modules).for_each(|(module_id, _)| { |
13 |
| - let local_def_id = hir_map.local_def_id(*module_id); |
14 |
| - hir_map.visit_item_likes_in_module(local_def_id, &mut OuterVisitor { |
15 |
| - hir_map, |
16 |
| - errors: &errors, |
17 |
| - }); |
| 11 | + par_iter(0..hir_map.map.len()).for_each(|owner| { |
| 12 | + let owner = DefIndex::from(owner); |
| 13 | + let local_map = &hir_map.map[owner]; |
| 14 | + |
| 15 | + // Collect the missing `ItemLocalId`s. |
| 16 | + let missing: Vec<_> = local_map |
| 17 | + .iter_enumerated() |
| 18 | + .filter(|(_, entry)| entry.is_none()) |
| 19 | + .map(|(local_id, _)| local_id) |
| 20 | + .collect(); |
| 21 | + |
| 22 | + if !missing.is_empty() { |
| 23 | + let present: BTreeMap<_, _> = local_map |
| 24 | + .iter_enumerated() |
| 25 | + .filter(|(_, entry)| entry.is_some()) |
| 26 | + .map(|(local_id, _)| { |
| 27 | + (local_id, hir_map.node_to_string(HirId { owner, local_id })) |
| 28 | + }) |
| 29 | + .collect(); |
| 30 | + |
| 31 | + errors.lock().push(format!( |
| 32 | + "{}:\n missing IDs = {:?}\n present IDs = {:#?}", |
| 33 | + hir_map.def_path(DefId::local(owner)).to_string_no_crate(), |
| 34 | + missing, |
| 35 | + present, |
| 36 | + )); |
| 37 | + } |
18 | 38 | });
|
19 | 39 |
|
20 | 40 | let errors = errors.into_inner();
|
21 |
| - |
22 | 41 | if !errors.is_empty() {
|
23 |
| - let message = errors |
24 |
| - .iter() |
25 |
| - .fold(String::new(), |s1, s2| s1 + "\n" + s2); |
26 |
| - bug!("{}", message); |
27 |
| - } |
28 |
| -} |
29 |
| - |
30 |
| -struct HirIdValidator<'a, 'hir> { |
31 |
| - hir_map: &'a hir::map::Map<'hir>, |
32 |
| - owner_def_index: Option<DefIndex>, |
33 |
| - hir_ids_seen: FxHashSet<ItemLocalId>, |
34 |
| - errors: &'a Lock<Vec<String>>, |
35 |
| -} |
36 |
| - |
37 |
| -struct OuterVisitor<'a, 'hir> { |
38 |
| - hir_map: &'a hir::map::Map<'hir>, |
39 |
| - errors: &'a Lock<Vec<String>>, |
40 |
| -} |
41 |
| - |
42 |
| -impl<'a, 'hir> OuterVisitor<'a, 'hir> { |
43 |
| - fn new_inner_visitor(&self, |
44 |
| - hir_map: &'a hir::map::Map<'hir>) |
45 |
| - -> HirIdValidator<'a, 'hir> { |
46 |
| - HirIdValidator { |
47 |
| - hir_map, |
48 |
| - owner_def_index: None, |
49 |
| - hir_ids_seen: Default::default(), |
50 |
| - errors: self.errors, |
51 |
| - } |
52 |
| - } |
53 |
| -} |
54 |
| - |
55 |
| -impl<'a, 'hir> ItemLikeVisitor<'hir> for OuterVisitor<'a, 'hir> { |
56 |
| - fn visit_item(&mut self, i: &'hir hir::Item) { |
57 |
| - let mut inner_visitor = self.new_inner_visitor(self.hir_map); |
58 |
| - inner_visitor.check(i.hir_id, |this| intravisit::walk_item(this, i)); |
59 |
| - } |
60 |
| - |
61 |
| - fn visit_trait_item(&mut self, i: &'hir hir::TraitItem) { |
62 |
| - let mut inner_visitor = self.new_inner_visitor(self.hir_map); |
63 |
| - inner_visitor.check(i.hir_id, |this| intravisit::walk_trait_item(this, i)); |
64 |
| - } |
65 |
| - |
66 |
| - fn visit_impl_item(&mut self, i: &'hir hir::ImplItem) { |
67 |
| - let mut inner_visitor = self.new_inner_visitor(self.hir_map); |
68 |
| - inner_visitor.check(i.hir_id, |this| intravisit::walk_impl_item(this, i)); |
69 |
| - } |
70 |
| -} |
71 |
| - |
72 |
| -impl<'a, 'hir> HirIdValidator<'a, 'hir> { |
73 |
| - #[cold] |
74 |
| - #[inline(never)] |
75 |
| - fn error(&self, f: impl FnOnce() -> String) { |
76 |
| - self.errors.lock().push(f()); |
77 |
| - } |
78 |
| - |
79 |
| - fn check<F: FnOnce(&mut HirIdValidator<'a, 'hir>)>(&mut self, |
80 |
| - hir_id: HirId, |
81 |
| - walk: F) { |
82 |
| - assert!(self.owner_def_index.is_none()); |
83 |
| - let owner_def_index = self.hir_map.local_def_id(hir_id).index; |
84 |
| - self.owner_def_index = Some(owner_def_index); |
85 |
| - walk(self); |
86 |
| - |
87 |
| - if owner_def_index == CRATE_DEF_INDEX { |
88 |
| - return; |
89 |
| - } |
90 |
| - |
91 |
| - // There's always at least one entry for the owning item itself |
92 |
| - let max = self.hir_ids_seen |
93 |
| - .iter() |
94 |
| - .map(|local_id| local_id.as_usize()) |
95 |
| - .max() |
96 |
| - .expect("owning item has no entry"); |
97 |
| - |
98 |
| - if max != self.hir_ids_seen.len() - 1 { |
99 |
| - // Collect the missing ItemLocalIds |
100 |
| - let missing: Vec<_> = (0 ..= max as u32) |
101 |
| - .filter(|&i| !self.hir_ids_seen.contains(&ItemLocalId::from_u32(i))) |
102 |
| - .collect(); |
103 |
| - |
104 |
| - // Try to map those to something more useful |
105 |
| - let mut missing_items = Vec::with_capacity(missing.len()); |
106 |
| - |
107 |
| - for local_id in missing { |
108 |
| - let hir_id = HirId { |
109 |
| - owner: owner_def_index, |
110 |
| - local_id: ItemLocalId::from_u32(local_id), |
111 |
| - }; |
112 |
| - |
113 |
| - trace!("missing hir id {:#?}", hir_id); |
114 |
| - |
115 |
| - missing_items.push(format!("[local_id: {}, node:{}]", |
116 |
| - local_id, |
117 |
| - self.hir_map.node_to_string(hir_id))); |
118 |
| - } |
119 |
| - self.error(|| format!( |
120 |
| - "ItemLocalIds not assigned densely in {}. \ |
121 |
| - Max ItemLocalId = {}, missing IDs = {:?}; seens IDs = {:?}", |
122 |
| - self.hir_map.def_path(DefId::local(owner_def_index)).to_string_no_crate(), |
123 |
| - max, |
124 |
| - missing_items, |
125 |
| - self.hir_ids_seen |
126 |
| - .iter() |
127 |
| - .map(|&local_id| HirId { |
128 |
| - owner: owner_def_index, |
129 |
| - local_id, |
130 |
| - }) |
131 |
| - .map(|h| format!("({:?} {})", h, self.hir_map.node_to_string(h))) |
132 |
| - .collect::<Vec<_>>())); |
133 |
| - } |
134 |
| - } |
135 |
| -} |
136 |
| - |
137 |
| -impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { |
138 |
| - |
139 |
| - fn nested_visit_map<'this>(&'this mut self) |
140 |
| - -> intravisit::NestedVisitorMap<'this, 'hir> { |
141 |
| - intravisit::NestedVisitorMap::OnlyBodies(self.hir_map) |
142 |
| - } |
143 |
| - |
144 |
| - fn visit_id(&mut self, hir_id: HirId) { |
145 |
| - let owner = self.owner_def_index.expect("no owner_def_index"); |
146 |
| - |
147 |
| - if hir_id == hir::DUMMY_HIR_ID { |
148 |
| - self.error(|| format!("HirIdValidator: HirId {:?} is invalid", |
149 |
| - self.hir_map.node_to_string(hir_id))); |
150 |
| - return; |
151 |
| - } |
152 |
| - |
153 |
| - if owner != hir_id.owner { |
154 |
| - self.error(|| format!( |
155 |
| - "HirIdValidator: The recorded owner of {} is {} instead of {}", |
156 |
| - self.hir_map.node_to_string(hir_id), |
157 |
| - self.hir_map.def_path(DefId::local(hir_id.owner)).to_string_no_crate(), |
158 |
| - self.hir_map.def_path(DefId::local(owner)).to_string_no_crate())); |
159 |
| - } |
160 |
| - |
161 |
| - self.hir_ids_seen.insert(hir_id.local_id); |
162 |
| - } |
163 |
| - |
164 |
| - fn visit_impl_item_ref(&mut self, _: &'hir hir::ImplItemRef) { |
165 |
| - // Explicitly do nothing here. ImplItemRefs contain hir::Visibility |
166 |
| - // values that actually belong to an ImplItem instead of the ItemKind::Impl |
167 |
| - // we are currently in. So for those it's correct that they have a |
168 |
| - // different owner. |
| 42 | + bug!("`ItemLocalId`s not assigned densely in:\n{}", errors.join("\n")); |
169 | 43 | }
|
170 | 44 | }
|
0 commit comments