Skip to content

Commit e26ef01

Browse files
committed
Refactor resolve Method
1 parent 137a36f commit e26ef01

17 files changed

+246
-210
lines changed

crates/resolver-tests/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::rc::Rc;
88
use std::time::Instant;
99

1010
use cargo::core::dependency::Kind;
11-
use cargo::core::resolver::{self, Method};
11+
use cargo::core::resolver::{self, ResolveOpts};
1212
use cargo::core::source::{GitReference, SourceId};
1313
use cargo::core::Resolve;
1414
use cargo::core::{Dependency, PackageId, Registry, Summary};
@@ -175,10 +175,10 @@ pub fn resolve_with_config_raw(
175175
false,
176176
)
177177
.unwrap();
178-
let method = Method::Everything;
178+
let opts = ResolveOpts::everything();
179179
let start = Instant::now();
180180
let resolve = resolver::resolve(
181-
&[(summary, method)],
181+
&[(summary, opts)],
182182
&[],
183183
&mut registry,
184184
&HashSet::new(),

src/cargo/core/compiler/layout.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! The directory layout is a little tricky at times, hence a separate file to
44
//! house this logic. The current layout looks like this:
55
//!
6-
//! ```ignore
6+
//! ```text
77
//! # This is the root directory for all output, the top-level package
88
//! # places all of its output here.
99
//! target/

src/cargo/core/resolver/context.rs

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::util::CargoResult;
1313
use crate::util::Graph;
1414

1515
use super::dep_cache::RegistryQueryer;
16-
use super::types::{ConflictMap, FeaturesSet, Method};
16+
use super::types::{ConflictMap, FeaturesSet, ResolveOpts};
1717

1818
pub use super::encode::Metadata;
1919
pub use super::encode::{EncodableDependency, EncodablePackageId, EncodableResolve};
@@ -103,11 +103,11 @@ impl Context {
103103
/// cased `summary` to get activated. This may not be present for the root
104104
/// crate, for example.
105105
///
106-
/// Returns `true` if this summary with the given method is already activated.
106+
/// Returns `true` if this summary with the given features is already activated.
107107
pub fn flag_activated(
108108
&mut self,
109109
summary: &Summary,
110-
method: &Method,
110+
opts: &ResolveOpts,
111111
parent: Option<(&Summary, &Dependency)>,
112112
) -> CargoResult<bool> {
113113
let id = summary.package_id();
@@ -158,25 +158,21 @@ impl Context {
158158
}
159159
}
160160
debug!("checking if {} is already activated", summary.package_id());
161-
let (features, use_default) = match method {
162-
Method::Everything
163-
| Method::Required {
164-
all_features: true, ..
165-
} => return Ok(false),
166-
Method::Required {
167-
features,
168-
uses_default_features,
169-
..
170-
} => (features, uses_default_features),
171-
};
161+
if opts.all_features {
162+
return Ok(false);
163+
}
172164

173165
let has_default_feature = summary.features().contains_key("default");
174166
Ok(match self.resolve_features.get(&id) {
175167
Some(prev) => {
176-
features.is_subset(prev)
177-
&& (!use_default || prev.contains("default") || !has_default_feature)
168+
opts.features.is_subset(prev)
169+
&& (!opts.uses_default_features
170+
|| prev.contains("default")
171+
|| !has_default_feature)
172+
}
173+
None => {
174+
opts.features.is_empty() && (!opts.uses_default_features || !has_default_feature)
178175
}
179-
None => features.is_empty() && (!use_default || !has_default_feature),
180176
})
181177
}
182178

src/cargo/core/resolver/dep_cache.rs

Lines changed: 26 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use crate::core::{Dependency, FeatureValue, PackageId, PackageIdSpec, Registry,
2020
use crate::util::errors::CargoResult;
2121

2222
use crate::core::resolver::types::{ConflictReason, DepInfo, FeaturesSet};
23-
use crate::core::resolver::{ActivateResult, Method};
23+
use crate::core::resolver::{ActivateResult, ResolveOpts};
2424

2525
pub struct RegistryQueryer<'a> {
2626
pub registry: &'a mut (dyn Registry + 'a),
@@ -34,7 +34,7 @@ pub struct RegistryQueryer<'a> {
3434
registry_cache: HashMap<Dependency, Rc<Vec<Summary>>>,
3535
/// a cache of `Dependency`s that are required for a `Summary`
3636
summary_cache: HashMap<
37-
(Option<PackageId>, Summary, Method),
37+
(Option<PackageId>, Summary, ResolveOpts),
3838
Rc<(HashSet<InternedString>, Rc<Vec<DepInfo>>)>,
3939
>,
4040
/// all the cases we ended up using a supplied replacement
@@ -192,28 +192,28 @@ impl<'a> RegistryQueryer<'a> {
192192
}
193193

194194
/// Find out what dependencies will be added by activating `candidate`,
195-
/// with features described in `method`. Then look up in the `registry`
195+
/// with features described in `opts`. Then look up in the `registry`
196196
/// the candidates that will fulfil each of these dependencies, as it is the
197197
/// next obvious question.
198198
pub fn build_deps(
199199
&mut self,
200200
parent: Option<PackageId>,
201201
candidate: &Summary,
202-
method: &Method,
202+
opts: &ResolveOpts,
203203
) -> ActivateResult<Rc<(HashSet<InternedString>, Rc<Vec<DepInfo>>)>> {
204204
// if we have calculated a result before, then we can just return it,
205205
// as it is a "pure" query of its arguments.
206206
if let Some(out) = self
207207
.summary_cache
208-
.get(&(parent, candidate.clone(), method.clone()))
208+
.get(&(parent, candidate.clone(), opts.clone()))
209209
.cloned()
210210
{
211211
return Ok(out);
212212
}
213213
// First, figure out our set of dependencies based on the requested set
214214
// of features. This also calculates what features we're going to enable
215215
// for our own dependencies.
216-
let (used_features, deps) = resolve_features(parent, candidate, method)?;
216+
let (used_features, deps) = resolve_features(parent, candidate, opts)?;
217217

218218
// Next, transform all dependencies into a list of possible candidates
219219
// which can satisfy that dependency.
@@ -236,7 +236,7 @@ impl<'a> RegistryQueryer<'a> {
236236
// If we succeed we add the result to the cache so we can use it again next time.
237237
// We dont cache the failure cases as they dont impl Clone.
238238
self.summary_cache
239-
.insert((parent, candidate.clone(), method.clone()), out.clone());
239+
.insert((parent, candidate.clone(), opts.clone()), out.clone());
240240

241241
Ok(out)
242242
}
@@ -247,18 +247,13 @@ impl<'a> RegistryQueryer<'a> {
247247
pub fn resolve_features<'b>(
248248
parent: Option<PackageId>,
249249
s: &'b Summary,
250-
method: &'b Method,
250+
opts: &'b ResolveOpts,
251251
) -> ActivateResult<(HashSet<InternedString>, Vec<(Dependency, FeaturesSet)>)> {
252-
let dev_deps = match *method {
253-
Method::Everything => true,
254-
Method::Required { dev_deps, .. } => dev_deps,
255-
};
256-
257252
// First, filter by dev-dependencies.
258253
let deps = s.dependencies();
259-
let deps = deps.iter().filter(|d| d.is_transitive() || dev_deps);
254+
let deps = deps.iter().filter(|d| d.is_transitive() || opts.dev_deps);
260255

261-
let reqs = build_requirements(s, method)?;
256+
let reqs = build_requirements(s, opts)?;
262257
let mut ret = Vec::new();
263258
let mut used_features = HashSet::new();
264259
let default_dep = (false, BTreeSet::new());
@@ -336,52 +331,34 @@ pub fn resolve_features<'b>(
336331
Ok((reqs.into_used(), ret))
337332
}
338333

339-
/// Takes requested features for a single package from the input `Method` and
334+
/// Takes requested features for a single package from the input `ResolveOpts` and
340335
/// recurses to find all requested features, dependencies and requested
341336
/// dependency features in a `Requirements` object, returning it to the resolver.
342337
fn build_requirements<'a, 'b: 'a>(
343338
s: &'a Summary,
344-
method: &'b Method,
339+
opts: &'b ResolveOpts,
345340
) -> CargoResult<Requirements<'a>> {
346341
let mut reqs = Requirements::new(s);
347342

348-
match method {
349-
Method::Everything
350-
| Method::Required {
351-
all_features: true, ..
352-
} => {
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-
}
343+
if opts.all_features {
344+
for key in s.features().keys() {
345+
reqs.require_feature(*key)?;
359346
}
360-
Method::Required {
361-
all_features: false,
362-
features: requested,
363-
..
364-
} => {
365-
for &f in requested.iter() {
366-
reqs.require_value(&FeatureValue::new(f, s))?;
367-
}
347+
for dep in s.dependencies().iter().filter(|d| d.is_optional()) {
348+
reqs.require_dependency(dep.name_in_toml());
349+
}
350+
} else {
351+
for &f in opts.features.iter() {
352+
reqs.require_value(&FeatureValue::new(f, s))?;
368353
}
369354
}
370-
match *method {
371-
Method::Everything
372-
| Method::Required {
373-
uses_default_features: true,
374-
..
375-
} => {
376-
if s.features().contains_key("default") {
377-
reqs.require_feature(InternedString::new("default"))?;
378-
}
355+
356+
if opts.uses_default_features {
357+
if s.features().contains_key("default") {
358+
reqs.require_feature(InternedString::new("default"))?;
379359
}
380-
Method::Required {
381-
uses_default_features: false,
382-
..
383-
} => {}
384360
}
361+
385362
Ok(reqs)
386363
}
387364

src/cargo/core/resolver/encode.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ use crate::util::{internal, Graph};
105105

106106
use super::{Resolve, ResolveVersion};
107107

108+
/// The `Cargo.lock` structure.
108109
#[derive(Serialize, Deserialize, Debug)]
109110
pub struct EncodableResolve {
110111
package: Option<Vec<EncodableDependency>>,
@@ -123,6 +124,14 @@ struct Patch {
123124
pub type Metadata = BTreeMap<String, String>;
124125

125126
impl EncodableResolve {
127+
/// Convert a `Cargo.lock` to a Resolve.
128+
///
129+
/// Note that this `Resolve` is not "complete". For example, the
130+
/// dependencies do not know the difference between regular/dev/build
131+
/// dependencies, so they are not filled in. It also does not include
132+
/// `features`. Care should be taken when using this Resolve. One of the
133+
/// primary uses is to be used with `resolve_with_previous` to guide the
134+
/// resolver to create a complete Resolve.
126135
pub fn into_resolve(self, ws: &Workspace<'_>) -> CargoResult<Resolve> {
127136
let path_deps = build_path_deps(ws);
128137
let mut checksums = HashMap::new();

src/cargo/core/resolver/mod.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ pub use self::encode::Metadata;
6969
pub use self::encode::{EncodableDependency, EncodablePackageId, EncodableResolve};
7070
pub use self::errors::{ActivateError, ActivateResult, ResolveError};
7171
pub use self::resolve::{Resolve, ResolveVersion};
72-
pub use self::types::Method;
72+
pub use self::types::ResolveOpts;
7373

7474
mod conflict_cache;
7575
mod context;
@@ -120,7 +120,7 @@ mod types;
120120
/// When we have a decision for how to implement is without breaking existing functionality
121121
/// this flag can be removed.
122122
pub fn resolve(
123-
summaries: &[(Summary, Method)],
123+
summaries: &[(Summary, ResolveOpts)],
124124
replacements: &[(PackageIdSpec, Dependency)],
125125
registry: &mut dyn Registry,
126126
try_to_use: &HashSet<PackageId>,
@@ -169,7 +169,7 @@ pub fn resolve(
169169
fn activate_deps_loop(
170170
mut cx: Context,
171171
registry: &mut RegistryQueryer<'_>,
172-
summaries: &[(Summary, Method)],
172+
summaries: &[(Summary, ResolveOpts)],
173173
config: Option<&Config>,
174174
) -> CargoResult<Context> {
175175
let mut backtrack_stack = Vec::new();
@@ -180,9 +180,9 @@ fn activate_deps_loop(
180180
let mut past_conflicting_activations = conflict_cache::ConflictCache::new();
181181

182182
// Activate all the initial summaries to kick off some work.
183-
for &(ref summary, ref method) in summaries {
183+
for &(ref summary, ref opts) in summaries {
184184
debug!("initial activation: {}", summary.package_id());
185-
let res = activate(&mut cx, registry, None, summary.clone(), method.clone());
185+
let res = activate(&mut cx, registry, None, summary.clone(), opts.clone());
186186
match res {
187187
Ok(Some((frame, _))) => remaining_deps.push(frame),
188188
Ok(None) => (),
@@ -366,7 +366,7 @@ fn activate_deps_loop(
366366
};
367367

368368
let pid = candidate.package_id();
369-
let method = Method::Required {
369+
let opts = ResolveOpts {
370370
dev_deps: false,
371371
features: Rc::clone(&features),
372372
all_features: false,
@@ -379,7 +379,7 @@ fn activate_deps_loop(
379379
dep.package_name(),
380380
candidate.version()
381381
);
382-
let res = activate(&mut cx, registry, Some((&parent, &dep)), candidate, method);
382+
let res = activate(&mut cx, registry, Some((&parent, &dep)), candidate, opts);
383383

384384
let successfully_activated = match res {
385385
// Success! We've now activated our `candidate` in our context
@@ -583,15 +583,15 @@ fn activate_deps_loop(
583583
/// Attempts to activate the summary `candidate` in the context `cx`.
584584
///
585585
/// This function will pull dependency summaries from the registry provided, and
586-
/// the dependencies of the package will be determined by the `method` provided.
586+
/// the dependencies of the package will be determined by the `opts` provided.
587587
/// If `candidate` was activated, this function returns the dependency frame to
588588
/// iterate through next.
589589
fn activate(
590590
cx: &mut Context,
591591
registry: &mut RegistryQueryer<'_>,
592592
parent: Option<(&Summary, &Dependency)>,
593593
candidate: Summary,
594-
method: Method,
594+
opts: ResolveOpts,
595595
) -> ActivateResult<Option<(DepsFrame, Duration)>> {
596596
let candidate_pid = candidate.package_id();
597597
if let Some((parent, dep)) = parent {
@@ -652,7 +652,7 @@ fn activate(
652652
}
653653
}
654654

655-
let activated = cx.flag_activated(&candidate, &method, parent)?;
655+
let activated = cx.flag_activated(&candidate, &opts, parent)?;
656656

657657
let candidate = match registry.replacement_summary(candidate_pid) {
658658
Some(replace) => {
@@ -661,7 +661,7 @@ fn activate(
661661
// does. TBH it basically cause panics in the test suite if
662662
// `parent` is passed through here and `[replace]` is otherwise
663663
// on life support so it's not critical to fix bugs anyway per se.
664-
if cx.flag_activated(replace, &method, None)? && activated {
664+
if cx.flag_activated(replace, &opts, None)? && activated {
665665
return Ok(None);
666666
}
667667
trace!(
@@ -682,7 +682,7 @@ fn activate(
682682

683683
let now = Instant::now();
684684
let (used_features, deps) =
685-
&*registry.build_deps(parent.map(|p| p.0.package_id()), &candidate, &method)?;
685+
&*registry.build_deps(parent.map(|p| p.0.package_id()), &candidate, &opts)?;
686686

687687
// Record what list of features is active for this package.
688688
if !used_features.is_empty() {

0 commit comments

Comments
 (0)