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