Skip to content

Commit

Permalink
Auto merge of #7756 - ehuss:dep-kinds-dedup, r=alexcrichton
Browse files Browse the repository at this point in the history
Remove metadata dep_kinds duplicates.

In `cargo metadata`, an entry could appear multiple times in the `dep_kinds` array if it is used by multiple workspace members with different features activated.  This fixes it by de-duplicating the entries.

This is kinda related to `cargo metadata` not handling workspaces and features very well. But workspaces and features are a bit awkward overall.

Fixes #7752
  • Loading branch information
bors committed Jan 6, 2020
2 parents 801942b + 7acf376 commit 1081bc7
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 2 deletions.
9 changes: 7 additions & 2 deletions src/cargo/ops/cargo_output_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ struct Dep {
dep_kinds: Vec<DepKindInfo>,
}

#[derive(Serialize)]
#[derive(Serialize, PartialEq, Eq, PartialOrd, Ord)]
struct DepKindInfo {
kind: dependency::Kind,
target: Option<Platform>,
Expand Down Expand Up @@ -184,14 +184,19 @@ fn build_resolve_graph_r(
None => true,
})
.filter_map(|(dep_id, deps)| {
let mut dep_kinds: Vec<_> = deps.iter().map(DepKindInfo::from).collect();
// Duplicates may appear if the same package is used by different
// members of a workspace with different features selected.
dep_kinds.sort_unstable();
dep_kinds.dedup();
package_map
.get(&dep_id)
.and_then(|pkg| pkg.targets().iter().find(|t| t.is_lib()))
.and_then(|lib_target| resolve.extern_crate_name(pkg_id, dep_id, lib_target).ok())
.map(|name| Dep {
name,
pkg: dep_id,
dep_kinds: deps.iter().map(DepKindInfo::from).collect(),
dep_kinds,
})
})
.collect();
Expand Down
110 changes: 110 additions & 0 deletions tests/testsuite/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2623,3 +2623,113 @@ fn dep_kinds() {
)
.run();
}

#[cargo_test]
fn dep_kinds_workspace() {
// Check for bug with duplicate dep kinds in a workspace.
// If different members select different features for the same package,
// they show up multiple times in the resolver `deps`.
//
// Here:
// foo -> dep
// bar -> foo[feat1] -> dep
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[features]
feat1 = []
[dependencies]
dep = { path="dep" }
[workspace]
members = ["bar"]
"#,
)
.file("src/lib.rs", "")
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.1.0"
[dependencies]
foo = { path="..", features=["feat1"] }
"#,
)
.file("bar/src/lib.rs", "")
.file("dep/Cargo.toml", &basic_lib_manifest("dep"))
.file("dep/src/lib.rs", "")
.build();

p.cargo("metadata")
.with_json(
r#"
{
"packages": "{...}",
"workspace_members": "{...}",
"target_directory": "[..]/foo/target",
"version": 1,
"workspace_root": "[..]/foo",
"resolve": {
"nodes": [
{
"id": "dep 0.5.0 (path+file://[..]/foo/dep)",
"dependencies": [],
"deps": [],
"features": []
},
{
"id": "bar 0.1.0 (path+file://[..]/foo/bar)",
"dependencies": [
"foo 0.1.0 (path+file://[..]/foo)"
],
"deps": [
{
"name": "foo",
"pkg": "foo 0.1.0 (path+file://[..]/foo)",
"dep_kinds": [
{
"kind": null,
"target": null
}
]
}
],
"features": []
},
{
"id": "foo 0.1.0 (path+file://[..]/foo)",
"dependencies": [
"dep 0.5.0 (path+file://[..]/foo/dep)"
],
"deps": [
{
"name": "dep",
"pkg": "dep 0.5.0 (path+file://[..]/foo/dep)",
"dep_kinds": [
{
"kind": null,
"target": null
}
]
}
],
"features": [
"feat1"
]
}
],
"root": "foo 0.1.0 (path+file://[..]/foo)"
}
}
"#,
)
.run();
}

0 comments on commit 1081bc7

Please sign in to comment.