1use std::cmp::Ordering;
13use std::collections::{BTreeSet, HashMap, HashSet};
14use std::rc::Rc;
15
16use log::debug;
17
18use crate::core::interning::InternedString;
19use crate::core::resolver::context::Context;
20use crate::core::resolver::errors::describe_path;
21use crate::core::{Dependency, FeatureValue, PackageId, PackageIdSpec, Registry, Summary};
22use crate::util::errors::{CargoResult, CargoResultExt};
23
24use crate::core::resolver::types::{ConflictReason, DepInfo, FeaturesSet};
25use crate::core::resolver::{ActivateResult, ResolveOpts};
26
27pub struct RegistryQueryer<'a> {
28 pub registry: &'a mut (dyn Registry + 'a),
29 replacements: &'a [(PackageIdSpec, Dependency)],
30 try_to_use: &'a HashSet<PackageId>,
31 minimal_versions: bool,
35 registry_cache: HashMap<Dependency, Rc<Vec<Summary>>>,
37 summary_cache: HashMap<
39 (Option<PackageId>, Summary, ResolveOpts),
40 Rc<(HashSet<InternedString>, Rc<Vec<DepInfo>>)>,
41 >,
42 used_replacements: HashMap<PackageId, Summary>,
44}
45
46impl<'a> RegistryQueryer<'a> {
47 pub fn new(
48 registry: &'a mut dyn Registry,
49 replacements: &'a [(PackageIdSpec, Dependency)],
50 try_to_use: &'a HashSet<PackageId>,
51 minimal_versions: bool,
52 ) -> Self {
53 RegistryQueryer {
54 registry,
55 replacements,
56 try_to_use,
57 minimal_versions,
58 registry_cache: HashMap::new(),
59 summary_cache: HashMap::new(),
60 used_replacements: HashMap::new(),
61 }
62 }
63
64 pub fn used_replacement_for(&self, p: PackageId) -> Option<(PackageId, PackageId)> {
65 self.used_replacements.get(&p).map(|r| (p, r.package_id()))
66 }
67
68 pub fn replacement_summary(&self, p: PackageId) -> Option<&Summary> {
69 self.used_replacements.get(&p)
70 }
71
72 pub fn query(&mut self, dep: &Dependency) -> CargoResult<Rc<Vec<Summary>>> {
79 if let Some(out) = self.registry_cache.get(dep).cloned() {
80 return Ok(out);
81 }
82
83 let mut ret = Vec::new();
84 self.registry.query(
85 dep,
86 &mut |s| {
87 ret.push(s);
88 },
89 false,
90 )?;
91 for summary in ret.iter_mut() {
92 let mut potential_matches = self
93 .replacements
94 .iter()
95 .filter(|&&(ref spec, _)| spec.matches(summary.package_id()));
96
97 let &(ref spec, ref dep) = match potential_matches.next() {
98 None => continue,
99 Some(replacement) => replacement,
100 };
101 debug!(
102 "found an override for {} {}",
103 dep.package_name(),
104 dep.version_req()
105 );
106
107 let mut summaries = self.registry.query_vec(dep, false)?.into_iter();
108 let s = summaries.next().ok_or_else(|| {
109 anyhow::format_err!(
110 "no matching package for override `{}` found\n\
111 location searched: {}\n\
112 version required: {}",
113 spec,
114 dep.source_id(),
115 dep.version_req()
116 )
117 })?;
118 let summaries = summaries.collect::<Vec<_>>();
119 if !summaries.is_empty() {
120 let bullets = summaries
121 .iter()
122 .map(|s| format!(" * {}", s.package_id()))
123 .collect::<Vec<_>>();
124 anyhow::bail!(
125 "the replacement specification `{}` matched \
126 multiple packages:\n * {}\n{}",
127 spec,
128 s.package_id(),
129 bullets.join("\n")
130 );
131 }
132
133 assert_eq!(s.version(), summary.version());
137 assert_eq!(s.name(), summary.name());
138
139 let replace = if s.source_id() == summary.source_id() {
140 debug!("Preventing\n{:?}\nfrom replacing\n{:?}", summary, s);
141 None
142 } else {
143 Some(s)
144 };
145 let matched_spec = spec.clone();
146
147 if let Some(&(ref spec, _)) = potential_matches.next() {
149 anyhow::bail!(
150 "overlapping replacement specifications found:\n\n \
151 * {}\n * {}\n\nboth specifications match: {}",
152 matched_spec,
153 spec,
154 summary.package_id()
155 );
156 }
157
158 for dep in summary.dependencies() {
159 debug!("\t{} => {}", dep.package_name(), dep.version_req());
160 }
161 if let Some(r) = replace {
162 self.used_replacements.insert(summary.package_id(), r);
163 }
164 }
165
166 ret.sort_unstable_by(|a, b| {
171 let a_in_previous = self.try_to_use.contains(&a.package_id());
172 let b_in_previous = self.try_to_use.contains(&b.package_id());
173 let previous_cmp = a_in_previous.cmp(&b_in_previous).reverse();
174 match previous_cmp {
175 Ordering::Equal => {
176 let cmp = a.version().cmp(b.version());
177 if self.minimal_versions {
178 cmp
180 } else {
181 cmp.reverse()
183 }
184 }
185 _ => previous_cmp,
186 }
187 });
188
189 let out = Rc::new(ret);
190
191 self.registry_cache.insert(dep.clone(), out.clone());
192
193 Ok(out)
194 }
195
196 pub fn build_deps(
201 &mut self,
202 cx: &Context,
203 parent: Option<PackageId>,
204 candidate: &Summary,
205 opts: &ResolveOpts,
206 ) -> ActivateResult<Rc<(HashSet<InternedString>, Rc<Vec<DepInfo>>)>> {
207 if let Some(out) = self
210 .summary_cache
211 .get(&(parent, candidate.clone(), opts.clone()))
212 .cloned()
213 {
214 return Ok(out);
215 }
216 let (used_features, deps) = resolve_features(parent, candidate, opts)?;
220
221 let mut deps = deps
224 .into_iter()
225 .map(|(dep, features)| {
226 let candidates = self.query(&dep).chain_err(|| {
227 anyhow::format_err!(
228 "failed to get `{}` as a dependency of {}",
229 dep.package_name(),
230 describe_path(&cx.parents.path_to_bottom(&candidate.package_id())),
231 )
232 })?;
233 Ok((dep, candidates, features))
234 })
235 .collect::<CargoResult<Vec<DepInfo>>>()?;
236
237 deps.sort_by_key(|&(_, ref a, _)| a.len());
242
243 let out = Rc::new((used_features, Rc::new(deps)));
244
245 self.summary_cache
248 .insert((parent, candidate.clone(), opts.clone()), out.clone());
249
250 Ok(out)
251 }
252}
253
254pub fn resolve_features<'b>(
257 parent: Option<PackageId>,
258 s: &'b Summary,
259 opts: &'b ResolveOpts,
260) -> ActivateResult<(HashSet<InternedString>, Vec<(Dependency, FeaturesSet)>)> {
261 let deps = s.dependencies();
263 let deps = deps.iter().filter(|d| d.is_transitive() || opts.dev_deps);
264
265 let reqs = build_requirements(s, opts)?;
266 let mut ret = Vec::new();
267 let mut used_features = HashSet::new();
268 let default_dep = (false, BTreeSet::new());
269
270 for dep in deps {
272 if dep.is_optional() && !reqs.deps.contains_key(&dep.name_in_toml()) {
275 continue;
276 }
277 let base = reqs.deps.get(&dep.name_in_toml()).unwrap_or(&default_dep);
281 used_features.insert(dep.name_in_toml());
282 let always_required = !dep.is_optional()
283 && !s
284 .dependencies()
285 .iter()
286 .any(|d| d.is_optional() && d.name_in_toml() == dep.name_in_toml());
287 if always_required && base.0 {
288 return Err(match parent {
289 None => anyhow::format_err!(
290 "Package `{}` does not have feature `{}`. It has a required dependency \
291 with that name, but only optional dependencies can be used as features.",
292 s.package_id(),
293 dep.name_in_toml()
294 )
295 .into(),
296 Some(p) => (
297 p,
298 ConflictReason::RequiredDependencyAsFeatures(dep.name_in_toml()),
299 )
300 .into(),
301 });
302 }
303 let mut base = base.1.clone();
304 base.extend(dep.features().iter());
305 for feature in base.iter() {
306 if feature.contains('/') {
307 return Err(anyhow::format_err!(
308 "feature names may not contain slashes: `{}`",
309 feature
310 )
311 .into());
312 }
313 }
314 ret.push((dep.clone(), Rc::new(base)));
315 }
316
317 let remaining = reqs
322 .deps
323 .keys()
324 .cloned()
325 .filter(|s| !used_features.contains(s))
326 .collect::<Vec<_>>();
327 if !remaining.is_empty() {
328 let features = remaining.join(", ");
329 return Err(match parent {
330 None => anyhow::format_err!(
331 "Package `{}` does not have these features: `{}`",
332 s.package_id(),
333 features
334 )
335 .into(),
336 Some(p) => (p, ConflictReason::MissingFeatures(features)).into(),
337 });
338 }
339
340 Ok((reqs.into_used(), ret))
341}
342
343fn build_requirements<'a, 'b: 'a>(
347 s: &'a Summary,
348 opts: &'b ResolveOpts,
349) -> CargoResult<Requirements<'a>> {
350 let mut reqs = Requirements::new(s);
351
352 if opts.features.all_features {
353 for key in s.features().keys() {
354 reqs.require_feature(*key)?;
355 }
356 for dep in s.dependencies().iter().filter(|d| d.is_optional()) {
357 reqs.require_dependency(dep.name_in_toml());
358 }
359 } else {
360 for &f in opts.features.features.iter() {
361 reqs.require_value(&FeatureValue::new(f, s))?;
362 }
363 }
364
365 if opts.features.uses_default_features && s.features().contains_key("default") {
366 reqs.require_feature(InternedString::new("default"))?;
367 }
368
369 Ok(reqs)
370}
371
372struct Requirements<'a> {
373 summary: &'a Summary,
374 deps: HashMap<InternedString, (bool, BTreeSet<InternedString>)>,
380 used: HashSet<InternedString>,
384 visited: HashSet<InternedString>,
385}
386
387impl Requirements<'_> {
388 fn new(summary: &Summary) -> Requirements<'_> {
389 Requirements {
390 summary,
391 deps: HashMap::new(),
392 used: HashSet::new(),
393 visited: HashSet::new(),
394 }
395 }
396
397 fn into_used(self) -> HashSet<InternedString> {
398 self.used
399 }
400
401 fn require_crate_feature(&mut self, package: InternedString, feat: InternedString) {
402 if let Some(dep) = self
406 .summary
407 .dependencies()
408 .iter()
409 .find(|p| p.name_in_toml() == package)
410 {
411 if dep.is_optional() {
412 self.used.insert(package);
413 }
414 }
415 self.deps
416 .entry(package)
417 .or_insert((false, BTreeSet::new()))
418 .1
419 .insert(feat);
420 }
421
422 fn seen(&mut self, feat: InternedString) -> bool {
423 if self.visited.insert(feat) {
424 self.used.insert(feat);
425 false
426 } else {
427 true
428 }
429 }
430
431 fn require_dependency(&mut self, pkg: InternedString) {
432 if self.seen(pkg) {
433 return;
434 }
435 self.deps.entry(pkg).or_insert((false, BTreeSet::new())).0 = true;
436 }
437
438 fn require_feature(&mut self, feat: InternedString) -> CargoResult<()> {
439 if feat.is_empty() || self.seen(feat) {
440 return Ok(());
441 }
442 for fv in self
443 .summary
444 .features()
445 .get(&feat)
446 .expect("must be a valid feature")
447 {
448 match *fv {
449 FeatureValue::Feature(ref dep_feat) if **dep_feat == *feat => anyhow::bail!(
450 "cyclic feature dependency: feature `{}` depends on itself",
451 feat
452 ),
453 _ => {}
454 }
455 self.require_value(fv)?;
456 }
457 Ok(())
458 }
459
460 fn require_value(&mut self, fv: &FeatureValue) -> CargoResult<()> {
461 match fv {
462 FeatureValue::Feature(feat) => self.require_feature(*feat)?,
463 FeatureValue::Crate(dep) => self.require_dependency(*dep),
464 FeatureValue::CrateFeature(dep, dep_feat) => {
465 self.require_crate_feature(*dep, *dep_feat)
466 }
467 };
468 Ok(())
469 }
470}