Skip to content

Commit 3439765

Browse files
committed
Query RustcTargetData during feature resolution
1 parent 93cd6c6 commit 3439765

File tree

10 files changed

+98
-62
lines changed

10 files changed

+98
-62
lines changed

benches/benchsuite/benches/resolve.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ struct ResolveInfo<'cfg> {
2525
fn do_resolve<'cfg>(config: &'cfg Config, ws_root: &Path) -> ResolveInfo<'cfg> {
2626
let requested_kinds = [CompileKind::Host];
2727
let ws = Workspace::new(&ws_root.join("Cargo.toml"), config).unwrap();
28-
let target_data = RustcTargetData::new(&ws, &requested_kinds).unwrap();
28+
let mut target_data = RustcTargetData::new(&ws, &requested_kinds).unwrap();
2929
let cli_features = CliFeatures::from_command_line(&[], false, true).unwrap();
3030
let pkgs = cargo::ops::Packages::Default;
3131
let specs = pkgs.to_package_id_specs(&ws).unwrap();
@@ -35,7 +35,7 @@ fn do_resolve<'cfg>(config: &'cfg Config, ws_root: &Path) -> ResolveInfo<'cfg> {
3535
// not confuse criterion's warmup.
3636
let ws_resolve = cargo::ops::resolve_ws_with_opts(
3737
&ws,
38-
&target_data,
38+
&mut target_data,
3939
&requested_kinds,
4040
&cli_features,
4141
&specs,

src/cargo/core/compiler/build_context/target_info.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -942,7 +942,7 @@ impl<'cfg> RustcTargetData<'cfg> {
942942
}
943943

944944
/// Insert `kind` into our `target_info` and `target_config` members if it isn't present yet.
945-
fn merge_compile_kind(&mut self, kind: CompileKind) -> CargoResult<()> {
945+
pub fn merge_compile_kind(&mut self, kind: CompileKind) -> CargoResult<()> {
946946
if let CompileKind::Target(target) = kind {
947947
if !self.target_config.contains_key(&target) {
948948
self.target_config

src/cargo/core/compiler/standard_lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ pub(crate) fn std_crates(config: &Config, units: Option<&[Unit]>) -> Option<Vec<
6262
/// Resolve the standard library dependencies.
6363
pub fn resolve_std<'cfg>(
6464
ws: &Workspace<'cfg>,
65-
target_data: &RustcTargetData<'cfg>,
65+
target_data: &mut RustcTargetData<'cfg>,
6666
build_config: &BuildConfig,
6767
crates: &[String],
6868
) -> CargoResult<(PackageSet<'cfg>, Resolve, ResolvedFeatures)> {

src/cargo/core/resolver/features.rs

Lines changed: 78 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ use crate::core::{FeatureValue, PackageId, PackageIdSpec, PackageSet, Workspace}
4646
use crate::util::interning::InternedString;
4747
use crate::util::CargoResult;
4848
use anyhow::bail;
49+
use itertools::Itertools;
4950
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
5051
use std::rc::Rc;
5152

@@ -408,7 +409,7 @@ pub type DiffMap = BTreeMap<PackageFeaturesKey, BTreeSet<InternedString>>;
408409
/// [module-level documentation]: crate::core::resolver::features
409410
pub struct FeatureResolver<'a, 'cfg> {
410411
ws: &'a Workspace<'cfg>,
411-
target_data: &'a RustcTargetData<'cfg>,
412+
target_data: &'a mut RustcTargetData<'cfg>,
412413
/// The platforms to build for, requested by the user.
413414
requested_targets: &'a [CompileKind],
414415
resolve: &'a Resolve,
@@ -445,7 +446,7 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
445446
/// with the result.
446447
pub fn resolve(
447448
ws: &Workspace<'cfg>,
448-
target_data: &RustcTargetData<'cfg>,
449+
target_data: &'a mut RustcTargetData<'cfg>,
449450
resolve: &Resolve,
450451
package_set: &'a PackageSet<'cfg>,
451452
cli_features: &CliFeatures,
@@ -544,7 +545,7 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
544545
// features that enable other features.
545546
return Ok(());
546547
}
547-
for (dep_pkg_id, deps) in self.deps(pkg_id, fk) {
548+
for (dep_pkg_id, deps) in self.deps(pkg_id, fk)? {
548549
for (dep, dep_fk) in deps {
549550
if dep.is_optional() {
550551
// Optional dependencies are enabled in `activate_fv` when
@@ -647,7 +648,7 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
647648
.deferred_weak_dependencies
648649
.remove(&(pkg_id, fk, dep_name));
649650
// 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)? {
651652
for (dep, dep_fk) in deps {
652653
if dep.name_in_toml() != dep_name {
653654
continue;
@@ -681,7 +682,7 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
681682
dep_feature: InternedString,
682683
weak: bool,
683684
) -> 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)? {
685686
for (dep, dep_fk) in deps {
686687
if dep.name_in_toml() != dep_name {
687688
continue;
@@ -777,12 +778,17 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
777778

778779
/// Returns the dependencies for a package, filtering out inactive targets.
779780
fn deps(
780-
&self,
781+
&mut self,
781782
pkg_id: PackageId,
782783
fk: FeaturesFor,
783-
) -> Vec<(PackageId, Vec<(&'a Dependency, FeaturesFor)>)> {
784+
) -> CargoResult<Vec<(PackageId, Vec<(&'a Dependency, FeaturesFor)>)>> {
784785
// 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 {
786792
// We always count platforms as activated if the target stems from an artifact
787793
// dependency's target specification. This triggers in conjunction with
788794
// `[target.'cfg(…)'.dependencies]` manifest sections.
@@ -791,18 +797,17 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
791797
// We always care about build-dependencies, and they are always
792798
// Host. If we are computing dependencies "for a build script",
793799
// 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)
796801
}
797-
(_, FeaturesFor::NormalOrDev) => self
798-
.requested_targets
802+
(_, FeaturesFor::NormalOrDev) => requested_targets
799803
.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+
}
804808
}
805-
};
809+
}
810+
806811
self.resolve
807812
.deps(pkg_id)
808813
.map(|(dep_id, deps)| {
@@ -811,7 +816,12 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
811816
.filter(|dep| {
812817
if dep.platform().is_some()
813818
&& 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+
)
815825
{
816826
return false;
817827
}
@@ -820,7 +830,9 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
820830
}
821831
true
822832
})
823-
.flat_map(|dep| {
833+
.collect_vec() // collect because the next closure mutably borrows `self.target_data`
834+
.into_iter()
835+
.map(|dep| {
824836
// Each `dep`endency can be built for multiple targets. For one, it
825837
// may be a library target which is built as initially configured
826838
// by `fk`. If it appears as build dependency, it must be built
@@ -852,28 +864,49 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
852864
};
853865

854866
// `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+
})
871905
})
872-
.map(FeaturesFor::ArtifactDep)
873-
.collect(),
874-
}),
875-
)
876-
});
906+
.transpose()?,
907+
))
908+
})
909+
.transpose()?;
877910

878911
let dep_fks = match artifact_target_keys {
879912
// The artifact is also a library and does specify custom
@@ -893,12 +926,13 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
893926
// Use the standard feature key without any alteration.
894927
Some((_, None)) | None => vec![lib_fk],
895928
};
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)))
897930
})
898-
.collect::<Vec<_>>();
899-
(dep_id, deps)
931+
.flatten_ok()
932+
.collect::<CargoResult<Vec<_>>>()?;
933+
Ok((dep_id, deps))
900934
})
901-
.filter(|(_id, deps)| !deps.is_empty())
935+
.filter(|res| res.as_ref().map_or(true, |(_id, deps)| !deps.is_empty()))
902936
.collect()
903937
}
904938

