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;
81use rustc_middle:: ty:: TyCtxt ;
92
103pub 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 `{:?}`:\n expected={:?}\n found={:?}" ,
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 `{:?}`:\n expected={:?}\n found={:?}" ,
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