1use crate::core::resolver::context::ResolverContext;
13use crate::core::resolver::errors::describe_path_in_context;
14use crate::core::resolver::types::{ConflictReason, DepInfo, FeaturesSet};
15use crate::core::resolver::{
16 ActivateError, ActivateResult, CliFeatures, RequestedFeatures, ResolveOpts, VersionOrdering,
17 VersionPreferences,
18};
19use crate::core::{
20 Dependency, FeatureValue, PackageId, PackageIdSpec, PackageIdSpecQuery, Registry, Summary,
21};
22use crate::sources::source::QueryKind;
23use crate::util::closest_msg;
24use crate::util::errors::CargoResult;
25use crate::util::interning::{InternedString, INTERNED_DEFAULT};
26
27use anyhow::Context as _;
28use std::collections::{BTreeSet, HashMap, HashSet};
29use std::fmt::Write;
30use std::rc::Rc;
31use std::task::Poll;
32use tracing::debug;
33
34pub struct RegistryQueryer<'a> {
35 pub registry: &'a mut (dyn Registry + 'a),
36 replacements: &'a [(PackageIdSpec, Dependency)],
37 version_prefs: &'a VersionPreferences,
38 registry_cache: HashMap<(Dependency, Option<VersionOrdering>), Poll<Rc<Vec<Summary>>>>,
40 summary_cache: HashMap<
46 (Option<PackageId>, Summary, ResolveOpts),
47 (Rc<(HashSet<InternedString>, Rc<Vec<DepInfo>>)>, bool),
48 >,
49 used_replacements: HashMap<PackageId, Summary>,
51}
52
53impl<'a> RegistryQueryer<'a> {
54 pub fn new(
55 registry: &'a mut dyn Registry,
56 replacements: &'a [(PackageIdSpec, Dependency)],
57 version_prefs: &'a VersionPreferences,
58 ) -> Self {
59 RegistryQueryer {
60 registry,
61 replacements,
62 version_prefs,
63 registry_cache: HashMap::new(),
64 summary_cache: HashMap::new(),
65 used_replacements: HashMap::new(),
66 }
67 }
68
69 pub fn reset_pending(&mut self) -> bool {
70 let mut all_ready = true;
71 self.registry_cache.retain(|_, r| {
72 if !r.is_ready() {
73 all_ready = false;
74 }
75 r.is_ready()
76 });
77 self.summary_cache.retain(|_, (_, r)| {
78 if !*r {
79 all_ready = false;
80 }
81 *r
82 });
83 all_ready
84 }
85
86 pub fn used_replacement_for(&self, p: PackageId) -> Option<(PackageId, PackageId)> {
87 self.used_replacements.get(&p).map(|r| (p, r.package_id()))
88 }
89
90 pub fn replacement_summary(&self, p: PackageId) -> Option<&Summary> {
91 self.used_replacements.get(&p)
92 }
93
94 pub fn query(
101 &mut self,
102 dep: &Dependency,
103 first_version: Option<VersionOrdering>,
104 ) -> Poll<CargoResult<Rc<Vec<Summary>>>> {
105 let registry_cache_key = (dep.clone(), first_version);
106 if let Some(out) = self.registry_cache.get(®istry_cache_key).cloned() {
107 return out.map(Result::Ok);
108 }
109
110 let mut ret = Vec::new();
111 let ready = self.registry.query(dep, QueryKind::Exact, &mut |s| {
112 ret.push(s.into_summary());
113 })?;
114 if ready.is_pending() {
115 self.registry_cache
116 .insert((dep.clone(), first_version), Poll::Pending);
117 return Poll::Pending;
118 }
119 for summary in ret.iter() {
120 let mut potential_matches = self
121 .replacements
122 .iter()
123 .filter(|(spec, _)| spec.matches(summary.package_id()));
124
125 let Some((spec, dep)) = potential_matches.next() else {
126 continue;
127 };
128 debug!(
129 "found an override for {} {}",
130 dep.package_name(),
131 dep.version_req()
132 );
133
134 let mut summaries = match self.registry.query_vec(dep, QueryKind::Exact)? {
135 Poll::Ready(s) => s.into_iter(),
136 Poll::Pending => {
137 self.registry_cache
138 .insert((dep.clone(), first_version), Poll::Pending);
139 return Poll::Pending;
140 }
141 };
142 let s = summaries
143 .next()
144 .ok_or_else(|| {
145 anyhow::format_err!(
146 "no matching package for override `{}` found\n\
147 location searched: {}\n\
148 version required: {}",
149 spec,
150 dep.source_id(),
151 dep.version_req()
152 )
153 })?
154 .into_summary();
155 let summaries = summaries.collect::<Vec<_>>();
156 if !summaries.is_empty() {
157 let bullets = summaries
158 .iter()
159 .map(|s| format!(" * {}", s.package_id()))
160 .collect::<Vec<_>>();
161 return Poll::Ready(Err(anyhow::anyhow!(
162 "the replacement specification `{}` matched \
163 multiple packages:\n * {}\n{}",
164 spec,
165 s.package_id(),
166 bullets.join("\n")
167 )));
168 }
169
170 assert_eq!(
171 s.name(),
172 summary.name(),
173 "dependency should be hard coded to have the same name"
174 );
175 if s.version() != summary.version() {
176 return Poll::Ready(Err(anyhow::anyhow!(
177 "replacement specification `{}` matched {} and tried to override it with {}\n\
178 avoid matching unrelated packages by being more specific",
179 spec,
180 summary.version(),
181 s.version(),
182 )));
183 }
184
185 let replace = if s.source_id() == summary.source_id() {
186 debug!("Preventing\n{:?}\nfrom replacing\n{:?}", summary, s);
187 None
188 } else {
189 Some(s)
190 };
191 let matched_spec = spec.clone();
192
193 if let Some((spec, _)) = potential_matches.next() {
195 return Poll::Ready(Err(anyhow::anyhow!(
196 "overlapping replacement specifications found:\n\n \
197 * {}\n * {}\n\nboth specifications match: {}",
198 matched_spec,
199 spec,
200 summary.package_id()
201 )));
202 }
203
204 for dep in summary.dependencies() {
205 debug!("\t{} => {}", dep.package_name(), dep.version_req());
206 }
207 if let Some(r) = replace {
208 self.used_replacements.insert(summary.package_id(), r);
209 }
210 }
211
212 self.version_prefs.sort_summaries(&mut ret, first_version);
213
214 let out = Poll::Ready(Rc::new(ret));
215
216 self.registry_cache.insert(registry_cache_key, out.clone());
217
218 out.map(Result::Ok)
219 }
220
221 pub fn build_deps(
226 &mut self,
227 cx: &ResolverContext,
228 parent: Option<PackageId>,
229 candidate: &Summary,
230 opts: &ResolveOpts,
231 first_version: Option<VersionOrdering>,
232 ) -> ActivateResult<Rc<(HashSet<InternedString>, Rc<Vec<DepInfo>>)>> {
233 if let Some(out) = self
236 .summary_cache
237 .get(&(parent, candidate.clone(), opts.clone()))
238 {
239 return Ok(out.0.clone());
240 }
241 let (used_features, deps) = resolve_features(parent, candidate, opts)?;
245
246 let mut all_ready = true;
249 let mut deps = deps
250 .into_iter()
251 .filter_map(|(dep, features)| match self.query(&dep, first_version) {
252 Poll::Ready(Ok(candidates)) => Some(Ok((dep, candidates, features))),
253 Poll::Pending => {
254 all_ready = false;
255 None
258 }
259 Poll::Ready(Err(e)) => Some(Err(e).with_context(|| {
260 format!(
261 "failed to get `{}` as a dependency of {}",
262 dep.package_name(),
263 describe_path_in_context(cx, &candidate.package_id()),
264 )
265 })),
266 })
267 .collect::<CargoResult<Vec<DepInfo>>>()?;
268
269 deps.sort_by_key(|(_, a, _)| a.len());
274
275 let out = Rc::new((used_features, Rc::new(deps)));
276
277 self.summary_cache.insert(
280 (parent, candidate.clone(), opts.clone()),
281 (out.clone(), all_ready),
282 );
283
284 Ok(out)
285 }
286}
287
288pub fn resolve_features<'b>(
291 parent: Option<PackageId>,
292 s: &'b Summary,
293 opts: &'b ResolveOpts,
294) -> ActivateResult<(HashSet<InternedString>, Vec<(Dependency, FeaturesSet)>)> {
295 let deps = s.dependencies();
297 let deps = deps.iter().filter(|d| d.is_transitive() || opts.dev_deps);
298
299 let reqs = build_requirements(parent, s, opts)?;
300 let mut ret = Vec::new();
301 let default_dep = BTreeSet::new();
302 let mut valid_dep_names = HashSet::new();
303
304 for dep in deps {
306 if dep.is_optional() && !reqs.deps.contains_key(&dep.name_in_toml()) {
309 continue;
310 }
311 valid_dep_names.insert(dep.name_in_toml());
312 let mut base = reqs
316 .deps
317 .get(&dep.name_in_toml())
318 .unwrap_or(&default_dep)
319 .clone();
320 base.extend(dep.features().iter());
321 ret.push((dep.clone(), Rc::new(base)));
322 }
323
324 if parent.is_none() {
329 for dep_name in reqs.deps.keys() {
330 if !valid_dep_names.contains(dep_name) {
331 let e = RequirementError::MissingDependency(*dep_name);
332 return Err(e.into_activate_error(parent, s));
333 }
334 }
335 }
336
337 Ok((reqs.into_features(), ret))
338}
339
340fn build_requirements<'a, 'b: 'a>(
344 parent: Option<PackageId>,
345 s: &'a Summary,
346 opts: &'b ResolveOpts,
347) -> ActivateResult<Requirements<'a>> {
348 let mut reqs = Requirements::new(s);
349
350 let handle_default = |uses_default_features, reqs: &mut Requirements<'_>| {
351 if uses_default_features && s.features().contains_key("default") {
352 if let Err(e) = reqs.require_feature(INTERNED_DEFAULT) {
353 return Err(e.into_activate_error(parent, s));
354 }
355 }
356 Ok(())
357 };
358
359 match &opts.features {
360 RequestedFeatures::CliFeatures(CliFeatures {
361 features,
362 all_features,
363 uses_default_features,
364 }) => {
365 if *all_features {
366 for key in s.features().keys() {
367 if let Err(e) = reqs.require_feature(*key) {
368 return Err(e.into_activate_error(parent, s));
369 }
370 }
371 }
372
373 for fv in features.iter() {
374 if let Err(e) = reqs.require_value(fv) {
375 return Err(e.into_activate_error(parent, s));
376 }
377 }
378 handle_default(*uses_default_features, &mut reqs)?;
379 }
380 RequestedFeatures::DepFeatures {
381 features,
382 uses_default_features,
383 } => {
384 for feature in features.iter() {
385 if let Err(e) = reqs.require_feature(*feature) {
386 return Err(e.into_activate_error(parent, s));
387 }
388 }
389 handle_default(*uses_default_features, &mut reqs)?;
390 }
391 }
392
393 Ok(reqs)
394}
395
396#[derive(Debug)]
398struct Requirements<'a> {
399 summary: &'a Summary,
400 deps: HashMap<InternedString, BTreeSet<InternedString>>,
405 features: HashSet<InternedString>,
408}
409
410enum RequirementError {
415 MissingFeature(InternedString),
417 MissingDependency(InternedString),
419 Cycle(InternedString),
424}
425
426impl Requirements<'_> {
427 fn new(summary: &Summary) -> Requirements<'_> {
428 Requirements {
429 summary,
430 deps: HashMap::new(),
431 features: HashSet::new(),
432 }
433 }
434
435 fn into_features(self) -> HashSet<InternedString> {
436 self.features
437 }
438
439 fn require_dep_feature(
440 &mut self,
441 package: InternedString,
442 feat: InternedString,
443 weak: bool,
444 ) -> Result<(), RequirementError> {
445 if !weak
449 && self
450 .summary
451 .dependencies()
452 .iter()
453 .any(|dep| dep.name_in_toml() == package && dep.is_optional())
454 {
455 if self.summary.features().contains_key(&package) {
459 self.require_feature(package)?;
460 }
461 }
462 self.deps.entry(package).or_default().insert(feat);
463 Ok(())
464 }
465
466 fn require_dependency(&mut self, pkg: InternedString) {
467 self.deps.entry(pkg).or_default();
468 }
469
470 fn require_feature(&mut self, feat: InternedString) -> Result<(), RequirementError> {
471 if !self.features.insert(feat) {
472 return Ok(());
474 }
475
476 let Some(fvs) = self.summary.features().get(&feat) else {
477 return Err(RequirementError::MissingFeature(feat));
478 };
479
480 for fv in fvs {
481 if let FeatureValue::Feature(dep_feat) = fv {
482 if *dep_feat == feat {
483 return Err(RequirementError::Cycle(feat));
484 }
485 }
486 self.require_value(fv)?;
487 }
488 Ok(())
489 }
490
491 fn require_value(&mut self, fv: &FeatureValue) -> Result<(), RequirementError> {
492 match fv {
493 FeatureValue::Feature(feat) => self.require_feature(*feat)?,
494 FeatureValue::Dep { dep_name } => self.require_dependency(*dep_name),
495 FeatureValue::DepFeature {
496 dep_name,
497 dep_feature,
498 weak,
502 } => self.require_dep_feature(*dep_name, *dep_feature, *weak)?,
503 };
504 Ok(())
505 }
506}
507
508impl RequirementError {
509 fn into_activate_error(self, parent: Option<PackageId>, summary: &Summary) -> ActivateError {
510 match self {
511 RequirementError::MissingFeature(feat) => {
512 let deps: Vec<_> = summary
513 .dependencies()
514 .iter()
515 .filter(|dep| dep.name_in_toml() == feat)
516 .collect();
517 if deps.is_empty() {
518 return match parent {
519 None => {
520 let closest = closest_msg(
521 &feat.as_str(),
522 summary.features().keys(),
523 |key| &key,
524 "feature",
525 );
526 ActivateError::Fatal(anyhow::format_err!(
527 "Package `{}` does not have the feature `{}`{}",
528 summary.package_id(),
529 feat,
530 closest
531 ))
532 }
533 Some(p) => {
534 ActivateError::Conflict(p, ConflictReason::MissingFeatures(feat))
535 }
536 };
537 }
538 if deps.iter().any(|dep| dep.is_optional()) {
539 match parent {
540 None => {
541 let mut features =
542 features_enabling_dependency_sorted(summary, feat).peekable();
543 let mut suggestion = String::new();
544 if features.peek().is_some() {
545 suggestion = format!(
546 "\nDependency `{}` would be enabled by these features:",
547 feat
548 );
549 for feature in (&mut features).take(3) {
550 let _ = write!(&mut suggestion, "\n\t- `{}`", feature);
551 }
552 if features.peek().is_some() {
553 suggestion.push_str("\n\t ...");
554 }
555 }
556 ActivateError::Fatal(anyhow::format_err!(
557 "\
558Package `{}` does not have feature `{}`. It has an optional dependency \
559with that name, but that dependency uses the \"dep:\" \
560syntax in the features table, so it does not have an implicit feature with that name.{}",
561 summary.package_id(),
562 feat,
563 suggestion
564 ))
565 }
566 Some(p) => ActivateError::Conflict(
567 p,
568 ConflictReason::NonImplicitDependencyAsFeature(feat),
569 ),
570 }
571 } else {
572 match parent {
573 None => ActivateError::Fatal(anyhow::format_err!(
574 "Package `{}` does not have feature `{}`. It has a required dependency \
575 with that name, but only optional dependencies can be used as features.",
576 summary.package_id(),
577 feat,
578 )),
579 Some(p) => ActivateError::Conflict(
580 p,
581 ConflictReason::RequiredDependencyAsFeature(feat),
582 ),
583 }
584 }
585 }
586 RequirementError::MissingDependency(dep_name) => {
587 match parent {
588 None => ActivateError::Fatal(anyhow::format_err!(
589 "package `{}` does not have a dependency named `{}`",
590 summary.package_id(),
591 dep_name
592 )),
593 Some(p) => {
596 ActivateError::Conflict(p, ConflictReason::MissingFeatures(dep_name))
597 }
598 }
599 }
600 RequirementError::Cycle(feat) => ActivateError::Fatal(anyhow::format_err!(
601 "cyclic feature dependency: feature `{}` depends on itself",
602 feat
603 )),
604 }
605 }
606}
607
608fn features_enabling_dependency_sorted(
612 summary: &Summary,
613 target_dep: InternedString,
614) -> impl Iterator<Item = InternedString> + '_ {
615 let iter = summary
616 .features()
617 .iter()
618 .filter(move |(_, values)| {
619 for value in *values {
620 match value {
621 FeatureValue::Dep { dep_name }
622 | FeatureValue::DepFeature {
623 dep_name,
624 weak: false,
625 ..
626 } if dep_name == &target_dep => return true,
627 _ => (),
628 }
629 }
630 false
631 })
632 .map(|(name, _)| *name);
633 iter
635}