Skip to content

Commit ba331c9

Browse files
committed
Add proper cfgs for struct HirIdValidator used only with debug assertions
1 parent 2064c19 commit ba331c9

File tree

1 file changed

+132
-117
lines changed

1 file changed

+132
-117
lines changed
+132-117
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,3 @@
1-
use rustc_data_structures::sync::Lock;
2-
use rustc_hir as hir;
3-
use rustc_hir::def_id::LocalDefId;
4-
use rustc_hir::intravisit;
5-
use rustc_hir::{HirId, ItemLocalId};
6-
use rustc_index::bit_set::GrowableBitSet;
7-
use rustc_middle::hir::nested_filter;
81
use rustc_middle::ty::TyCtxt;
92

103
pub fn check_crate(tcx: TyCtxt<'_>) {
@@ -13,7 +6,20 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
136
}
147

158
#[cfg(debug_assertions)]
16-
{
9+
validator::check_crate(tcx);
10+
}
11+
12+
#[cfg(debug_assertions)]
13+
mod validator {
14+
use rustc_data_structures::sync::Lock;
15+
use rustc_hir as hir;
16+
use rustc_hir::def_id::LocalDefId;
17+
use rustc_hir::{intravisit, HirId, ItemLocalId};
18+
use rustc_index::bit_set::GrowableBitSet;
19+
use rustc_middle::hir::nested_filter;
20+
use rustc_middle::ty::TyCtxt;
21+
22+
pub fn check_crate(tcx: TyCtxt<'_>) {
1723
let errors = Lock::new(Vec::new());
1824

1925
tcx.hir().par_for_each_module(|module_id| {
@@ -34,143 +40,152 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
3440
tcx.dcx().delayed_bug(message);
3541
}
3642
}
37-
}
38-
39-
struct HirIdValidator<'a, 'hir> {
40-
tcx: TyCtxt<'hir>,
41-
owner: Option<hir::OwnerId>,
42-
hir_ids_seen: GrowableBitSet<ItemLocalId>,
43-
errors: &'a Lock<Vec<String>>,
44-
}
45-
46-
impl<'a, 'hir> HirIdValidator<'a, 'hir> {
47-
fn new_visitor(&self, tcx: TyCtxt<'hir>) -> HirIdValidator<'a, 'hir> {
48-
HirIdValidator { tcx, owner: None, hir_ids_seen: Default::default(), errors: self.errors }
49-
}
5043

51-
#[cold]
52-
#[inline(never)]
53-
fn error(&self, f: impl FnOnce() -> String) {
54-
self.errors.lock().push(f());
44+
struct HirIdValidator<'a, 'hir> {
45+
tcx: TyCtxt<'hir>,
46+
owner: Option<hir::OwnerId>,
47+
hir_ids_seen: GrowableBitSet<ItemLocalId>,
48+
errors: &'a Lock<Vec<String>>,
5549
}
5650

57-
fn check<F: FnOnce(&mut HirIdValidator<'a, 'hir>)>(&mut self, owner: hir::OwnerId, walk: F) {
58-
assert!(self.owner.is_none());
59-
self.owner = Some(owner);
60-
walk(self);
51+
impl<'a, 'hir> HirIdValidator<'a, 'hir> {
52+
fn new_visitor(&self, tcx: TyCtxt<'hir>) -> HirIdValidator<'a, 'hir> {
53+
HirIdValidator {
54+
tcx,
55+
owner: None,
56+
hir_ids_seen: Default::default(),
57+
errors: self.errors,
58+
}
59+
}
6160

62-
if owner == hir::CRATE_OWNER_ID {
63-
return;
61+
#[cold]
62+
#[inline(never)]
63+
fn error(&self, f: impl FnOnce() -> String) {
64+
self.errors.lock().push(f());
6465
}
6566

66-
// There's always at least one entry for the owning item itself
67-
let max = self
68-
.hir_ids_seen
69-
.iter()
70-
.map(|local_id| local_id.as_usize())
71-
.max()
72-
.expect("owning item has no entry");
73-
74-
if max != self.hir_ids_seen.len() - 1 {
75-
let hir = self.tcx.hir();
76-
let pretty_owner = hir.def_path(owner.def_id).to_string_no_crate_verbose();
77-
78-
let missing_items: Vec<_> = (0..=max as u32)
79-
.map(|i| ItemLocalId::from_u32(i))
80-
.filter(|&local_id| !self.hir_ids_seen.contains(local_id))
81-
.map(|local_id| hir.node_to_string(HirId { owner, local_id }))
82-
.collect();
83-
84-
let seen_items: Vec<_> = self
67+
fn check<F: FnOnce(&mut HirIdValidator<'a, 'hir>)>(
68+
&mut self,
69+
owner: hir::OwnerId,
70+
walk: F,
71+
) {
72+
assert!(self.owner.is_none());
73+
self.owner = Some(owner);
74+
walk(self);
75+
76+
if owner == hir::CRATE_OWNER_ID {
77+
return;
78+
}
79+
80+
// There's always at least one entry for the owning item itself
81+
let max = self
8582
.hir_ids_seen
8683
.iter()
87-
.map(|local_id| hir.node_to_string(HirId { owner, local_id }))
88-
.collect();
89-
90-
self.error(|| {
84+
.map(|local_id| local_id.as_usize())
85+
.max()
86+
.expect("owning item has no entry");
87+
88+
if max != self.hir_ids_seen.len() - 1 {
89+
let hir = self.tcx.hir();
90+
let pretty_owner = hir.def_path(owner.def_id).to_string_no_crate_verbose();
91+
92+
let missing_items: Vec<_> = (0..=max as u32)
93+
.map(|i| ItemLocalId::from_u32(i))
94+
.filter(|&local_id| !self.hir_ids_seen.contains(local_id))
95+
.map(|local_id| hir.node_to_string(HirId { owner, local_id }))
96+
.collect();
97+
98+
let seen_items: Vec<_> = self
99+
.hir_ids_seen
100+
.iter()
101+
.map(|local_id| hir.node_to_string(HirId { owner, local_id }))
102+
.collect();
103+
104+
self.error(|| {
91105
format!(
92106
"ItemLocalIds not assigned densely in {pretty_owner}. \
93107
Max ItemLocalId = {max}, missing IDs = {missing_items:#?}; seen IDs = {seen_items:#?}"
94108
)
95109
});
110+
}
96111
}
97-
}
98112

99-
fn check_nested_id(&mut self, id: LocalDefId) {
100-
let Some(owner) = self.owner else { return };
101-
let def_parent = self.tcx.local_parent(id);
102-
let def_parent_hir_id = self.tcx.local_def_id_to_hir_id(def_parent);
103-
if def_parent_hir_id.owner != owner {
104-
self.error(|| {
105-
format!(
106-
"inconsistent Def parent at `{:?}` for `{:?}`:\nexpected={:?}\nfound={:?}",
107-
self.tcx.def_span(id),
108-
id,
109-
owner,
110-
def_parent_hir_id
111-
)
112-
});
113+
fn check_nested_id(&mut self, id: LocalDefId) {
114+
let Some(owner) = self.owner else { return };
115+
let def_parent = self.tcx.local_parent(id);
116+
let def_parent_hir_id = self.tcx.local_def_id_to_hir_id(def_parent);
117+
if def_parent_hir_id.owner != owner {
118+
self.error(|| {
119+
format!(
120+
"inconsistent Def parent at `{:?}` for `{:?}`:\nexpected={:?}\nfound={:?}",
121+
self.tcx.def_span(id),
122+
id,
123+
owner,
124+
def_parent_hir_id
125+
)
126+
});
127+
}
113128
}
114129
}
115-
}
116-
117-
impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> {
118-
type NestedFilter = nested_filter::OnlyBodies;
119-
120-
fn nested_visit_map(&mut self) -> Self::Map {
121-
self.tcx.hir()
122-
}
123130

124-
fn visit_nested_item(&mut self, id: hir::ItemId) {
125-
self.check_nested_id(id.owner_id.def_id);
126-
}
131+
impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> {
132+
type NestedFilter = nested_filter::OnlyBodies;
127133

128-
fn visit_nested_trait_item(&mut self, id: hir::TraitItemId) {
129-
self.check_nested_id(id.owner_id.def_id);
130-
}
134+
fn nested_visit_map(&mut self) -> Self::Map {
135+
self.tcx.hir()
136+
}
131137

132-
fn visit_nested_impl_item(&mut self, id: hir::ImplItemId) {
133-
self.check_nested_id(id.owner_id.def_id);
134-
}
138+
fn visit_nested_item(&mut self, id: hir::ItemId) {
139+
self.check_nested_id(id.owner_id.def_id);
140+
}
135141

136-
fn visit_nested_foreign_item(&mut self, id: hir::ForeignItemId) {
137-
self.check_nested_id(id.owner_id.def_id);
138-
}
142+
fn visit_nested_trait_item(&mut self, id: hir::TraitItemId) {
143+
self.check_nested_id(id.owner_id.def_id);
144+
}
139145

140-
fn visit_item(&mut self, i: &'hir hir::Item<'hir>) {
141-
let mut inner_visitor = self.new_visitor(self.tcx);
142-
inner_visitor.check(i.owner_id, |this| intravisit::walk_item(this, i));
143-
}
146+
fn visit_nested_impl_item(&mut self, id: hir::ImplItemId) {
147+
self.check_nested_id(id.owner_id.def_id);
148+
}
144149

145-
fn visit_id(&mut self, hir_id: HirId) {
146-
let owner = self.owner.expect("no owner");
150+
fn visit_nested_foreign_item(&mut self, id: hir::ForeignItemId) {
151+
self.check_nested_id(id.owner_id.def_id);
152+
}
147153

148-
if owner != hir_id.owner {
149-
self.error(|| {
150-
format!(
151-
"HirIdValidator: The recorded owner of {} is {} instead of {}",
152-
self.tcx.hir().node_to_string(hir_id),
153-
self.tcx.hir().def_path(hir_id.owner.def_id).to_string_no_crate_verbose(),
154-
self.tcx.hir().def_path(owner.def_id).to_string_no_crate_verbose()
155-
)
156-
});
154+
fn visit_item(&mut self, i: &'hir hir::Item<'hir>) {
155+
let mut inner_visitor = self.new_visitor(self.tcx);
156+
inner_visitor.check(i.owner_id, |this| intravisit::walk_item(this, i));
157157
}
158158

159-
self.hir_ids_seen.insert(hir_id.local_id);
160-
}
159+
fn visit_id(&mut self, hir_id: HirId) {
160+
let owner = self.owner.expect("no owner");
161+
162+
if owner != hir_id.owner {
163+
self.error(|| {
164+
format!(
165+
"HirIdValidator: The recorded owner of {} is {} instead of {}",
166+
self.tcx.hir().node_to_string(hir_id),
167+
self.tcx.hir().def_path(hir_id.owner.def_id).to_string_no_crate_verbose(),
168+
self.tcx.hir().def_path(owner.def_id).to_string_no_crate_verbose()
169+
)
170+
});
171+
}
172+
173+
self.hir_ids_seen.insert(hir_id.local_id);
174+
}
161175

162-
fn visit_foreign_item(&mut self, i: &'hir hir::ForeignItem<'hir>) {
163-
let mut inner_visitor = self.new_visitor(self.tcx);
164-
inner_visitor.check(i.owner_id, |this| intravisit::walk_foreign_item(this, i));
165-
}
176+
fn visit_foreign_item(&mut self, i: &'hir hir::ForeignItem<'hir>) {
177+
let mut inner_visitor = self.new_visitor(self.tcx);
178+
inner_visitor.check(i.owner_id, |this| intravisit::walk_foreign_item(this, i));
179+
}
166180

167-
fn visit_trait_item(&mut self, i: &'hir hir::TraitItem<'hir>) {
168-
let mut inner_visitor = self.new_visitor(self.tcx);
169-
inner_visitor.check(i.owner_id, |this| intravisit::walk_trait_item(this, i));
170-
}
181+
fn visit_trait_item(&mut self, i: &'hir hir::TraitItem<'hir>) {
182+
let mut inner_visitor = self.new_visitor(self.tcx);
183+
inner_visitor.check(i.owner_id, |this| intravisit::walk_trait_item(this, i));
184+
}
171185

172-
fn visit_impl_item(&mut self, i: &'hir hir::ImplItem<'hir>) {
173-
let mut inner_visitor = self.new_visitor(self.tcx);
174-
inner_visitor.check(i.owner_id, |this| intravisit::walk_impl_item(this, i));
186+
fn visit_impl_item(&mut self, i: &'hir hir::ImplItem<'hir>) {
187+
let mut inner_visitor = self.new_visitor(self.tcx);
188+
inner_visitor.check(i.owner_id, |this| intravisit::walk_impl_item(this, i));
189+
}
175190
}
176191
}

0 commit comments

Comments
 (0)