Skip to content

Commit 1a9b845

Browse files
committed
v3
1 parent 1d268fc commit 1a9b845

File tree

2 files changed

+49
-65
lines changed

2 files changed

+49
-65
lines changed

crates/base-db/src/input.rs

+44-64
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
99
use std::{fmt, mem, ops, panic::RefUnwindSafe, str::FromStr, sync};
1010

11-
use cfg::{CfgDiff, CfgOptions};
11+
use cfg::CfgOptions;
1212
use la_arena::{Arena, Idx};
1313
use rustc_hash::{FxHashMap, FxHashSet};
1414
use syntax::SmolStr;
@@ -330,7 +330,7 @@ pub struct CrateData {
330330

331331
impl CrateData {
332332
/// 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 {
334334
// This method has some obscure bits. These are mostly there to be compliant with
335335
// some patches. References to the patches are given.
336336
if self.root_file_id != other.root_file_id {
@@ -353,69 +353,36 @@ impl CrateData {
353353
return false;
354354
}
355355

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" {
405364
return false;
406365
}
407-
408-
anx = itself.next();
409-
bnx = otself.next();
410366
}
411367
}
412-
}
368+
_ => return false,
369+
};
413370

414371
if self.env != other.env {
415372
return false;
416373
}
417374

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)
419386
}
420387
}
421388

@@ -446,7 +413,7 @@ impl Env {
446413
}
447414
}
448415

449-
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
416+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
450417
pub enum DependencyKind {
451418
Normal,
452419
Dev,
@@ -480,8 +447,8 @@ impl Dependency {
480447
self.prelude
481448
}
482449

483-
pub fn kind(&self) -> &DependencyKind {
484-
&self.kind
450+
pub fn kind(&self) -> DependencyKind {
451+
self.kind
485452
}
486453
}
487454

@@ -692,14 +659,27 @@ impl CrateGraph {
692659
crate_data.dependencies.iter_mut().for_each(|dep| dep.crate_id = id_map[&dep.crate_id]);
693660
crate_data.dependencies.sort_by_key(|dep| dep.crate_id);
694661
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 { .. }) => {
697669
// 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+
}
699673
}
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,
702681
}
682+
703683
None
704684
});
705685

crates/cfg/src/lib.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ mod dnf;
77
#[cfg(test)]
88
mod tests;
99

10-
use std::fmt;
10+
use std::{collections::HashSet, fmt};
1111

1212
use rustc_hash::FxHashSet;
1313
use tt::SmolStr;
@@ -58,6 +58,10 @@ impl CfgOptions {
5858
self.enabled.insert(CfgAtom::KeyValue { key, value });
5959
}
6060

61+
pub fn diff<'a>(&'a self, other: &'a CfgOptions) -> HashSet<&CfgAtom> {
62+
self.enabled.difference(&other.enabled).collect()
63+
}
64+
6165
pub fn apply_diff(&mut self, diff: CfgDiff) {
6266
for atom in diff.enable {
6367
self.enabled.insert(atom);

0 commit comments

Comments
 (0)