src/cargo/ops/cargo_compile/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ pub fn create_bcx<'a, 'cfg>(
237237
}
238238
config.validate_term_config()?;
239239

240-
let target_data = RustcTargetData::new(ws, &build_config.requested_kinds)?;
240+
let mut target_data = RustcTargetData::new(ws, &build_config.requested_kinds)?;
241241

242242
let specs = spec.to_package_id_specs(ws)?;
243243
let has_dev_units = {
@@ -263,7 +263,7 @@ pub fn create_bcx<'a, 'cfg>(
263263
};
264264
let resolve = ops::resolve_ws_with_opts(
265265
ws,
266-
&target_data,
266+
&mut target_data,
267267
&build_config.requested_kinds,
268268
cli_features,
269269
&specs,
@@ -279,7 +279,7 @@ pub fn create_bcx<'a, 'cfg>(
279279

280280
let std_resolve_features = if let Some(crates) = &config.cli_unstable().build_std {
281281
let (std_package_set, std_resolve, std_features) =
282-
standard_lib::resolve_std(ws, &target_data, &build_config, crates)?;
282+
standard_lib::resolve_std(ws, &mut target_data, &build_config, crates)?;
283283
pkg_set.add_set(std_package_set);
284284
Some((std_resolve, std_features))
285285
} else {

src/cargo/ops/cargo_fetch.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub fn fetch<'a>(
3131
&options.targets,
3232
CompileMode::Build,
3333
)?;
34-
let data = RustcTargetData::new(ws, &build_config.requested_kinds)?;
34+
let mut data = RustcTargetData::new(ws, &build_config.requested_kinds)?;
3535
let mut fetched_packages = HashSet::new();
3636
let mut deps_to_fetch = ws.members().map(|p| p.package_id()).collect::<Vec<_>>();
3737
let mut to_download = Vec::new();
@@ -70,7 +70,8 @@ pub fn fetch<'a>(
7070
// If -Zbuild-std was passed, download dependencies for the standard library.
7171
// We don't know ahead of time what jobs we'll be running, so tell `std_crates` that.
7272
if let Some(crates) = standard_lib::std_crates(config, None) {
73-
let (std_package_set, _, _) = standard_lib::resolve_std(ws, &data, &build_config, &crates)?;
73+
let (std_package_set, _, _) =
74+
standard_lib::resolve_std(ws, &mut data, &build_config, &crates)?;
7475
packages.add_set(std_package_set);
7576
}
7677

src/cargo/ops/cargo_output_metadata.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ fn build_resolve_graph(
126126
// How should this work?
127127
let requested_kinds =
128128
CompileKind::from_requested_targets(ws.config(), &metadata_opts.filter_platforms)?;
129-
let target_data = RustcTargetData::new(ws, &requested_kinds)?;
129+
let mut target_data = RustcTargetData::new(ws, &requested_kinds)?;
130130
// Resolve entire workspace.
131131
let specs = Packages::All.to_package_id_specs(ws)?;
132132
let force_all = if metadata_opts.filter_platforms.is_empty() {
@@ -139,7 +139,7 @@ fn build_resolve_graph(
139139
// as that is the behavior of download_accessible.
140140
let ws_resolve = ops::resolve_ws_with_opts(
141141
ws,
142-
&target_data,
142+
&mut target_data,
143143
&requested_kinds,
144144
&metadata_opts.cli_features,
145145
&specs,

src/cargo/ops/fix.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -243,11 +243,12 @@ fn check_resolver_change(ws: &Workspace<'_>, opts: &FixOptions) -> CargoResult<(
243243
// 2018 without `resolver` set must be V1
244244
assert_eq!(ws.resolve_behavior(), ResolveBehavior::V1);
245245
let specs = opts.compile_opts.spec.to_package_id_specs(ws)?;
246-
let target_data = RustcTargetData::new(ws, &opts.compile_opts.build_config.requested_kinds)?;
247-
let resolve_differences = |has_dev_units| -> CargoResult<(WorkspaceResolve<'_>, DiffMap)> {
246+
let mut target_data =
247+
RustcTargetData::new(ws, &opts.compile_opts.build_config.requested_kinds)?;
248+
let mut resolve_differences = |has_dev_units| -> CargoResult<(WorkspaceResolve<'_>, DiffMap)> {
248249
let ws_resolve = ops::resolve_ws_with_opts(
249250
ws,
250-
&target_data,
251+
&mut target_data,
251252
&opts.compile_opts.build_config.requested_kinds,
252253
&opts.compile_opts.cli_features,
253254
&specs,
@@ -258,7 +259,7 @@ fn check_resolver_change(ws: &Workspace<'_>, opts: &FixOptions) -> CargoResult<(
258259
let feature_opts = FeatureOpts::new_behavior(ResolveBehavior::V2, has_dev_units);
259260
let v2_features = FeatureResolver::resolve(
260261
ws,
261-
&target_data,
262+
&mut target_data,
262263
&ws_resolve.targeted_resolve,
263264
&ws_resolve.pkg_set,
264265
&opts.compile_opts.cli_features,

src/cargo/ops/resolve.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ pub fn resolve_ws<'a>(ws: &Workspace<'a>) -> CargoResult<(PackageSet<'a>, Resolv
124124
/// members. In this case, `opts.all_features` must be `true`.
125125
pub fn resolve_ws_with_opts<'cfg>(
126126
ws: &Workspace<'cfg>,
127-
target_data: &RustcTargetData<'cfg>,
127+
target_data: &mut RustcTargetData<'cfg>,
128128
requested_targets: &[CompileKind],
129129
cli_features: &CliFeatures,
130130
specs: &[PackageIdSpec],

src/cargo/ops/tree/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ pub fn build_and_print(ws: &Workspace<'_>, opts: &TreeOptions) -> CargoResult<()
135135
// TODO: Target::All is broken with -Zfeatures=itarget. To handle that properly,
136136
// `FeatureResolver` will need to be taught what "all" means.
137137
let requested_kinds = CompileKind::from_requested_targets(ws.config(), &requested_targets)?;
138-
let target_data = RustcTargetData::new(ws, &requested_kinds)?;
138+
let mut target_data = RustcTargetData::new(ws, &requested_kinds)?;
139139
let specs = opts.packages.to_package_id_specs(ws)?;
140140
let has_dev = if opts
141141
.edge_kinds
@@ -152,7 +152,7 @@ pub fn build_and_print(ws: &Workspace<'_>, opts: &TreeOptions) -> CargoResult<()
152152
};
153153
let ws_resolve = ops::resolve_ws_with_opts(
154154
ws,
155-
&target_data,
155+
&mut target_data,
156156
&requested_kinds,
157157
&opts.cli_features,
158158
&specs,

0 commit comments

Comments
 (0)