Auto merge of #7756 - ehuss:dep-kinds-dedup, r=alexcrichton

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
This commit is contained in:
bors 2020-01-06 16:25:33 +00:00
commit 1081bc7e66
2 changed files with 117 additions and 2 deletions

View file

@ -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>,
@ -184,6 +184,11 @@ 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()))
@ -191,7 +196,7 @@ fn build_resolve_graph_r(
.map(|name| Dep {
name,
pkg: dep_id,
dep_kinds: deps.iter().map(DepKindInfo::from).collect(),
dep_kinds,
})
})
.collect();

View file

@ -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();
}