Skip to content

Commit

Permalink
Fix panic when running cargo tree on a package with a cross compile…
Browse files Browse the repository at this point in the history
…d bindep
  • Loading branch information
rukai committed Dec 26, 2023
1 parent 4e792c2 commit 8ab6462
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 30 deletions.
52 changes: 26 additions & 26 deletions src/cargo/core/resolver/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,8 +319,32 @@ impl ResolvedFeatures {
pkg_id: PackageId,
features_for: FeaturesFor,
) -> Vec<InternedString> {
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<Vec<InternedString>> {
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.
Expand All @@ -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<Vec<InternedString>> {
self.activated_features_int(pkg_id, features_for).ok()
}

fn activated_features_int(
&self,
pkg_id: PackageId,
features_for: FeaturesFor,
) -> CargoResult<Vec<InternedString>> {
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.
Expand Down
18 changes: 14 additions & 4 deletions src/cargo/ops/tree/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 = <triple> }`
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,
Expand Down
49 changes: 49 additions & 0 deletions tests/testsuite/artifact_dep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1445,6 +1445,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 [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() {
Expand Down

0 comments on commit 8ab6462

Please sign in to comment.