Skip to content

Commit 3b14988

Browse files
committed
Auto merge of #5415 - alexcrichton:rename-same-dep, r=matklad
Fix renaming crates as they come from 2 sources Previously there was a verification in manifest parsing that the same dependency must come from the same source, but this erroneously triggered an error to get emitted when the `package` key was used to rename crates. The first change here was to update that clause to key off the `rename` field rather than the `name` field. Afterwards, though, this exposed an existing bug in the implementation. During compilation we have a `Resolve` which is a graph of crates, but we don't know *why* each edge in the dependency graph exists. In other words we don't know, when looking at an edge of the graph, what `Dependency` caused that edge to be drawn. We need to know this when passing `--extern` flags because the `Dependency` is what lists what's being renamed. This commit then primarily refactors `Resolve::deps` from an iterator of package ids to an iterator of a tuples. The first element is the package id from before and the second element is a list of `Dependency` directives which caused the edge to ber driven. This refactoring cleaned up a few places in the backend where we had to work around the lack of this knowledge. Namely this also fixes the extra test added here. Closes #5413
2 parents d998906 + ce5bbbc commit 3b14988

14 files changed

+402
-171
lines changed

src/cargo/core/compiler/context/unit_dependencies.rs

+28-29
Original file line numberDiff line numberDiff line change
@@ -64,54 +64,55 @@ fn compute_deps<'a, 'b, 'cfg>(
6464

