diff --git a/src/cargo/core/resolver/features.rs b/src/cargo/core/resolver/features.rs index fdb49c0bf9f..52ff231b2c8 100644 --- a/src/cargo/core/resolver/features.rs +++ b/src/cargo/core/resolver/features.rs @@ -319,8 +319,32 @@ impl ResolvedFeatures { pkg_id: PackageId, features_for: FeaturesFor, ) -> Vec { - self.activated_features_int(pkg_id, features_for) - .expect("activated_features for invalid package") + let fk = features_for.apply_opts(&self.opts); + let key = (pkg_id, fk); + if let Some(fs) = self.activated_features.get(&key) { + fs.iter().cloned().collect() + } else { + panic!( + "did not find features for {key:?} within activated_features:\n{:#?}", + self.activated_features + ) + } + } + + /// Variant of `activated_features` that returns `None` if this is + /// not a valid pkg_id/is_build combination. Used in places which do + /// not know which packages are activated (like `cargo clean`). + pub fn activated_features_unverified( + &self, + pkg_id: PackageId, + features_for: FeaturesFor, + ) -> Option> { + let fk = features_for.apply_opts(&self.opts); + if let Some(fs) = self.activated_features.get(&(pkg_id, fk)) { + Some(fs.iter().cloned().collect()) + } else { + None + } } /// Returns if the given dependency should be included. @@ -340,30 +364,6 @@ impl ResolvedFeatures { .unwrap_or(false) } - /// Variant of `activated_features` that returns `None` if this is - /// not a valid pkg_id/is_build combination. Used in places which do - /// not know which packages are activated (like `cargo clean`). - pub fn activated_features_unverified( - &self, - pkg_id: PackageId, - features_for: FeaturesFor, - ) -> Option> { - self.activated_features_int(pkg_id, features_for).ok() - } - - fn activated_features_int( - &self, - pkg_id: PackageId, - features_for: FeaturesFor, - ) -> CargoResult> { - let fk = features_for.apply_opts(&self.opts); - if let Some(fs) = self.activated_features.get(&(pkg_id, fk)) { - Ok(fs.iter().cloned().collect()) - } else { - bail!("features did not find {:?} {:?}", pkg_id, fk) - } - } - /// Compares the result against the original resolver behavior. /// /// Used by `cargo fix --edition` to display any differences. diff --git a/src/cargo/ops/tree/graph.rs b/src/cargo/ops/tree/graph.rs index 31276f10416..fab079cf65a 100644 --- a/src/cargo/ops/tree/graph.rs +++ b/src/cargo/ops/tree/graph.rs @@ -391,10 +391,20 @@ fn add_pkg( let dep_pkg = graph.package_map[&dep_id]; for dep in deps { - let dep_features_for = if dep.is_build() || dep_pkg.proc_macro() { - FeaturesFor::HostDep - } else { - features_for + let dep_features_for = match dep + .artifact() + .and_then(|artifact| artifact.target()) + .and_then(|target| target.to_resolved_compile_target(requested_kind)) + { + // Dependency has a `{ …, target = }` + Some(target) => FeaturesFor::ArtifactDep(target), + None => { + if dep.is_build() || dep_pkg.proc_macro() { + FeaturesFor::HostDep + } else { + features_for + } + } }; let dep_index = add_pkg( graph, diff --git a/tests/testsuite/artifact_dep.rs b/tests/testsuite/artifact_dep.rs index e04fb1bddf9..c7208270e85 100644 --- a/tests/testsuite/artifact_dep.rs +++ b/tests/testsuite/artifact_dep.rs @@ -1497,6 +1497,55 @@ foo v0.0.0 ([CWD]) ) .run(); } + +#[cargo_test] +fn artifact_dep_target_specified() { + if cross_compile::disabled() { + return; + } + let target = cross_compile::alternate(); + + let p = project() + .file( + "Cargo.toml", + &r#" + [package] + name = "foo" + version = "0.0.0" + authors = [] + resolver = "2" + + [dependencies] + bindep = { path = "bindep", artifact = "bin", target = "$TARGET" } + "# + .replace("$TARGET", target), + ) + .file("src/lib.rs", "") + .file("bindep/Cargo.toml", &basic_manifest("bindep", "0.0.0")) + .file("bindep/src/main.rs", "fn main() {}") + .build(); + + p.cargo("check -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_contains( + r#"[COMPILING] bindep v0.0.0 ([CWD]/bindep) +[CHECKING] foo v0.0.0 ([CWD]) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]"#, + ) + .with_status(0) + .run(); + + p.cargo("tree -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stdout( + "\ +foo v0.0.0 ([CWD]) +└── bindep v0.0.0 ([CWD]/bindep)", + ) + .with_status(0) + .run(); +} + #[cargo_test] fn targets_are_picked_up_from_non_workspace_artifact_deps() { if cross_compile::disabled() {