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::IndexSummary;
23use crate::sources::source::QueryKind;
24use crate::util::LocalPollAdapter;
25use crate::util::closest_msg;
26use crate::util::errors::CargoResult;
27use crate::util::interning::{INTERNED_DEFAULT, InternedString};
28
29use anyhow::Context as _;
30use std::cell::RefCell;
31use std::collections::{BTreeSet, HashMap, HashSet};
32use std::fmt::Write;
33use std::rc::Rc;
34use std::task::Poll;
35use tracing::debug;
36
37pub struct RegistryQueryerAsync<'a, T: Registry> {
38 pub registry: &'a T,
39 replacements: &'a [(PackageIdSpec, Dependency)],
40 version_prefs: &'a VersionPreferences,
41 used_replacements: RefCell<HashMap<PackageId, Summary>>,
43}
44
45impl<'a, T: Registry> RegistryQueryerAsync<'a, T> {
46 pub fn new(
47 registry: &'a T,
48 replacements: &'a [(PackageIdSpec, Dependency)],
49 version_prefs: &'a VersionPreferences,
50 ) -> Self {
51 RegistryQueryerAsync {
52 registry,
53 replacements,
54 version_prefs,
55 used_replacements: RefCell::new(HashMap::new()),
56 }
57 }
58
59 async fn query(
66 &self,
67 key: &(Dependency, Option<VersionOrdering>),
68 ) -> CargoResult<Rc<Vec<Summary>>> {
69 let (dep, first_version) = key;
70 let mut summaries = Vec::new();
71 self.registry
72 .query(dep, QueryKind::Exact, &mut |s| match s {
73 IndexSummary::Candidate(summary) => summaries.push(summary),
74 IndexSummary::Yanked(summary) => {
79 let pkg_id = summary.package_id();
80 let allow_precise = pkg_id
81 .source_id()
82 .precise_registry_version(pkg_id.name().as_str())
83 .is_some_and(|(_, to)| to == pkg_id.version());
84 if allow_precise || self.version_prefs.should_prefer(&pkg_id) {
85 summaries.push(summary);
86 }
87 }
88 _ => {}
89 })
90 .await?;
91
92 for summary in summaries.iter() {
93 let mut potential_matches = self
94 .replacements
95 .iter()
96 .filter(|(spec, _)| spec.matches(summary.package_id()));
97
98 let Some((spec, dep)) = potential_matches.next() else {
99 continue;
100 };
101 debug!(
102 "found an override for {} {}",
103 dep.package_name(),
104 dep.version_req()
105 );
106
107 let mut summaries = self
108 .registry
109 .query_vec(dep, QueryKind::Exact)
110 .await?
111 .into_iter()
112 .filter_map(|s| match s {
113 IndexSummary::Candidate(s) => Some(s),
114 _ => None,
115 });
116 let s = summaries.next().ok_or_else(|| {
117 anyhow::format_err!(
118 "no matching package for override `{}` found\n\
119 location searched: {}\n\
120 version required: {}",
121 spec,
122 dep.source_id(),
123 dep.version_req()
124 )
125 })?;
126 let summaries = summaries.collect::<Vec<_>>();
127 if !summaries.is_empty() {
128 let bullets = summaries
129 .iter()
130 .map(|s| format!(" * {}", s.package_id()))
131 .collect::<Vec<_>>();
132 return Err(anyhow::anyhow!(
133 "the replacement specification `{}` matched \
134 multiple packages:\n * {}\n{}",
135 spec,
136 s.package_id(),
137 bullets.join("\n")
138 ));
139 }
140
141 assert_eq!(
142 s.name(),
143 summary.name(),
144 "dependency should be hard coded to have the same name"
145 );
146 if s.version() != summary.version() {
147 return Err(anyhow::anyhow!(
148 "replacement specification `{}` matched {} and tried to override it with {}\n\
149 avoid matching unrelated packages by being more specific",
150 spec,
151 summary.version(),
152 s.version(),
153 ));
154 }
155
156 let replace = if s.source_id() == summary.source_id() {
157 debug!("Preventing\n{:?}\nfrom replacing\n{:?}", summary, s);
158 None
159 } else {
160 Some(s)
161 };
162 let matched_spec = spec.clone();
163
164 if let Some((spec, _)) = potential_matches.next() {
166 return Err(anyhow::anyhow!(
167 "overlapping replacement specifications found:\n\n \
168 * {}\n * {}\n\nboth specifications match: {}",
169 matched_spec,
170 spec,
171 summary.package_id()
172 ));
173 }
174
175 for dep in summary.dependencies() {
176 debug!("\t{} => {}", dep.package_name(), dep.version_req());
177 }
178 if let Some(r) = replace {
179 self.used_replacements
180 .borrow_mut()
181 .insert(summary.package_id(), r);
182 }
183 }
184
185 self.version_prefs
186 .sort_summaries(&mut summaries, *first_version);
187 Ok(Rc::new(summaries))
188 }
189}
190
191pub struct RegistryQueryer<'a, T: Registry> {
194 inner: Rc<RegistryQueryerAsync<'a, T>>,
195 poller: LocalPollAdapter<
196 'a,
197 Rc<RegistryQueryerAsync<'a, T>>,
198 (Dependency, Option<VersionOrdering>),
199 CargoResult<Rc<Vec<Summary>>>,
200 >,
201
202 summary_cache: HashMap<
208 (Option<PackageId>, Summary, ResolveOpts),
209 (Rc<(HashSet<InternedString>, Rc<Vec<DepInfo>>)>, bool),
210 >,
211}
212
213impl<'a, T: Registry> RegistryQueryer<'a, T> {
214 pub fn new(
215 registry: &'a T,
216 replacements: &'a [(PackageIdSpec, Dependency)],
217 version_prefs: &'a VersionPreferences,
218 ) -> Self {
219 let inner = Rc::new(RegistryQueryerAsync::new(
220 registry,
221 replacements,
222 version_prefs,
223 ));
224 Self {
225 inner: inner.clone(),
226 poller: LocalPollAdapter::new(inner),
227 summary_cache: HashMap::new(),
228 }
229 }
230
231 pub fn registry(&self) -> &T {
232 self.inner.registry
233 }
234
235 pub fn query(
236 &mut self,
237 dep: &Dependency,
238 first_version: Option<VersionOrdering>,
239 ) -> Poll<CargoResult<Rc<Vec<Summary>>>> {
240 self.poller
241 .poll(RegistryQueryerAsync::query, (dep.clone(), first_version))
242 }
243
244 pub fn wait(&mut self) -> CargoResult<bool> {
245 let pending = self.poller.pending_count();
246 let mut all_ready = self.poller.wait();
248 debug!(target: "cargo::core::resolver::restarting", pending);
249
250 self.summary_cache.retain(|_, (_, r)| {
252 if !*r {
253 all_ready = false;
254 }
255 *r
256 });
257
258 Ok(all_ready)
259 }
260
261 pub fn used_replacement_for(&self, p: PackageId) -> Option<(PackageId, PackageId)> {
262 self.inner
263 .used_replacements
264 .borrow()
265 .get(&p)
266 .map(|r| (p, r.package_id()))
267 }
268
269 pub fn replacement_summary(&self, p: PackageId) -> Option<Summary> {
270 self.inner.used_replacements.borrow().get(&p).cloned()
271 }
272
273 pub fn build_deps(
278 &mut self,
279 cx: &ResolverContext,
280 parent: Option<PackageId>,
281 candidate: &Summary,
282 opts: &ResolveOpts,
283 first_version: Option<VersionOrdering>,
284 ) -> ActivateResult<Rc<(HashSet<InternedString>, Rc<Vec<DepInfo>>)>> {
285 if let Some(out) = self
288 .summary_cache
289 .get(&(parent, candidate.clone(), opts.clone()))
290 {
291 return Ok(out.0.clone());
292 }
293 let (used_features, deps) = resolve_features(parent, candidate, opts)?;
297
298 let mut all_ready = true;
301 let mut deps = deps
302 .into_iter()
303 .filter_map(|(dep, features)| match self.query(&dep, first_version) {
304 Poll::Ready(Ok(candidates)) => Some(Ok((dep, candidates, features))),
305 Poll::Pending => {
306 all_ready = false;
307 None
310 }
311 Poll::Ready(Err(e)) => Some(Err(e).with_context(|| {
312 format!(
313 "failed to get `{}` as a dependency of {}",
314 dep.package_name(),
315 describe_path_in_context(cx, &candidate.package_id()),
316 )
317 })),
318 })
319 .collect::<CargoResult<Vec<DepInfo>>>()?;
320
321 deps.sort_by_key(|(_, a, _)| a.len());
326
327 let out = Rc::new((used_features, Rc::new(deps)));
328
329 self.summary_cache.insert(
332 (parent, candidate.clone(), opts.clone()),
333 (out.clone(), all_ready),
334 );
335
336 Ok(out)
337 }
338}
339
340pub fn resolve_features<'b>(
343 parent: Option<PackageId>,
344 s: &'b Summary,
345 opts: &'b ResolveOpts,
346) -> ActivateResult<(HashSet<InternedString>, Vec<(Dependency, FeaturesSet)>)> {
347 let deps = s.dependencies();
349 let deps = deps.iter().filter(|d| d.is_transitive() || opts.dev_deps);
350
351 let reqs = build_requirements(parent, s, opts)?;
352 let mut ret = Vec::new();
353 let default_dep = BTreeSet::new();
354 let mut valid_dep_names = HashSet::new();
355
356 for dep in deps {
358 if dep.is_optional() && !reqs.deps.contains_key(&dep.name_in_toml()) {
361 continue;
362 }
363 valid_dep_names.insert(dep.name_in_toml());
364 let mut base = reqs
368 .deps
369 .get(&dep.name_in_toml())
370 .unwrap_or(&default_dep)
371 .clone();
372 base.extend(dep.features().iter());
373 ret.push((dep.clone(), Rc::new(base)));
374 }
375
376 if parent.is_none() {
381 for dep_name in reqs.deps.keys() {
382 if !valid_dep_names.contains(dep_name) {
383 let e = RequirementError::MissingDependency(*dep_name);
384 return Err(e.into_activate_error(parent, s));
385 }
386 }
387 }
388
389 Ok((reqs.into_features(), ret))
390}
391
392fn build_requirements<'a, 'b: 'a>(
396 parent: Option<PackageId>,
397 s: &'a Summary,
398 opts: &'b ResolveOpts,
399) -> ActivateResult<Requirements<'a>> {
400 let mut reqs = Requirements::new(s);
401
402 let handle_default = |uses_default_features, reqs: &mut Requirements<'_>| {
403 if uses_default_features && s.features().contains_key("default") {
404 if let Err(e) = reqs.require_feature(INTERNED_DEFAULT) {
405 return Err(e.into_activate_error(parent, s));
406 }
407 }
408 Ok(())
409 };
410
411 match &opts.features {
412 RequestedFeatures::CliFeatures(CliFeatures {
413 features,
414 all_features,
415 uses_default_features,
416 }) => {
417 if *all_features {
418 for key in s.features().keys() {
419 if let Err(e) = reqs.require_feature(*key) {
420 return Err(e.into_activate_error(parent, s));
421 }
422 }
423 }
424
425 for fv in features.iter() {
426 if let Err(e) = reqs.require_value(fv) {
427 return Err(e.into_activate_error(parent, s));
428 }
429 }
430 handle_default(*uses_default_features, &mut reqs)?;
431 }
432 RequestedFeatures::DepFeatures {
433 features,
434 uses_default_features,
435 } => {
436 for feature in features.iter() {
437 if let Err(e) = reqs.require_feature(*feature) {
438 return Err(e.into_activate_error(parent, s));
439 }
440 }
441 handle_default(*uses_default_features, &mut reqs)?;
442 }
443 }
444
445 Ok(reqs)
446}
447
448#[derive(Debug)]
450struct Requirements<'a> {
451 summary: &'a Summary,
452 deps: HashMap<InternedString, BTreeSet<InternedString>>,
457 features: HashSet<InternedString>,
460}
461
462enum RequirementError {
467 MissingFeature(InternedString),
469 MissingDependency(InternedString),
471 Cycle(InternedString),
476}
477
478impl Requirements<'_> {
479 fn new(summary: &Summary) -> Requirements<'_> {
480 Requirements {
481 summary,
482 deps: HashMap::new(),
483 features: HashSet::new(),
484 }
485 }
486
487 fn into_features(self) -> HashSet<InternedString> {
488 self.features
489 }
490
491 fn require_dep_feature(
492 &mut self,
493 package: InternedString,
494 feat: InternedString,
495 weak: bool,
496 ) -> Result<(), RequirementError> {
497 if !weak
501 && self
502 .summary
503 .dependencies()
504 .iter()
505 .any(|dep| dep.name_in_toml() == package && dep.is_optional())
506 {
507 if self.summary.features().contains_key(&package) {
511 self.require_feature(package)?;
512 }
513 }
514 self.deps.entry(package).or_default().insert(feat);
515 Ok(())
516 }
517
518 fn require_dependency(&mut self, pkg: InternedString) {
519 self.deps.entry(pkg).or_default();
520 }
521
522 fn require_feature(&mut self, feat: InternedString) -> Result<(), RequirementError> {
523 if !self.features.insert(feat) {
524 return Ok(());
526 }
527
528 let Some(fvs) = self.summary.features().get(&feat) else {
529 return Err(RequirementError::MissingFeature(feat));
530 };
531
532 for fv in fvs {
533 if let FeatureValue::Feature(dep_feat) = fv {
534 if *dep_feat == feat {
535 return Err(RequirementError::Cycle(feat));
536 }
537 }
538 self.require_value(fv)?;
539 }
540 Ok(())
541 }
542
543 fn require_value(&mut self, fv: &FeatureValue) -> Result<(), RequirementError> {
544 match fv {
545 FeatureValue::Feature(feat) => self.require_feature(*feat)?,
546 FeatureValue::Dep { dep_name } => self.require_dependency(*dep_name),
547 FeatureValue::DepFeature {
548 dep_name,
549 dep_feature,
550 weak,
554 } => self.require_dep_feature(*dep_name, *dep_feature, *weak)?,
555 };
556 Ok(())
557 }
558}
559
560impl RequirementError {
561 fn into_activate_error(self, parent: Option<PackageId>, summary: &Summary) -> ActivateError {
562 match self {
563 RequirementError::MissingFeature(feat) => {
564 let deps: Vec<_> = summary
565 .dependencies()
566 .iter()
567 .filter(|dep| dep.name_in_toml() == feat)
568 .collect();
569 if deps.is_empty() {
570 return match parent {
571 None => {
572 let closest = closest_msg(
573 &feat.as_str(),
574 summary.features().keys(),
575 |key| &key,
576 "feature",
577 );
578 ActivateError::Fatal(anyhow::format_err!(
579 "package `{}` does not have the feature `{}`{}",
580 summary.package_id(),
581 feat,
582 closest
583 ))
584 }
585 Some(p) => ActivateError::Conflict(p, ConflictReason::MissingFeature(feat)),
586 };
587 }
588 if deps.iter().any(|dep| dep.is_optional()) {
589 match parent {
590 None => {
591 let mut features =
592 features_enabling_dependency_sorted(summary, feat).peekable();
593 let mut suggestion = String::new();
594 if features.peek().is_some() {
595 suggestion = format!(
596 "\nDependency `{}` would be enabled by these features:",
597 feat
598 );
599 for feature in (&mut features).take(3) {
600 let _ = write!(&mut suggestion, "\n\t- `{}`", feature);
601 }
602 if features.peek().is_some() {
603 suggestion.push_str("\n\t ...");
604 }
605 }
606 ActivateError::Fatal(anyhow::format_err!(
607 "\
608package `{}` does not have feature `{}`
609
610help: an optional dependency \
611with that name exists, but the `features` table includes it with the \"dep:\" \
612syntax so it does not have an implicit feature with that name{}",
613 summary.package_id(),
614 feat,
615 suggestion
616 ))
617 }
618 Some(p) => ActivateError::Conflict(
619 p,
620 ConflictReason::NonImplicitDependencyAsFeature(feat),
621 ),
622 }
623 } else {
624 match parent {
625 None => ActivateError::Fatal(anyhow::format_err!(
626 "package `{}` does not have feature `{}`
627
628help: a dependency with that name exists but it is required dependency and only optional dependencies can be used as features.",
629 summary.package_id(),
630 feat,
631 )),
632 Some(p) => ActivateError::Conflict(
633 p,
634 ConflictReason::RequiredDependencyAsFeature(feat),
635 ),
636 }
637 }
638 }
639 RequirementError::MissingDependency(dep_name) => {
640 match parent {
641 None => ActivateError::Fatal(anyhow::format_err!(
642 "package `{}` does not have a dependency named `{}`",
643 summary.package_id(),
644 dep_name
645 )),
646 Some(p) => ActivateError::Conflict(p, ConflictReason::MissingFeature(dep_name)),
649 }
650 }
651 RequirementError::Cycle(feat) => ActivateError::Fatal(anyhow::format_err!(
652 "cyclic feature dependency: feature `{}` depends on itself",
653 feat
654 )),
655 }
656 }
657}
658
659fn features_enabling_dependency_sorted(
663 summary: &Summary,
664 target_dep: InternedString,
665) -> impl Iterator<Item = InternedString> + '_ {
666 let iter = summary
667 .features()
668 .iter()
669 .filter(move |(_, values)| {
670 for value in *values {
671 match value {
672 FeatureValue::Dep { dep_name }
673 | FeatureValue::DepFeature {
674 dep_name,
675 weak: false,
676 ..
677 } if dep_name == &target_dep => return true,
678 _ => (),
679 }
680 }
681 false
682 })
683 .map(|(name, _)| *name);
684 iter
686}