@@ -12,18 +12,24 @@ use smol_str::SmolStr;
12
12
13
13
#[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
14
14
pub enum CrateId {
15
+ Root ( usize ) ,
15
16
Crate ( usize ) ,
16
17
Stdlib ( usize ) ,
18
+ Dummy ,
17
19
}
18
20
19
21
impl CrateId {
20
22
pub fn dummy_id ( ) -> CrateId {
21
- CrateId :: Crate ( std :: usize :: MAX )
23
+ CrateId :: Dummy
22
24
}
23
25
24
26
pub fn is_stdlib ( & self ) -> bool {
25
27
matches ! ( self , CrateId :: Stdlib ( _) )
26
28
}
29
+
30
+ pub fn is_root ( & self ) -> bool {
31
+ matches ! ( self , CrateId :: Root ( _) )
32
+ }
27
33
}
28
34
29
35
#[ derive( Debug , Clone , PartialEq , Eq , Hash , Ord , PartialOrd ) ]
@@ -117,29 +123,73 @@ impl Dependency {
117
123
}
118
124
119
125
impl CrateGraph {
126
+ pub fn root_crate_id ( & self ) -> & CrateId {
127
+ self . arena
128
+ . keys ( )
129
+ . find ( |crate_id| crate_id. is_root ( ) )
130
+ . expect ( "ICE: A root crate should exist in the CrateGraph" )
131
+ }
132
+
120
133
pub fn add_crate_root ( & mut self , file_id : FileId ) -> CrateId {
121
- let mut roots_with_file_id =
122
- self . arena . iter ( ) . filter ( |( _, crate_data) | crate_data. root_file_id == file_id) ;
134
+ for ( crate_id, crate_data) in self . arena . iter ( ) {
135
+ if crate_id. is_root ( ) {
136
+ panic ! ( "ICE: Cannot add two crate roots to a graph - use `add_crate` instead" ) ;
137
+ }
123
138
124
- let next_file_id = roots_with_file_id . next ( ) ;
125
- if let Some ( file_id ) = next_file_id {
126
- return * file_id . 0 ;
139
+ if crate_data . root_file_id == file_id {
140
+ panic ! ( "ICE: This FileId was already added to the CrateGraph" )
141
+ }
127
142
}
128
143
129
144
let data = CrateData { root_file_id : file_id, dependencies : Vec :: new ( ) } ;
130
- let crate_id = CrateId :: Crate ( self . arena . len ( ) ) ;
145
+ let crate_id = CrateId :: Root ( self . arena . len ( ) ) ;
131
146
let prev = self . arena . insert ( crate_id, data) ;
132
147
assert ! ( prev. is_none( ) ) ;
133
148
crate_id
134
149
}
135
150
151
+ pub fn add_crate ( & mut self , file_id : FileId ) -> CrateId {
152
+ let mut crates_with_file_id = self
153
+ . arena
154
+ . iter ( )
155
+ . filter ( |( _, crate_data) | crate_data. root_file_id == file_id)
156
+ . peekable ( ) ;
157
+
158
+ let matching_id = crates_with_file_id. next ( ) ;
159
+ if crates_with_file_id. peek ( ) . is_some ( ) {
160
+ panic ! ( "ICE: Found multiple crates with the same FileId" ) ;
161
+ }
162
+
163
+ match matching_id {
164
+ Some ( ( crate_id @ CrateId :: Crate ( _) , _) ) => * crate_id,
165
+ Some ( ( CrateId :: Root ( _) , _) ) => {
166
+ panic ! ( "ICE: Tried to re-add the root crate as a regular crate" )
167
+ }
168
+ Some ( ( CrateId :: Stdlib ( _) , _) ) => {
169
+ panic ! ( "ICE: Tried to re-add the stdlib crate as a regular crate" )
170
+ }
171
+ Some ( ( CrateId :: Dummy , _) ) => {
172
+ panic ! ( "ICE: A dummy CrateId should not exist in the CrateGraph" )
173
+ }
174
+ None => {
175
+ let data = CrateData { root_file_id : file_id, dependencies : Vec :: new ( ) } ;
176
+ let crate_id = CrateId :: Crate ( self . arena . len ( ) ) ;
177
+ let prev = self . arena . insert ( crate_id, data) ;
178
+ assert ! ( prev. is_none( ) ) ;
179
+ crate_id
180
+ }
181
+ }
182
+ }
183
+
136
184
pub fn add_stdlib ( & mut self , file_id : FileId ) -> CrateId {
137
- let mut roots_with_file_id =
138
- self . arena . iter ( ) . filter ( |( _, crate_data) | crate_data. root_file_id == file_id) ;
185
+ for ( crate_id, crate_data) in self . arena . iter ( ) {
186
+ if crate_id. is_stdlib ( ) {
187
+ panic ! ( "ICE: Cannot add two stdlib crates to a graph - use `add_crate` instead" ) ;
188
+ }
139
189
140
- let next_file_id = roots_with_file_id . next ( ) ;
141
- if let Some ( file_id ) = next_file_id {
142
- return * file_id . 0 ;
190
+ if crate_data . root_file_id == file_id {
191
+ panic ! ( "ICE: This FileId was already added to the CrateGraph" )
192
+ }
143
193
}
144
194
145
195
let data = CrateData { root_file_id : file_id, dependencies : Vec :: new ( ) } ;
@@ -263,8 +313,8 @@ mod tests {
263
313
264
314
let mut graph = CrateGraph :: default ( ) ;
265
315
let crate1 = graph. add_crate_root ( file_ids[ 0 ] ) ;
266
- let crate2 = graph. add_crate_root ( file_ids[ 1 ] ) ;
267
- let crate3 = graph. add_crate_root ( file_ids[ 2 ] ) ;
316
+ let crate2 = graph. add_crate ( file_ids[ 1 ] ) ;
317
+ let crate3 = graph. add_crate ( file_ids[ 2 ] ) ;
268
318
269
319
assert ! ( graph. add_dep( crate1, "crate2" . parse( ) . unwrap( ) , crate2) . is_ok( ) ) ;
270
320
assert ! ( graph. add_dep( crate2, "crate3" . parse( ) . unwrap( ) , crate3) . is_ok( ) ) ;
@@ -279,8 +329,8 @@ mod tests {
279
329
let file_id_2 = file_ids[ 2 ] ;
280
330
let mut graph = CrateGraph :: default ( ) ;
281
331
let crate1 = graph. add_crate_root ( file_id_0) ;
282
- let crate2 = graph. add_crate_root ( file_id_1) ;
283
- let crate3 = graph. add_crate_root ( file_id_2) ;
332
+ let crate2 = graph. add_crate ( file_id_1) ;
333
+ let crate3 = graph. add_crate ( file_id_2) ;
284
334
assert ! ( graph. add_dep( crate1, "crate2" . parse( ) . unwrap( ) , crate2) . is_ok( ) ) ;
285
335
assert ! ( graph. add_dep( crate2, "crate3" . parse( ) . unwrap( ) , crate3) . is_ok( ) ) ;
286
336
}
@@ -292,11 +342,68 @@ mod tests {
292
342
let file_id_2 = file_ids[ 2 ] ;
293
343
let mut graph = CrateGraph :: default ( ) ;
294
344
let _crate1 = graph. add_crate_root ( file_id_0) ;
295
- let _crate2 = graph. add_crate_root ( file_id_1) ;
345
+ let _crate2 = graph. add_crate ( file_id_1) ;
296
346
297
347
// Adding the same file, so the crate should be the same.
298
- let crate3 = graph. add_crate_root ( file_id_2) ;
299
- let crate3_2 = graph. add_crate_root ( file_id_2) ;
348
+ let crate3 = graph. add_crate ( file_id_2) ;
349
+ let crate3_2 = graph. add_crate ( file_id_2) ;
300
350
assert_eq ! ( crate3, crate3_2) ;
301
351
}
352
+
353
+ #[ test]
354
+ #[ should_panic = "ICE: Cannot add two crate roots to a graph - use `add_crate` instead" ]
355
+ fn panics_if_adding_two_roots ( ) {
356
+ let file_ids = dummy_file_ids ( 2 ) ;
357
+ let mut graph = CrateGraph :: default ( ) ;
358
+ let _ = graph. add_crate_root ( file_ids[ 0 ] ) ;
359
+ let _ = graph. add_crate_root ( file_ids[ 1 ] ) ;
360
+ }
361
+
362
+ #[ test]
363
+ #[ should_panic = "ICE: This FileId was already added to the CrateGraph" ]
364
+ fn panics_if_adding_existing_file_as_root ( ) {
365
+ let file_ids = dummy_file_ids ( 1 ) ;
366
+ let mut graph = CrateGraph :: default ( ) ;
367
+ let file_id_0 = file_ids[ 0 ] ;
368
+ let _ = graph. add_crate ( file_id_0) ;
369
+ let _ = graph. add_crate_root ( file_id_0) ;
370
+ }
371
+
372
+ #[ test]
373
+ #[ should_panic = "ICE: Cannot add two stdlib crates to a graph - use `add_crate` instead" ]
374
+ fn panics_if_adding_two_stdlib ( ) {
375
+ let file_ids = dummy_file_ids ( 2 ) ;
376
+ let mut graph = CrateGraph :: default ( ) ;
377
+ let _ = graph. add_stdlib ( file_ids[ 0 ] ) ;
378
+ let _ = graph. add_stdlib ( file_ids[ 1 ] ) ;
379
+ }
380
+
381
+ #[ test]
382
+ #[ should_panic = "ICE: This FileId was already added to the CrateGraph" ]
383
+ fn panics_if_adding_existing_file_as_stdlib ( ) {
384
+ let file_ids = dummy_file_ids ( 1 ) ;
385
+ let mut graph = CrateGraph :: default ( ) ;
386
+ let file_id_0 = file_ids[ 0 ] ;
387
+ let _ = graph. add_crate ( file_id_0) ;
388
+ let _ = graph. add_stdlib ( file_id_0) ;
389
+ }
390
+
391
+ #[ test]
392
+ #[ should_panic = "ICE: Tried to re-add the root crate as a regular crate" ]
393
+ fn panics_if_adding_root_as_regular ( ) {
394
+ let file_ids = dummy_file_ids ( 1 ) ;
395
+ let mut graph = CrateGraph :: default ( ) ;
396
+ let file_id_0 = file_ids[ 0 ] ;
397
+ let _ = graph. add_crate_root ( file_id_0) ;
398
+ let _ = graph. add_crate ( file_id_0) ;
399
+ }
400
+ #[ test]
401
+ #[ should_panic = "ICE: Tried to re-add the stdlib crate as a regular crate" ]
402
+ fn panics_if_adding_stdlib_as_regular ( ) {
403
+ let file_ids = dummy_file_ids ( 1 ) ;
404
+ let mut graph = CrateGraph :: default ( ) ;
405
+ let file_id_0 = file_ids[ 0 ] ;
406
+ let _ = graph. add_stdlib ( file_id_0) ;
407
+ let _ = graph. add_crate ( file_id_0) ;
408
+ }
302
409
}
0 commit comments