6565
let id = unit.pkg.package_id();
6666
let deps = cx.resolve.deps(id);
67-
let mut ret = deps.filter(|dep| {
68-
unit.pkg
69-
.dependencies()
70-
.iter()
71-
.filter(|d| d.name() == dep.name() && d.version_req().matches(dep.version()))
72-
.any(|d| {
67+
let mut ret = deps
68+
.filter(|&(_id, deps)| {
69+
assert!(deps.len() > 0);
70+
deps.iter().any(|dep| {
7371
// If this target is a build command, then we only want build
7472
// dependencies, otherwise we want everything *other than* build
7573
// dependencies.
76-
if unit.target.is_custom_build() != d.is_build() {
74+
if unit.target.is_custom_build() != dep.is_build() {
7775
return false;
7876
}
7977

8078
// If this dependency is *not* a transitive dependency, then it
8179
// only applies to test/example targets
82-
if !d.is_transitive() && !unit.target.is_test() && !unit.target.is_example()
80+
if !dep.is_transitive() && !unit.target.is_test() && !unit.target.is_example()
8381
&& !unit.profile.test
8482
{
8583
return false;
8684
}
8785

8886
// If this dependency is only available for certain platforms,
8987
// make sure we're only enabling it for that platform.
90-
if !cx.dep_platform_activated(d, unit.kind) {
88+
if !cx.dep_platform_activated(dep, unit.kind) {
9189
return false;
9290
}
9391

9492
// If the dependency is optional, then we're only activating it
9593
// if the corresponding feature was activated
96-
if d.is_optional() && !cx.resolve.features(id).contains(&*d.name()) {
94+
if dep.is_optional() && !cx.resolve.features(id).contains(&*dep.name()) {
9795
return false;
9896
}
9997

10098
// If we've gotten past all that, then this dependency is
10199
// actually used!
102100
true
103101
})
104-
}).filter_map(|id| match cx.get_package(id) {
105-
Ok(pkg) => pkg.targets().iter().find(|t| t.is_lib()).map(|t| {
106-
let unit = Unit {
107-
pkg,
108-
target: t,
109-
profile: lib_or_check_profile(unit, t, cx),
110-
kind: unit.kind.for_target(t),
111-
};
112-
Ok(unit)
113-
}),
114-
Err(e) => Some(Err(e)),
102+
})
103+
.filter_map(|(id, _)| {
104+
match cx.get_package(id) {
105+
Ok(pkg) => pkg.targets().iter().find(|t| t.is_lib()).map(|t| {
106+
let unit = Unit {
107+
pkg,
108+
target: t,
109+
profile: lib_or_check_profile(unit, t, cx),
110+
kind: unit.kind.for_target(t),
111+
};
112+
Ok(unit)
113+
}),
114+
Err(e) => Some(Err(e)),
115+
}
115116
})
116117
.collect::<CargoResult<Vec<_>>>()?;
117118

@@ -205,17 +206,15 @@ fn compute_deps_doc<'a, 'cfg>(
205206
) -> CargoResult<Vec<Unit<'a>>> {
206207
let deps = cx.resolve
207208
.deps(unit.pkg.package_id())
208-
.filter(|dep| {
209-
unit.pkg
210-
.dependencies()
211-
.iter()
212-
.filter(|d| d.name() == dep.name() && d.version_req().matches(dep.version()))
213-
.any(|dep| match dep.kind() {
209+
.filter(|&(_id, deps)| {
210+
deps.iter().any(|dep| {
211+
match dep.kind() {
214212
DepKind::Normal => cx.dep_platform_activated(dep, unit.kind),
215213
_ => false,
216-
})
214+
}
215+
})
217216
})
218-
.map(|dep| cx.get_package(dep));
217+
.map(|(id, _deps)| cx.get_package(id));
219218

220219
// To document a library, we depend on dependencies actually being
221220
// built. If we're documenting *all* libraries, then we also depend on

src/cargo/core/compiler/mod.rs

+24-17
Original file line numberDiff line numberDiff line change
@@ -1094,23 +1094,30 @@ fn build_deps_args<'a, 'cfg>(
10941094
}
10951095
let mut v = OsString::new();
10961096

1097-
// Unfortunately right now Cargo doesn't have a great way to get a
1098-
// 1:1 mapping of entries in `dependencies()` to the actual crate
1099-
// we're depending on. Instead we're left to do some guesswork here
1100-
// to figure out what `Dependency` the `dep` unit corresponds to in
1101-
// `current` to see if we're renaming it.
1102-
//
1103-
// This I believe mostly works out for now, but we'll likely want
1104-
// to tighten up this in the future.
1105-
let name = current
1106-
.pkg
1107-
.dependencies()
1108-
.iter()
1109-
.filter(|d| d.matches_ignoring_source(dep.pkg.package_id()))
1110-
.filter_map(|d| d.rename())
1111-
.next();
1112-
1113-
v.push(name.unwrap_or(&dep.target.crate_name()));
1097+
let deps = {
1098+
let a = current.pkg.package_id();
1099+
let b = dep.pkg.package_id();
1100+
if a == b {
1101+
&[]
1102+
} else {
1103+
cx.resolve.dependencies_listed(a, b)
1104+
}
1105+
};
1106+
1107+
let crate_name = dep.target.crate_name();
1108+
let mut names = deps.iter()
1109+
.map(|d| d.rename().unwrap_or(&crate_name));
1110+
let name = names.next().unwrap_or(&crate_name);
1111+
for n in names {
1112+
if n == name {
1113+
continue
1114+
}
1115+
bail!("multiple dependencies listed for the same crate must \
1116+
all have the same name, but the dependency on `{}` \
1117+
is listed as having different names", dep.pkg.package_id());
1118+
}
1119+
1120+
v.push(name);
11141121
v.push("=");
11151122
v.push(cx.files().out_dir(dep));
11161123
v.push(&path::MAIN_SEPARATOR.to_string());

src/cargo/core/resolver/context.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -269,17 +269,25 @@ impl Context {
269269
replacements
270270
}
271271

272-
pub fn graph(&self) -> Graph<PackageId> {
272+
pub fn graph(&self)
273+
-> (Graph<PackageId>, HashMap<(PackageId, PackageId), Vec<Dependency>>)
274+
{
273275
let mut graph = Graph::new();
276+
let mut deps = HashMap::new();
274277
let mut cur = &self.resolve_graph;
275278
while let Some(ref node) = cur.head {
276279
match node.0 {
277-
GraphNode::Add(ref p) => graph.add(p.clone(), &[]),
278-
GraphNode::Link(ref a, ref b) => graph.link(a.clone(), b.clone()),
280+
GraphNode::Add(ref p) => graph.add(p.clone()),
281+
GraphNode::Link(ref a, ref b, ref dep) => {
282+
graph.link(a.clone(), b.clone());
283+
deps.entry((a.clone(), b.clone()))
284+
.or_insert(Vec::new())
285+
.push(dep.clone());
286+
}
279287
}
280288
cur = &node.1;
281289
}
282-
graph
290+
(graph, deps)
283291
}
284292
}
285293

src/cargo/core/resolver/encode.rs

+10-13
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ impl EncodableResolve {
9595
let mut g = Graph::new();
9696

9797
for &(ref id, _) in live_pkgs.values() {
98-
g.add(id.clone(), &[]);
98+
g.add(id.clone());
9999
}
100100

101101
for &(ref id, pkg) in live_pkgs.values() {
@@ -177,15 +177,15 @@ impl EncodableResolve {
177177
unused_patches.push(id);
178178
}
179179

180-
Ok(Resolve {
181-
graph: g,
182-
empty_features: HashSet::new(),
183-
features: HashMap::new(),
180+
Ok(Resolve::new(
181+
g,
182+
HashMap::new(),
184183
replacements,
184+
HashMap::new(),
185185
checksums,
186186
metadata,
187187
unused_patches,
188-
})
188+
))
189189
}
190190
}
191191

@@ -347,17 +347,17 @@ impl<'a, 'cfg> ser::Serialize for WorkspaceResolve<'a, 'cfg> {
347347
where
348348
S: ser::Serializer,
349349
{
350-
let mut ids: Vec<&PackageId> = self.resolve.graph.iter().collect();
350+
let mut ids: Vec<_> = self.resolve.iter().collect();
351351
ids.sort();
352352

353353
let encodable = ids.iter()
354354
.filter_map(|&id| Some(encodable_resolve_node(id, self.resolve)))
355355
.collect::<Vec<_>>();
356356

357-
let mut metadata = self.resolve.metadata.clone();
357+
let mut metadata = self.resolve.metadata().clone();
358358

359359
for id in ids.iter().filter(|id| !id.source_id().is_path()) {
360-
let checksum = match self.resolve.checksums[*id] {
360+
let checksum = match self.resolve.checksums()[*id] {
361361
Some(ref s) => &s[..],
362362
None => "<none>",
363363
};
@@ -398,10 +398,7 @@ fn encodable_resolve_node(id: &PackageId, resolve: &Resolve) -> EncodableDepende
398398
Some(id) => (Some(encodable_package_id(id)), None),
399399
None => {
400400
let mut deps = resolve
401-
.graph
402-
.edges(id)
403-
.into_iter()
404-
.flat_map(|a| a)
401+
.deps_not_replaced(id)
405402
.map(encodable_package_id)
406403
.collect::<Vec<_>>();
407404
deps.sort();

0 commit comments

Comments
 (0)