@@ -46,6 +46,7 @@ use crate::core::{FeatureValue, PackageId, PackageIdSpec, PackageSet, Workspace}
46
46
use crate :: util:: interning:: InternedString ;
47
47
use crate :: util:: CargoResult ;
48
48
use anyhow:: bail;
49
+ use itertools:: Itertools ;
49
50
use std:: collections:: { BTreeMap , BTreeSet , HashMap , HashSet } ;
50
51
use std:: rc:: Rc ;
51
52
@@ -408,7 +409,7 @@ pub type DiffMap = BTreeMap<PackageFeaturesKey, BTreeSet<InternedString>>;
408
409
/// [module-level documentation]: crate::core::resolver::features
409
410
pub struct FeatureResolver < ' a , ' cfg > {
410
411
ws : & ' a Workspace < ' cfg > ,
411
- target_data : & ' a RustcTargetData < ' cfg > ,
412
+ target_data : & ' a mut RustcTargetData < ' cfg > ,
412
413
/// The platforms to build for, requested by the user.
413
414
requested_targets : & ' a [ CompileKind ] ,
414
415
resolve : & ' a Resolve ,
@@ -445,7 +446,7 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
445
446
/// with the result.
446
447
pub fn resolve (
447
448
ws : & Workspace < ' cfg > ,
448
- target_data : & RustcTargetData < ' cfg > ,
449
+ target_data : & ' a mut RustcTargetData < ' cfg > ,
449
450
resolve : & Resolve ,
450
451
package_set : & ' a PackageSet < ' cfg > ,
451
452
cli_features : & CliFeatures ,
@@ -544,7 +545,7 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
544
545
// features that enable other features.
545
546
return Ok ( ( ) ) ;
546
547
}
547
- for ( dep_pkg_id, deps) in self . deps ( pkg_id, fk) {
548
+ for ( dep_pkg_id, deps) in self . deps ( pkg_id, fk) ? {
548
549
for ( dep, dep_fk) in deps {
549
550
if dep. is_optional ( ) {
550
551
// Optional dependencies are enabled in `activate_fv` when
@@ -647,7 +648,7 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
647
648
. deferred_weak_dependencies
648
649
. remove ( & ( pkg_id, fk, dep_name) ) ;
649
650
// Activate the optional dep.
650
- for ( dep_pkg_id, deps) in self . deps ( pkg_id, fk) {
651
+ for ( dep_pkg_id, deps) in self . deps ( pkg_id, fk) ? {
651
652
for ( dep, dep_fk) in deps {
652
653
if dep. name_in_toml ( ) != dep_name {
653
654
continue ;
@@ -681,7 +682,7 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
681
682
dep_feature : InternedString ,
682
683
weak : bool ,
683
684
) -> CargoResult < ( ) > {
684
- for ( dep_pkg_id, deps) in self . deps ( pkg_id, fk) {
685
+ for ( dep_pkg_id, deps) in self . deps ( pkg_id, fk) ? {
685
686
for ( dep, dep_fk) in deps {
686
687
if dep. name_in_toml ( ) != dep_name {
687
688
continue ;
@@ -777,12 +778,17 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
777
778
778
779
/// Returns the dependencies for a package, filtering out inactive targets.
779
780
fn deps (
780
- & self ,
781
+ & mut self ,
781
782
pkg_id : PackageId ,
782
783
fk : FeaturesFor ,
783
- ) -> Vec < ( PackageId , Vec < ( & ' a Dependency , FeaturesFor ) > ) > {
784
+ ) -> CargoResult < Vec < ( PackageId , Vec < ( & ' a Dependency , FeaturesFor ) > ) > > {
784
785
// Helper for determining if a platform is activated.
785
- let platform_activated = |dep : & Dependency | -> bool {
786
+ fn platform_activated (
787
+ dep : & Dependency ,
788
+ fk : FeaturesFor ,
789
+ target_data : & RustcTargetData < ' _ > ,
790
+ requested_targets : & [ CompileKind ] ,
791
+ ) -> bool {
786
792
// We always count platforms as activated if the target stems from an artifact
787
793
// dependency's target specification. This triggers in conjunction with
788
794
// `[target.'cfg(…)'.dependencies]` manifest sections.
@@ -791,18 +797,17 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
791
797
// We always care about build-dependencies, and they are always
792
798
// Host. If we are computing dependencies "for a build script",
793
799
// even normal dependencies are host-only.
794
- self . target_data
795
- . dep_platform_activated ( dep, CompileKind :: Host )
800
+ target_data. dep_platform_activated ( dep, CompileKind :: Host )
796
801
}
797
- ( _, FeaturesFor :: NormalOrDev ) => self
798
- . requested_targets
802
+ ( _, FeaturesFor :: NormalOrDev ) => requested_targets
799
803
. iter ( )
800
- . any ( |kind| self . target_data . dep_platform_activated ( dep, * kind) ) ,
801
- ( _, FeaturesFor :: ArtifactDep ( target) ) => self
802
- . target_data
803
- . dep_platform_activated ( dep , CompileKind :: Target ( target ) ) ,
804
+ . any ( |kind| target_data. dep_platform_activated ( dep, * kind) ) ,
805
+ ( _, FeaturesFor :: ArtifactDep ( target) ) => {
806
+ target_data. dep_platform_activated ( dep , CompileKind :: Target ( target ) )
807
+ }
804
808
}
805
- } ;
809
+ }
810
+
806
811
self . resolve
807
812
. deps ( pkg_id)
808
813
. map ( |( dep_id, deps) | {
@@ -811,7 +816,12 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
811
816
. filter ( |dep| {
812
817
if dep. platform ( ) . is_some ( )
813
818
&& self . opts . ignore_inactive_targets
814
- && !platform_activated ( dep)
819
+ && !platform_activated (
820
+ dep,
821
+ fk,
822
+ self . target_data ,
823
+ self . requested_targets ,
824
+ )
815
825
{
816
826
return false ;
817
827
}
@@ -820,7 +830,9 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
820
830
}
821
831
true
822
832
} )
823
- . flat_map ( |dep| {
833
+ . collect_vec ( ) // collect because the next closure mutably borrows `self.target_data`
834
+ . into_iter ( )
835
+ . map ( |dep| {
824
836
// Each `dep`endency can be built for multiple targets. For one, it
825
837
// may be a library target which is built as initially configured
826
838
// by `fk`. If it appears as build dependency, it must be built
@@ -852,28 +864,49 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
852
864
} ;
853
865
854
866
// `artifact_target_keys` are produced to fulfil the needs of artifacts that have a target specification.
855
- let artifact_target_keys = dep. artifact ( ) . map ( |artifact| {
856
- (
857
- artifact. is_lib ( ) ,
858
- artifact. target ( ) . map ( |target| match target {
859
- ArtifactTarget :: Force ( target) => {
860
- vec ! [ FeaturesFor :: ArtifactDep ( target) ]
861
- }
862
- ArtifactTarget :: BuildDependencyAssumeTarget => self
863
- . requested_targets
864
- . iter ( )
865
- . map ( |kind| match kind {
866
- CompileKind :: Host => {
867
- let host_triple = self . target_data . rustc . host ;
868
- CompileTarget :: new ( & host_triple) . unwrap ( )
869
- }
870
- CompileKind :: Target ( target) => * target,
867
+ let artifact_target_keys = dep
868
+ . artifact ( )
869
+ . map ( |artifact| {
870
+ let host_triple = self . target_data . rustc . host ;
871
+ // not all targets may be queried before resolution since artifact dependencies
872
+ // and per-pkg-targets are not immediately known.
873
+ let mut activate_target = |target| {
874
+ self . target_data
875
+ . merge_compile_kind ( CompileKind :: Target ( target) )
876
+ } ;
877
+ CargoResult :: Ok ( (
878
+ artifact. is_lib ( ) ,
879
+ artifact
880
+ . target ( )
881
+ . map ( |target| {
882
+ CargoResult :: Ok ( match target {
883
+ ArtifactTarget :: Force ( target) => {
884
+ activate_target ( target) ?;
885
+ vec ! [ FeaturesFor :: ArtifactDep ( target) ]
886
+ }
887
+ // FIXME: this needs to interact with the `default-target` and `forced-target` values
888
+ // of the dependency
889
+ ArtifactTarget :: BuildDependencyAssumeTarget => self
890
+ . requested_targets
891
+ . iter ( )
892
+ . map ( |kind| match kind {
893
+ CompileKind :: Host => {
894
+ CompileTarget :: new ( & host_triple)
895
+ . unwrap ( )
896
+ }
897
+ CompileKind :: Target ( target) => * target,
898
+ } )
899
+ . map ( |target| {
900
+ activate_target ( target) ?;
901
+ Ok ( FeaturesFor :: ArtifactDep ( target) )
902
+ } )
903
+ . collect :: < CargoResult < _ > > ( ) ?,
904
+ } )
871
905
} )
872
- . map ( FeaturesFor :: ArtifactDep )
873
- . collect ( ) ,
874
- } ) ,
875
- )
876
- } ) ;
906
+ . transpose ( ) ?,
907
+ ) )
908
+ } )
909
+ . transpose ( ) ?;
877
910
878
911
let dep_fks = match artifact_target_keys {
879
912
// The artifact is also a library and does specify custom
@@ -893,12 +926,13 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
893
926
// Use the standard feature key without any alteration.
894
927
Some ( ( _, None ) ) | None => vec ! [ lib_fk] ,
895
928
} ;
896
- dep_fks. into_iter ( ) . map ( move |dep_fk| ( dep, dep_fk) )
929
+ Ok ( dep_fks. into_iter ( ) . map ( move |dep_fk| ( dep, dep_fk) ) )
897
930
} )
898
- . collect :: < Vec < _ > > ( ) ;
899
- ( dep_id, deps)
931
+ . flatten_ok ( )
932
+ . collect :: < CargoResult < Vec < _ > > > ( ) ?;
933
+ Ok ( ( dep_id, deps) )
900
934
} )
901
- . filter ( |( _id, deps) | !deps. is_empty ( ) )
935
+ . filter ( |res| res . as_ref ( ) . map_or ( true , | ( _id, deps) | !deps. is_empty ( ) ) )
902
936
. collect ( )
903
937
}
904
938
0 commit comments