Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/project-model/src/workspace.rs20
1 files changed, 12 insertions, 8 deletions
diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs
index 5e06010c67..8b4d6d9941 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -1077,6 +1077,8 @@ fn cargo_to_crate_graph(
}
}
+ let mut delayed_dev_deps = vec![];
+
// Now add a dep edge from all targets of upstream to the lib
// target of downstream.
for pkg in cargo.packages() {
@@ -1092,20 +1094,18 @@ fn cargo_to_crate_graph(
}
// If the dependency is a dev-dependency with both crates being member libraries of
- // the workspace we discard the edge. The reason can be read up on in
+ // the workspace we delay adding the edge. The reason can be read up on in
// https://github.com/rust-lang/rust-analyzer/issues/14167
- // but in short, such an edge usually causes some form of cycle in the crate graph
- // wrt to unit tests. Something we cannot reasonable support.
+ // but in short, such an edge is able to cause some form of cycle in the crate graph
+ // for normal dependencies. If we do run into a cycle like this, we want to prefer
+ // the non dev-dependency edge, and so the easiest way to do that is by adding the
+ // dev-dependency edges last.
if dep.kind == DepKind::Dev
&& matches!(kind, TargetKind::Lib { .. })
&& cargo[dep.pkg].is_member
&& cargo[pkg].is_member
{
- tracing::warn!(
- "Discarding dev-dependency edge from library target `{}` to library target `{}` to prevent potential cycles",
- cargo[dep.pkg].name,
- cargo[pkg].name
- );
+ delayed_dev_deps.push((from, name.clone(), to));
continue;
}
@@ -1114,6 +1114,10 @@ fn cargo_to_crate_graph(
}
}
+ for (from, name, to) in delayed_dev_deps {
+ add_dep(crate_graph, from, name, to);
+ }
+
if has_private {
// If the user provided a path to rustc sources, we add all the rustc_private crates
// and create dependencies on them for the crates which opt-in to that