@@ -262,22 +262,15 @@ fn compute_deps(
262262 return compute_deps_doc ( unit, state, unit_for) ;
263263 }
264264
265- let id = unit. pkg . package_id ( ) ;
266-
267- let filtered_deps = state. deps ( unit, unit_for) ;
268-
269265 let mut ret = Vec :: new ( ) ;
270266 let mut dev_deps = Vec :: new ( ) ;
271- for ( dep_pkg_id, deps) in filtered_deps {
272- let dep_pkg = state. get ( dep_pkg_id) ;
273- let ( could_have_non_artifact_lib, has_artifact_lib) =
274- calc_artifact_deps ( unit, unit_for, dep_pkg_id, deps, state, & mut ret) ?;
275-
276- let lib = package_lib ( dep_pkg, could_have_non_artifact_lib, has_artifact_lib) ;
277- let dep_lib = match lib {
278- Some ( t) => t,
267+ for ( dep_pkg_id, deps) in state. deps ( unit, unit_for) {
268+ let dep_lib = match calc_artifact_deps ( unit, unit_for, dep_pkg_id, & deps, state, & mut ret) ?
269+ {
270+ Some ( lib) => lib,
279271 None => continue ,
280272 } ;
273+ let dep_pkg = state. get ( dep_pkg_id) ;
281274 let mode = check_or_build_mode ( unit. mode , dep_lib) ;
282275 let dep_unit_for = unit_for. with_dependency ( unit, dep_lib, unit_for. root_compile_kind ( ) ) ;
283276
@@ -357,6 +350,7 @@ fn compute_deps(
357350 && unit. mode . is_any_test ( )
358351 && ( unit. target . is_test ( ) || unit. target . is_bench ( ) )
359352 {
353+ let id = unit. pkg . package_id ( ) ;
360354 ret. extend (
361355 unit. pkg
362356 . targets ( )
@@ -396,49 +390,28 @@ fn compute_deps(
396390 Ok ( ret)
397391}
398392
399- /// Try to find a target in `dep_pkg` which is a library.
400- ///
401- /// `has_artifact` is true if `dep_pkg` has any artifact, and `artifact_lib` is true
402- /// if any of them wants a library to be available too.
403- fn package_lib (
404- dep_pkg : & Package ,
405- could_have_non_artifact_lib : bool ,
406- artifact_lib : bool ,
407- ) -> Option < & Target > {
408- dep_pkg
409- . targets ( )
410- . iter ( )
411- . find ( |t| t. is_lib ( ) && ( could_have_non_artifact_lib || artifact_lib) )
412- }
413-
414393/// Find artifacts for all `deps` of `unit` and add units that build these artifacts
415394/// to `ret`.
416- fn calc_artifact_deps (
395+ fn calc_artifact_deps < ' a > (
417396 unit : & Unit ,
418397 unit_for : UnitFor ,
419398 dep_id : PackageId ,
420- deps : & HashSet < Dependency > ,
421- state : & State < ' _ , ' _ > ,
399+ deps : & [ & Dependency ] ,
400+ state : & State < ' a , ' _ > ,
422401 ret : & mut Vec < UnitDep > ,
423- ) -> CargoResult < ( bool , bool ) > {
402+ ) -> CargoResult < Option < & ' a Target > > {
424403 let mut has_artifact_lib = false ;
425- let mut num_artifacts = 0 ;
404+ let mut maybe_non_artifact_lib = false ;
426405 let artifact_pkg = state. get ( dep_id) ;
427- let mut deps_past_filter = 0 ;
428- for ( dep, artifact) in deps
429- . iter ( )
430- . filter ( |dep| {
431- if non_custom_and_non_transitive_deps ( unit, dep) {
432- deps_past_filter += 1 ;
433- true
434- } else {
435- false
406+ for dep in deps {
407+ let artifact = match dep. artifact ( ) {
408+ Some ( a) => a,
409+ None => {
410+ maybe_non_artifact_lib = true ;
411+ continue ;
436412 }
437- } )
438- . filter_map ( |dep| dep. artifact ( ) . map ( |a| ( dep, a) ) )
439- {
413+ } ;
440414 has_artifact_lib |= artifact. is_lib ( ) ;
441- num_artifacts += 1 ;
442415 // Custom build scripts (build/compile) never get artifact dependencies,
443416 // but the run-build-script step does (where it is handled).
444417 if !unit. target . is_custom_build ( ) {
@@ -462,8 +435,11 @@ fn calc_artifact_deps(
462435 ) ?) ;
463436 }
464437 }
465- let could_be_non_artifact_lib = deps_past_filter != num_artifacts;
466- Ok ( ( could_be_non_artifact_lib, has_artifact_lib) )
438+ if has_artifact_lib || maybe_non_artifact_lib {
439+ Ok ( artifact_pkg. targets ( ) . iter ( ) . find ( |t| t. is_lib ( ) ) )
440+ } else {
441+ Ok ( None )
442+ }
467443}
468444
469445/// Returns the dependencies needed to run a build script.
@@ -519,10 +495,7 @@ fn compute_deps_custom_build(
519495 //
520496 // This is essentially the same as `calc_artifact_deps`, but there are some
521497 // subtle differences that require this to be implemented differently.
522- let artifact_build_deps = state. deps_filtered ( unit, script_unit_for, & |_unit, dep| {
523- dep. kind ( ) == DepKind :: Build && dep. artifact ( ) . is_some ( )
524- } ) ;
525-
498+ //
526499 // Produce units that build all required artifact kinds (like binaries,
527500 // static libraries, etc) with the correct compile target.
528501 //
@@ -532,10 +505,13 @@ fn compute_deps_custom_build(
532505 // `root_unit_compile_target` necessary.
533506 let root_unit_compile_target = unit_for. root_compile_kind ( ) ;
534507 let unit_for = UnitFor :: new_host ( /*host_features*/ true , root_unit_compile_target) ;
535- for ( dep_pkg_id, deps) in artifact_build_deps {
536- let artifact_pkg = state. get ( dep_pkg_id) ;
537- for build_dep in deps. iter ( ) . filter ( |d| d. is_build ( ) ) {
538- let artifact = build_dep. artifact ( ) . expect ( "artifact dep" ) ;
508+ for ( dep_pkg_id, deps) in state. deps ( unit, script_unit_for) {
509+ for dep in deps {
510+ if dep. kind ( ) != DepKind :: Build || dep. artifact ( ) . is_none ( ) {
511+ continue ;
512+ }
513+ let artifact_pkg = state. get ( dep_pkg_id) ;
514+ let artifact = dep. artifact ( ) . expect ( "artifact dep" ) ;
539515 let resolved_artifact_compile_kind = artifact
540516 . target ( )
541517 . map ( |target| target. to_resolved_compile_kind ( root_unit_compile_target) ) ;
@@ -548,7 +524,7 @@ fn compute_deps_custom_build(
548524 state,
549525 resolved_artifact_compile_kind. unwrap_or ( CompileKind :: Host ) ,
550526 artifact_pkg,
551- build_dep ,
527+ dep ,
552528 ) ?) ;
553529 }
554530 }
@@ -663,22 +639,16 @@ fn compute_deps_doc(
663639 state : & mut State < ' _ , ' _ > ,
664640 unit_for : UnitFor ,
665641) -> CargoResult < Vec < UnitDep > > {
666- let deps = state. deps ( unit, unit_for) ;
667-
668642 // To document a library, we depend on dependencies actually being
669643 // built. If we're documenting *all* libraries, then we also depend on
670644 // the documentation of the library being built.
671645 let mut ret = Vec :: new ( ) ;
672- for ( id, deps) in deps {
673- let ( could_have_non_artifact_lib, has_artifact_lib) =
674- calc_artifact_deps ( unit, unit_for, id, deps, state, & mut ret) ?;
675-
676- let dep_pkg = state. get ( id) ;
677- let lib = package_lib ( dep_pkg, could_have_non_artifact_lib, has_artifact_lib) ;
678- let dep_lib = match lib {
646+ for ( id, deps) in state. deps ( unit, unit_for) {
647+ let dep_lib = match calc_artifact_deps ( unit, unit_for, id, & deps, state, & mut ret) ? {
679648 Some ( lib) => lib,
680649 None => continue ,
681650 } ;
651+ let dep_pkg = state. get ( id) ;
682652 // Rustdoc only needs rmeta files for regular dependencies.
683653 // However, for plugins/proc macros, deps should be built like normal.
684654 let mode = check_or_build_mode ( unit. mode , dep_lib) ;
@@ -1098,73 +1068,61 @@ impl<'a, 'cfg> State<'a, 'cfg> {
10981068 . unwrap_or_else ( |_| panic ! ( "expected {} to be downloaded" , id) )
10991069 }
11001070
1101- /// Returns a set of dependencies for the given unit, with a default filter.
1102- fn deps ( & self , unit : & Unit , unit_for : UnitFor ) -> Vec < ( PackageId , & HashSet < Dependency > ) > {
1103- self . deps_filtered ( unit, unit_for, & non_custom_and_non_transitive_deps)
1104- }
1105-
11061071 /// Returns a filtered set of dependencies for the given unit.
1107- fn deps_filtered (
1108- & self ,
1109- unit : & Unit ,
1110- unit_for : UnitFor ,
1111- filter : & dyn Fn ( & Unit , & Dependency ) -> bool ,
1112- ) -> Vec < ( PackageId , & HashSet < Dependency > ) > {
1072+ fn deps ( & self , unit : & Unit , unit_for : UnitFor ) -> Vec < ( PackageId , Vec < & Dependency > ) > {
11131073 let pkg_id = unit. pkg . package_id ( ) ;
11141074 let kind = unit. kind ;
11151075 self . resolve ( )
11161076 . deps ( pkg_id)
1117- . filter ( | & ( _id , deps) | {
1077+ . filter_map ( | ( id , deps) | {
11181078 assert ! ( !deps. is_empty( ) ) ;
1119- deps. iter ( ) . any ( |dep| {
1120- if !filter ( unit, dep) {
1121- return false ;
1122- }
1079+ let deps: Vec < _ > = deps
1080+ . iter ( )
1081+ . filter ( |dep| {
1082+ // If this target is a build command, then we only want build
1083+ // dependencies, otherwise we want everything *other than* build
1084+ // dependencies.
1085+ if unit. target . is_custom_build ( ) != dep. is_build ( ) {
1086+ return false ;
1087+ }
11231088
1124- // If this dependency is only available for certain platforms,
1125- // make sure we're only enabling it for that platform.
1126- if !self . target_data . dep_platform_activated ( dep, kind) {
1127- return false ;
1128- }
1089+ // If this dependency is **not** a transitive dependency, then it
1090+ // only applies to test/example targets.
1091+ if !dep. is_transitive ( )
1092+ && !unit. target . is_test ( )
1093+ && !unit. target . is_example ( )
1094+ && !unit. mode . is_doc_scrape ( )
1095+ && !unit. mode . is_any_test ( )
1096+ {
1097+ return false ;
1098+ }
11291099
1130- // If this is an optional dependency, and the new feature resolver
1131- // did not enable it, don't include it.
1132- if dep. is_optional ( ) {
1133- let features_for = unit_for. map_to_features_for ( dep. artifact ( ) ) ;
1134- if !self . is_dep_activated ( pkg_id, features_for, dep. name_in_toml ( ) ) {
1100+ // If this dependency is only available for certain platforms,
1101+ // make sure we're only enabling it for that platform.
1102+ if !self . target_data . dep_platform_activated ( dep, kind) {
11351103 return false ;
11361104 }
1137- }
11381105
1139- // If we've gotten past all that, then this dependency is
1140- // actually used!
1141- true
1142- } )
1106+ // If this is an optional dependency, and the new feature resolver
1107+ // did not enable it, don't include it.
1108+ if dep. is_optional ( ) {
1109+ let features_for = unit_for. map_to_features_for ( dep. artifact ( ) ) ;
1110+ if !self . is_dep_activated ( pkg_id, features_for, dep. name_in_toml ( ) ) {
1111+ return false ;
1112+ }
1113+ }
1114+
1115+ // If we've gotten past all that, then this dependency is
1116+ // actually used!
1117+ true
1118+ } )
1119+ . collect ( ) ;
1120+ if deps. is_empty ( ) {
1121+ None
1122+ } else {
1123+ Some ( ( id, deps) )
1124+ }
11431125 } )
11441126 . collect ( )
11451127 }
11461128}
1147-
1148- fn non_custom_and_non_transitive_deps ( unit : & Unit , dep : & Dependency ) -> bool {
1149- // If this target is a build command, then we only want build
1150- // dependencies, otherwise we want everything *other than* build
1151- // dependencies.
1152- if unit. target . is_custom_build ( ) != dep. is_build ( ) {
1153- return false ;
1154- }
1155-
1156- // If this dependency is **not** a transitive dependency, then it
1157- // only applies to test/example targets.
1158- if !dep. is_transitive ( )
1159- && !unit. target . is_test ( )
1160- && !unit. target . is_example ( )
1161- && !unit. mode . is_doc_scrape ( )
1162- && !unit. mode . is_any_test ( )
1163- {
1164- return false ;
1165- }
1166-
1167- // If we've gotten past all that, then this dependency is
1168- // actually used!
1169- true
1170- }
0 commit comments