@@ -6,6 +6,7 @@ use std::{collections::VecDeque, fmt, fs, path::Path, process::Command};
66
77use anyhow:: { Context , Result } ;
88use base_db:: { CrateDisplayName , CrateGraph , CrateId , CrateName , Edition , Env , FileId , ProcMacro } ;
9+ use cargo_workspace:: DepKind ;
910use cfg:: CfgOptions ;
1011use paths:: { AbsPath , AbsPathBuf } ;
1112use proc_macro_api:: ProcMacroClient ;
@@ -407,23 +408,25 @@ fn cargo_to_crate_graph(
407408 }
408409 }
409410
410- pkg_crates. entry ( pkg) . or_insert_with ( Vec :: new) . push ( crate_id) ;
411+ pkg_crates. entry ( pkg) . or_insert_with ( Vec :: new) . push ( ( crate_id, cargo [ tgt ] . kind ) ) ;
411412 }
412413 }
413414
414415 // Set deps to the core, std and to the lib target of the current package
415- for & from in pkg_crates. get ( & pkg) . into_iter ( ) . flatten ( ) {
416+ for ( from, kind ) in pkg_crates. get ( & pkg) . into_iter ( ) . flatten ( ) {
416417 if let Some ( ( to, name) ) = lib_tgt. clone ( ) {
417- if to != from {
418+ if to != * from && * kind != TargetKind :: BuildScript {
419+ // (build script can not depend on its library target)
420+
418421 // For root projects with dashes in their name,
419422 // cargo metadata does not do any normalization,
420423 // so we do it ourselves currently
421424 let name = CrateName :: normalize_dashes ( & name) ;
422- add_dep ( & mut crate_graph, from, name, to) ;
425+ add_dep ( & mut crate_graph, * from, name, to) ;
423426 }
424427 }
425428 for ( name, krate) in public_deps. iter ( ) {
426- add_dep ( & mut crate_graph, from, name. clone ( ) , * krate) ;
429+ add_dep ( & mut crate_graph, * from, name. clone ( ) , * krate) ;
427430 }
428431 }
429432 }
@@ -434,8 +437,17 @@ fn cargo_to_crate_graph(
434437 for dep in cargo[ pkg] . dependencies . iter ( ) {
435438 let name = CrateName :: new ( & dep. name ) . unwrap ( ) ;
436439 if let Some ( & to) = pkg_to_lib_crate. get ( & dep. pkg ) {
437- for & from in pkg_crates. get ( & pkg) . into_iter ( ) . flatten ( ) {
438- add_dep ( & mut crate_graph, from, name. clone ( ) , to)
440+ for ( from, kind) in pkg_crates. get ( & pkg) . into_iter ( ) . flatten ( ) {
441+ if dep. kind == DepKind :: Build && * kind != TargetKind :: BuildScript {
442+ // Only build scripts may depend on build dependencies.
443+ continue ;
444+ }
445+ if dep. kind != DepKind :: Build && * kind == TargetKind :: BuildScript {
446+ // Build scripts may only depend on build dependencies.
447+ continue ;
448+ }
449+
450+ add_dep ( & mut crate_graph, * from, name. clone ( ) , to)
439451 }
440452 }
441453 }
@@ -472,7 +484,7 @@ fn handle_rustc_crates(
472484 pkg_to_lib_crate : & mut FxHashMap < la_arena:: Idx < crate :: PackageData > , CrateId > ,
473485 public_deps : & [ ( CrateName , CrateId ) ] ,
474486 cargo : & CargoWorkspace ,
475- pkg_crates : & FxHashMap < la_arena:: Idx < crate :: PackageData > , Vec < CrateId > > ,
487+ pkg_crates : & FxHashMap < la_arena:: Idx < crate :: PackageData > , Vec < ( CrateId , TargetKind ) > > ,
476488) {
477489 let mut rustc_pkg_crates = FxHashMap :: default ( ) ;
478490 // The root package of the rustc-dev component is rustc_driver, so we match that
@@ -541,13 +553,13 @@ fn handle_rustc_crates(
541553 if !package. metadata . rustc_private {
542554 continue ;
543555 }
544- for & from in pkg_crates. get ( & pkg) . into_iter ( ) . flatten ( ) {
556+ for ( from, _ ) in pkg_crates. get ( & pkg) . into_iter ( ) . flatten ( ) {
545557 // Avoid creating duplicate dependencies
546558 // This avoids the situation where `from` depends on e.g. `arrayvec`, but
547559 // `rust_analyzer` thinks that it should use the one from the `rustcSource`
548560 // instead of the one from `crates.io`
549- if !crate_graph[ from] . dependencies . iter ( ) . any ( |d| d. name == name) {
550- add_dep ( crate_graph, from, name. clone ( ) , to) ;
561+ if !crate_graph[ * from] . dependencies . iter ( ) . any ( |d| d. name == name) {
562+ add_dep ( crate_graph, * from, name. clone ( ) , to) ;
551563 }
552564 }
553565 }
0 commit comments