8
8
9
9
use std:: { fmt, mem, ops, panic:: RefUnwindSafe , str:: FromStr , sync} ;
10
10
11
- use cfg:: { CfgDiff , CfgOptions } ;
11
+ use cfg:: CfgOptions ;
12
12
use la_arena:: { Arena , Idx } ;
13
13
use rustc_hash:: { FxHashMap , FxHashSet } ;
14
14
use syntax:: SmolStr ;
@@ -330,7 +330,7 @@ pub struct CrateData {
330
330
331
331
impl CrateData {
332
332
/// Check if [`other`] is almost equal to [`self`] ignoring `CrateOrigin` value.
333
- pub fn eq_ignoring_origin ( & self , other : & CrateData ) -> bool {
333
+ pub fn eq_ignoring_origin_and_deps ( & self , other : & CrateData , ignore_dev_deps : bool ) -> bool {
334
334
// This method has some obscure bits. These are mostly there to be compliant with
335
335
// some patches. References to the patches are given.
336
336
if self . root_file_id != other. root_file_id {
@@ -353,69 +353,36 @@ impl CrateData {
353
353
return false ;
354
354
}
355
355
356
- let mut opts = self . cfg_options . clone ( ) ;
357
- opts. apply_diff (
358
- CfgDiff :: new ( vec ! [ ] , other. cfg_options . clone ( ) . into_iter ( ) . collect ( ) )
359
- . expect ( "CfgOptions were expected to contain no duplicates." ) ,
360
- ) ;
361
-
362
- let mut cfgs = opts. into_iter ( ) ;
363
- if let Some ( cfg) = cfgs. next ( ) {
364
- // Don't care if rust_analyzer CfgAtom is the only cfg in the difference set of self's and other's cfgs.
365
- // https://github.com/rust-lang/rust-analyzer/blob/0840038f02daec6ba3238f05d8caa037d28701a0/crates/project-model/src/workspace.rs#L894
366
- if cfgs. next ( ) . is_some ( ) || cfg. to_string ( ) != "rust_analyzer" {
367
- return false ;
368
- }
369
- }
370
-
371
- let mut itself = self . dependencies . iter ( ) ;
372
- let mut otself = other. dependencies . iter ( ) ;
373
- let ( mut anx, mut bnx) = ( itself. next ( ) , otself. next ( ) ) ;
374
- loop {
375
- match ( anx, bnx) {
376
- ( None , None ) => {
377
- break ;
378
- }
379
- ( None , Some ( b) ) => {
380
- if b. kind != DependencyKind :: Normal {
381
- bnx = otself. next ( ) ;
382
- } else {
383
- break ;
384
- }
385
- }
386
- ( Some ( a) , None ) => {
387
- if a. kind != DependencyKind :: Normal {
388
- anx = itself. next ( ) ;
389
- } else {
390
- break ;
391
- }
392
- }
393
- ( Some ( a) , Some ( b) ) => {
394
- if a. kind != DependencyKind :: Normal {
395
- anx = itself. next ( ) ;
396
- continue ;
397
- }
398
-
399
- if b. kind != DependencyKind :: Normal {
400
- bnx = otself. next ( ) ;
401
- continue ;
402
- }
403
-
404
- if a != b {
356
+ let mut opts = self . cfg_options . diff ( & other. cfg_options ) . into_iter ( ) ;
357
+ match opts. len ( ) {
358
+ 0 => ( ) ,
359
+ 1 => {
360
+ // Don't care if rust_analyzer CfgAtom is the only cfg in the difference set of self's and other's cfgs.
361
+ // https://github.com/rust-lang/rust-analyzer/blob/0840038f02daec6ba3238f05d8caa037d28701a0/crates/project-model/src/workspace.rs#L894
362
+ if let Some ( cfg) = opts. next ( ) {
363
+ if cfg. to_string ( ) != "rust_analyzer" {
405
364
return false ;
406
365
}
407
-
408
- anx = itself. next ( ) ;
409
- bnx = otself. next ( ) ;
410
366
}
411
367
}
412
- }
368
+ _ => return false ,
369
+ } ;
413
370
414
371
if self . env != other. env {
415
372
return false ;
416
373
}
417
374
418
- true
375
+ let slf_deps = self . dependencies . iter ( ) ;
376
+ let other_deps = other. dependencies . iter ( ) ;
377
+
378
+ if ignore_dev_deps {
379
+ slf_deps
380
+ . clone ( )
381
+ . filter ( |it| it. kind == DependencyKind :: Normal )
382
+ . eq ( other_deps. clone ( ) . filter ( |it| it. kind == DependencyKind :: Normal ) ) ;
383
+ }
384
+
385
+ slf_deps. eq ( other_deps)
419
386
}
420
387
}
421
388
@@ -446,7 +413,7 @@ impl Env {
446
413
}
447
414
}
448
415
449
- #[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
416
+ #[ derive( Debug , Copy , Clone , PartialEq , Eq , Hash ) ]
450
417
pub enum DependencyKind {
451
418
Normal ,
452
419
Dev ,
@@ -480,8 +447,8 @@ impl Dependency {
480
447
self . prelude
481
448
}
482
449
483
- pub fn kind ( & self ) -> & DependencyKind {
484
- & self . kind
450
+ pub fn kind ( & self ) -> DependencyKind {
451
+ self . kind
485
452
}
486
453
}
487
454
@@ -692,14 +659,27 @@ impl CrateGraph {
692
659
crate_data. dependencies . iter_mut ( ) . for_each ( |dep| dep. crate_id = id_map[ & dep. crate_id ] ) ;
693
660
crate_data. dependencies . sort_by_key ( |dep| dep. crate_id ) ;
694
661
let res = self . arena . iter ( ) . find_map ( |( id, data) | {
695
- if data. eq_ignoring_origin ( crate_data) {
696
- if data. origin . is_lib ( ) && crate_data. origin . is_local ( ) {
662
+ match ( & data. origin , & crate_data. origin ) {
663
+ ( a, b) if a == b => {
664
+ if data. eq_ignoring_origin_and_deps ( & crate_data, false ) {
665
+ return Some ( ( id, false ) ) ;
666
+ }
667
+ }
668
+ ( CrateOrigin :: Local { .. } , CrateOrigin :: Library { .. } ) => {
697
669
// See #15656 for a relevant example.
698
- return Some ( ( id, true ) ) ;
670
+ if data. eq_ignoring_origin_and_deps ( & crate_data, true ) {
671
+ return Some ( ( id, false ) ) ;
672
+ }
699
673
}
700
-
701
- return Some ( ( id, false ) ) ;
674
+ ( CrateOrigin :: Library { .. } , CrateOrigin :: Local { .. } ) => {
675
+ // See #15656 for a relevant example.
676
+ if data. eq_ignoring_origin_and_deps ( & crate_data, true ) {
677
+ return Some ( ( id, true ) ) ;
678
+ }
679
+ }
680
+ ( _, _) => return None ,
702
681
}
682
+
703
683
None
704
684
} ) ;
705
685
0 commit comments