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