about summary refs log tree commit diff
diff options
context:
space:
mode:
-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 5e06010c678..8b4d6d99414 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