Skip to content

Commit 02b0dba

Browse files
committed
Fix optional dependencies and required dev-deps
This fixes an accidental bug introduced in #5300 by ensuring a local map keeps track of the fact that there can be multiple dependencies for one name Closes #5453
1 parent acea5e2 commit 02b0dba

File tree

4 files changed

+66
-21
lines changed

4 files changed

+66
-21
lines changed

src/cargo/core/resolver/mod.rs

+12-9
Original file line numberDiff line numberDiff line change
@@ -340,15 +340,18 @@ fn activate_deps_loop(
340340
backtracked = true;
341341
Ok((candidate, has_another))
342342
}
343-
None => Err(activation_error(
344-
&cx,
345-
registry.registry,
346-
&parent,
347-
&dep,
348-
&conflicting_activations,
349-
&candidates,
350-
config,
351-
)),
343+
None => {
344+
debug!("no candidates found");
345+
Err(activation_error(
346+
&cx,
347+
registry.registry,
348+
&parent,
349+
&dep,
350+
&conflicting_activations,
351+
&candidates,
352+
config,
353+
))
354+
}
352355
}
353356
})?;
354357

src/cargo/core/summary.rs

+10-6
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,12 @@ fn build_feature_map(
140140
namespaced: bool,
141141
) -> CargoResult<FeatureMap> {
142142
use self::FeatureValue::*;
143-
let dep_map: HashMap<_, _> = dependencies
144-
.iter()
145-
.map(|d| (d.name().as_str(), d))
146-
.collect();
143+
let mut dep_map = HashMap::new();
144+
for dep in dependencies.iter() {
145+
dep_map.entry(dep.name().as_str())
146+
.or_insert(Vec::new())
147+
.push(dep);
148+
}
147149

148150
let mut map = BTreeMap::new();
149151
for (feature, list) in features.iter() {
@@ -159,7 +161,7 @@ fn build_feature_map(
159161
let mut dependency_found = if namespaced {
160162
match dep_map.get(feature.as_str()) {
161163
Some(ref dep_data) => {
162-
if !dep_data.is_optional() {
164+
if !dep_data.iter().any(|d| d.is_optional()) {
163165
bail!(
164166
"Feature `{}` includes the dependency of the same name, but this is \
165167
left implicit in the features included by this feature.\n\
@@ -196,7 +198,9 @@ fn build_feature_map(
196198
}
197199
}
198200
};
199-
let is_optional_dep = dep_data.map_or(false, |d| d.is_optional());
201+
let is_optional_dep = dep_data.iter()
202+
.flat_map(|d| d.iter())
203+
.any(|d| d.is_optional());
200204
if let FeatureValue::Crate(ref dep_name) = val {
201205
// If we have a dependency value, check if this is the dependency named
202206
// the same as the feature that we were looking for.

src/cargo/sources/registry/index.rs

+12-6
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,19 @@ impl<'cfg> RegistryIndex<'cfg> {
113113
// interpretation of each line here and older cargo will simply
114114
// ignore the new lines.
115115
ret.extend(lines.filter_map(|line| {
116-
self.parse_registry_package(line).ok().and_then(|v| {
117-
if online || load.is_crate_downloaded(v.0.package_id()) {
118-
Some(v)
119-
} else {
120-
None
116+
let (summary, locked) = match self.parse_registry_package(line) {
117+
Ok(p) => p,
118+
Err(e) => {
119+
info!("failed to parse `{}` registry package: {}", name, e);
120+
trace!("line: {}", line);
121+
return None
121122
}
122-
})
123+
};
124+
if online || load.is_crate_downloaded(summary.package_id()) {
125+
Some((summary, locked))
126+
} else {
127+
None
128+
}
123129
}));
124130

125131
Ok(())

tests/testsuite/features.rs

+32
Original file line numberDiff line numberDiff line change
@@ -1999,3 +1999,35 @@ fn namespaced_same_name() {
19991999
execs().with_status(0),
20002000
);
20012001
}
2002+
2003+
#[test]
2004+
fn only_dep_is_optional() {
2005+
Package::new("bar", "0.1.0").publish();
2006+
2007+
let p = project("foo")
2008+
.file(
2009+
"Cargo.toml",
2010+
r#"
2011+
[project]
2012+
name = "foo"
2013+
version = "0.0.1"
2014+
authors = []
2015+
2016+
[features]
2017+
foo = ['bar']
2018+
2019+
[dependencies]
2020+
bar = { version = "0.1", optional = true }
2021+
2022+
[dev-dependencies]
2023+
bar = "0.1"
2024+
"#,
2025+
)
2026+
.file("src/main.rs", "fn main() {}")
2027+
.build();
2028+
2029+
assert_that(
2030+
p.cargo("build"),
2031+
execs().with_status(0),
2032+
);
2033+
}

0 commit comments

Comments
 (0)