Skip to content

Commit eaa50a9

Browse files
committed
Fix panic when running cargo tree on a package with a cross compiled bindep
1 parent eee4ea2 commit eaa50a9

File tree

5 files changed

+89
-32
lines changed

5 files changed

+89
-32
lines changed

src/cargo/core/resolver/features.rs

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -319,8 +319,32 @@ impl ResolvedFeatures {
319319
pkg_id: PackageId,
320320
features_for: FeaturesFor,
321321
) -> Vec<InternedString> {
322-
self.activated_features_int(pkg_id, features_for)
323-
.expect("activated_features for invalid package")
322+
let fk = features_for.apply_opts(&self.opts);
323+
let key = (pkg_id, fk);
324+
if let Some(fs) = self.activated_features.get(&key) {
325+
fs.iter().cloned().collect()
326+
} else {
327+
panic!(
328+
"did not find features for {key:?} within activated_features:\n{:#?}",
329+
self.activated_features
330+
)
331+
}
332+
}
333+
334+
/// Variant of `activated_features` that returns `None` if this is
335+
/// not a valid pkg_id/is_build combination. Used in places which do
336+
/// not know which packages are activated (like `cargo clean`).
337+
pub fn activated_features_unverified(
338+
&self,
339+
pkg_id: PackageId,
340+
features_for: FeaturesFor,
341+
) -> Option<Vec<InternedString>> {
342+
let fk = features_for.apply_opts(&self.opts);
343+
if let Some(fs) = self.activated_features.get(&(pkg_id, fk)) {
344+
Some(fs.iter().cloned().collect())
345+
} else {
346+
None
347+
}
324348
}
325349

326350
/// Returns if the given dependency should be included.
@@ -340,30 +364,6 @@ impl ResolvedFeatures {
340364
.unwrap_or(false)
341365
}
342366

343-
/// Variant of `activated_features` that returns `None` if this is
344-
/// not a valid pkg_id/is_build combination. Used in places which do
345-
/// not know which packages are activated (like `cargo clean`).
346-
pub fn activated_features_unverified(
347-
&self,
348-
pkg_id: PackageId,
349-
features_for: FeaturesFor,
350-
) -> Option<Vec<InternedString>> {
351-
self.activated_features_int(pkg_id, features_for).ok()
352-
}
353-
354-
fn activated_features_int(
355-
&self,
356-
pkg_id: PackageId,
357-
features_for: FeaturesFor,
358-
) -> CargoResult<Vec<InternedString>> {
359-
let fk = features_for.apply_opts(&self.opts);
360-
if let Some(fs) = self.activated_features.get(&(pkg_id, fk)) {
361-
Ok(fs.iter().cloned().collect())
362-
} else {
363-
bail!("features did not find {:?} {:?}", pkg_id, fk)
364-
}
365-
}
366-
367367
/// Compares the result against the original resolver behavior.
368368
///
369369
/// Used by `cargo fix --edition` to display any differences.

src/cargo/ops/tree/graph.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -391,10 +391,20 @@ fn add_pkg(
391391
let dep_pkg = graph.package_map[&dep_id];
392392

393393
for dep in deps {
394-
let dep_features_for = if dep.is_build() || dep_pkg.proc_macro() {
395-
FeaturesFor::HostDep
396-
} else {
397-
features_for
394+
let dep_features_for = match dep
395+
.artifact()
396+
.and_then(|artifact| artifact.target())
397+
.and_then(|target| target.to_resolved_compile_target(requested_kind))
398+
{
399+
// Dependency has a `{ …, target = <triple> }`
400+
Some(target) => FeaturesFor::ArtifactDep(target),
401+
None => {
402+
if dep.is_build() || dep_pkg.proc_macro() {
403+
FeaturesFor::HostDep
404+
} else {
405+
features_for
406+
}
407+
}
398408
};
399409
let dep_index = add_pkg(
400410
graph,

tests/testsuite/artifact_dep.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,6 +1497,55 @@ foo v0.0.0 ([CWD])
14971497
)
14981498
.run();
14991499
}
1500+
1501+
#[cargo_test]
1502+
fn artifact_dep_target_specified() {
1503+
if cross_compile::disabled() {
1504+
return;
1505+
}
1506+
let target = cross_compile::alternate();
1507+
1508+
let p = project()
1509+
.file(
1510+
"Cargo.toml",
1511+
&r#"
1512+
[package]
1513+
name = "foo"
1514+
version = "0.0.0"
1515+
authors = []
1516+
resolver = "2"
1517+
1518+
[dependencies]
1519+
bindep = { path = "bindep", artifact = "bin", target = "$TARGET" }
1520+
"#
1521+
.replace("$TARGET", target),
1522+
)
1523+
.file("src/lib.rs", "")
1524+
.file("bindep/Cargo.toml", &basic_manifest("bindep", "0.0.0"))
1525+
.file("bindep/src/main.rs", "fn main() {}")
1526+
.build();
1527+
1528+
p.cargo("check -Z bindeps")
1529+
.masquerade_as_nightly_cargo(&["bindeps"])
1530+
.with_stderr_contains(
1531+
r#"[COMPILING] bindep v0.0.0 ([CWD]/bindep)
1532+
[CHECKING] foo v0.0.0 ([CWD])
1533+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]"#,
1534+
)
1535+
.with_status(0)
1536+
.run();
1537+
1538+
p.cargo("tree -Z bindeps")
1539+
.masquerade_as_nightly_cargo(&["bindeps"])
1540+
.with_stdout(
1541+
"\
1542+
foo v0.0.0 ([CWD])
1543+
└── bindep v0.0.0 ([CWD]/bindep)",
1544+
)
1545+
.with_status(0)
1546+
.run();
1547+
}
1548+
15001549
#[cargo_test]
15011550
fn targets_are_picked_up_from_non_workspace_artifact_deps() {
15021551
if cross_compile::disabled() {

tests/testsuite/cargo_add/target/in

Lines changed: 0 additions & 1 deletion
This file was deleted.

tests/testsuite/cargo_remove/target/in

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)