Skip to content

Commit 0c2b370

Browse files
committed
Auto merge of #12560 - epage:msrv, r=๐Ÿ™ˆeh2406๐Ÿ™ˆ
feat(resolver): **Very** preliminary MSRV resolver support ### What does this PR try to resolve? A bare bones implementation of an MSRV resolver that is good enough for people running on nightly when they really need it but is not ready for general use. Current limitations - Does not honor `--ignore-version` - Gives terrible error messages - Nothing is done yet regarding `cargo install` - Doesn't inform the user when choosing non-latest These will be noted in #9930 on merge. Implementation wise, this is yet another hack (sorry `@Eh2406).` Our expectation to get this GA is to refactor the resolver to make the cargo/resolver boundary look a little more like the cargo/pubgrub boundary so we can better control policy without any of these hacks which will also make having all of the policy we need for this easier to maintain. This is a part of #9930 ### How should we test and review this PR? Per commit
2 parents edb5281 + 4abd05e commit 0c2b370

File tree

17 files changed

+258
-8
lines changed

17 files changed

+258
-8
lines changed

โ€Žbenches/benchsuite/benches/resolve.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ fn do_resolve<'cfg>(config: &'cfg Config, ws_root: &Path) -> ResolveInfo<'cfg> {
3131
let specs = pkgs.to_package_id_specs(&ws).unwrap();
3232
let has_dev_units = HasDevUnits::Yes;
3333
let force_all_targets = ForceAllTargets::No;
34+
let max_rust_version = None;
3435
// Do an initial run to download anything necessary so that it does
3536
// not confuse criterion's warmup.
3637
let ws_resolve = cargo::ops::resolve_ws_with_opts(
@@ -41,6 +42,7 @@ fn do_resolve<'cfg>(config: &'cfg Config, ws_root: &Path) -> ResolveInfo<'cfg> {
4142
&specs,
4243
has_dev_units,
4344
force_all_targets,
45+
max_rust_version,
4446
)
4547
.unwrap();
4648
ResolveInfo {
@@ -82,6 +84,7 @@ fn resolve_ws(c: &mut Criterion) {
8284
force_all_targets,
8385
..
8486
} = lazy_info.get_or_insert_with(|| do_resolve(&config, &ws_root));
87+
let max_rust_version = None;
8588
b.iter(|| {
8689
cargo::ops::resolve_ws_with_opts(
8790
ws,
@@ -91,6 +94,7 @@ fn resolve_ws(c: &mut Criterion) {
9194
specs,
9295
*has_dev_units,
9396
*force_all_targets,
97+
max_rust_version,
9498
)
9599
.unwrap();
96100
})

โ€Žcrates/resolver-tests/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,13 +188,15 @@ pub fn resolve_with_config_raw(
188188
.unwrap();
189189
let opts = ResolveOpts::everything();
190190
let start = Instant::now();
191+
let max_rust_version = None;
191192
let resolve = resolver::resolve(
192193
&[(summary, opts)],
193194
&[],
194195
&mut registry,
195196
&VersionPreferences::default(),
196197
Some(config),
197198
true,
199+
max_rust_version,
198200
);
199201

200202
// The largest test in our suite takes less then 30 sec.

โ€Žsrc/cargo/core/compiler/standard_lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ pub fn resolve_std<'cfg>(
145145
let cli_features = CliFeatures::from_command_line(
146146
&features, /*all_features*/ false, /*uses_default_features*/ false,
147147
)?;
148+
let max_rust_version = ws.rust_version();
148149
let resolve = ops::resolve_ws_with_opts(
149150
&std_ws,
150151
target_data,
@@ -153,6 +154,7 @@ pub fn resolve_std<'cfg>(
153154
&specs,
154155
HasDevUnits::No,
155156
crate::core::resolver::features::ForceAllTargets::No,
157+
max_rust_version,
156158
)?;
157159
Ok((
158160
resolve.pkg_set,

โ€Žsrc/cargo/core/resolver/dep_cache.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use crate::core::{
2121
};
2222
use crate::util::errors::CargoResult;
2323
use crate::util::interning::InternedString;
24+
use crate::util::PartialVersion;
2425

2526
use anyhow::Context as _;
2627
use std::collections::{BTreeSet, HashMap, HashSet};
@@ -36,6 +37,7 @@ pub struct RegistryQueryer<'a> {
3637
/// versions first. That allows `cargo update -Z minimal-versions` which will
3738
/// specify minimum dependency versions to be used.
3839
minimal_versions: bool,
40+
max_rust_version: Option<PartialVersion>,
3941
/// a cache of `Candidate`s that fulfil a `Dependency` (and whether `first_minimal_version`)
4042
registry_cache: HashMap<(Dependency, bool), Poll<Rc<Vec<Summary>>>>,
4143
/// a cache of `Dependency`s that are required for a `Summary`
@@ -57,12 +59,14 @@ impl<'a> RegistryQueryer<'a> {
5759
replacements: &'a [(PackageIdSpec, Dependency)],
5860
version_prefs: &'a VersionPreferences,
5961
minimal_versions: bool,
62+
max_rust_version: Option<PartialVersion>,
6063
) -> Self {
6164
RegistryQueryer {
6265
registry,
6366
replacements,
6467
version_prefs,
6568
minimal_versions,
69+
max_rust_version,
6670
registry_cache: HashMap::new(),
6771
summary_cache: HashMap::new(),
6872
used_replacements: HashMap::new(),
@@ -112,7 +116,9 @@ impl<'a> RegistryQueryer<'a> {
112116

113117
let mut ret = Vec::new();
114118
let ready = self.registry.query(dep, QueryKind::Exact, &mut |s| {
115-
ret.push(s);
119+
if self.max_rust_version.is_none() || s.rust_version() <= self.max_rust_version {
120+
ret.push(s);
121+
}
116122
})?;
117123
if ready.is_pending() {
118124
self.registry_cache

โ€Žsrc/cargo/core/resolver/mod.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ use crate::util::config::Config;
7171
use crate::util::errors::CargoResult;
7272
use crate::util::network::PollExt;
7373
use crate::util::profile;
74+
use crate::util::PartialVersion;
7475

7576
use self::context::Context;
7677
use self::dep_cache::RegistryQueryer;
@@ -138,6 +139,7 @@ pub fn resolve(
138139
version_prefs: &VersionPreferences,
139140
config: Option<&Config>,
140141
check_public_visible_dependencies: bool,
142+
mut max_rust_version: Option<PartialVersion>,
141143
) -> CargoResult<Resolve> {
142144
let _p = profile::start("resolving");
143145
let minimal_versions = match config {
@@ -148,8 +150,19 @@ pub fn resolve(
148150
Some(config) => config.cli_unstable().direct_minimal_versions,
149151
None => false,
150152
};
151-
let mut registry =
152-
RegistryQueryer::new(registry, replacements, version_prefs, minimal_versions);
153+
if !config
154+
.map(|c| c.cli_unstable().msrv_policy)
155+
.unwrap_or(false)
156+
{
157+
max_rust_version = None;
158+
}
159+
let mut registry = RegistryQueryer::new(
160+
registry,
161+
replacements,
162+
version_prefs,
163+
minimal_versions,
164+
max_rust_version,
165+
);
153166
let cx = loop {
154167
let cx = Context::new(check_public_visible_dependencies);
155168
let cx = activate_deps_loop(

โ€Žsrc/cargo/core/workspace.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use crate::util::edit_distance;
2323
use crate::util::errors::{CargoResult, ManifestError};
2424
use crate::util::interning::InternedString;
2525
use crate::util::toml::{read_manifest, InheritableFields, TomlDependency, TomlProfiles};
26+
use crate::util::PartialVersion;
2627
use crate::util::{config::ConfigRelativePath, Config, Filesystem, IntoUrl};
2728
use cargo_util::paths;
2829
use cargo_util::paths::normalize_path;
@@ -595,6 +596,12 @@ impl<'cfg> Workspace<'cfg> {
595596
self
596597
}
597598

599+
/// Get the lowest-common denominator `package.rust-version` within the workspace, if specified
600+
/// anywhere
601+
pub fn rust_version(&self) -> Option<PartialVersion> {
602+
self.members().filter_map(|pkg| pkg.rust_version()).min()
603+
}
604+
598605
pub fn custom_metadata(&self) -> Option<&toml::Value> {
599606
self.custom_metadata.as_ref()
600607
}

โ€Žsrc/cargo/ops/cargo_compile/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ pub fn create_bcx<'a, 'cfg>(
261261
HasDevUnits::No
262262
}
263263
};
264+
let max_rust_version = ws.rust_version();
264265
let resolve = ops::resolve_ws_with_opts(
265266
ws,
266267
&mut target_data,
@@ -269,6 +270,7 @@ pub fn create_bcx<'a, 'cfg>(
269270
&specs,
270271
has_dev_units,
271272
crate::core::resolver::features::ForceAllTargets::No,
273+
max_rust_version,
272274
)?;
273275
let WorkspaceResolve {
274276
mut pkg_set,

โ€Žsrc/cargo/ops/cargo_generate_lockfile.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub struct UpdateOptions<'a> {
2121

2222
pub fn generate_lockfile(ws: &Workspace<'_>) -> CargoResult<()> {
2323
let mut registry = PackageRegistry::new(ws.config())?;
24+
let max_rust_version = ws.rust_version();
2425
let mut resolve = ops::resolve_with_previous(
2526
&mut registry,
2627
ws,
@@ -30,6 +31,7 @@ pub fn generate_lockfile(ws: &Workspace<'_>) -> CargoResult<()> {
3031
None,
3132
&[],
3233
true,
34+
max_rust_version,
3335
)?;
3436
ops::write_pkg_lockfile(ws, &mut resolve)?;
3537
Ok(())
@@ -48,6 +50,8 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
4850
// that we're synchronized against other Cargos.
4951
let _lock = ws.config().acquire_package_cache_lock()?;
5052

53+
let max_rust_version = ws.rust_version();
54+
5155
let previous_resolve = match ops::load_pkg_lockfile(ws)? {
5256
Some(resolve) => resolve,
5357
None => {
@@ -67,6 +71,7 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
6771
None,
6872
&[],
6973
true,
74+
max_rust_version,
7075
)?
7176
}
7277
}
@@ -125,6 +130,7 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
125130
Some(&to_avoid),
126131
&[],
127132
true,
133+
max_rust_version,
128134
)?;
129135

130136
// Summarize what is changing for the user.

โ€Žsrc/cargo/ops/cargo_output_metadata.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ fn build_resolve_graph(
135135
crate::core::resolver::features::ForceAllTargets::No
136136
};
137137

138+
let max_rust_version = ws.rust_version();
139+
138140
// Note that even with --filter-platform we end up downloading host dependencies as well,
139141
// as that is the behavior of download_accessible.
140142
let ws_resolve = ops::resolve_ws_with_opts(
@@ -145,6 +147,7 @@ fn build_resolve_graph(
145147
&specs,
146148
HasDevUnits::Yes,
147149
force_all,
150+
max_rust_version,
148151
)?;
149152

150153
let package_map: BTreeMap<PackageId, Package> = ws_resolve

โ€Žsrc/cargo/ops/cargo_package.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,8 @@ fn build_lock(ws: &Workspace<'_>, orig_pkg: &Package) -> CargoResult<String> {
423423
TomlManifest::to_real_manifest(&toml_manifest, false, source_id, package_root, config)?;
424424
let new_pkg = Package::new(manifest, orig_pkg.manifest_path());
425425

426+
let max_rust_version = new_pkg.rust_version();
427+
426428
// Regenerate Cargo.lock using the old one as a guide.
427429
let tmp_ws = Workspace::ephemeral(new_pkg, ws.config(), None, true)?;
428430
let mut tmp_reg = PackageRegistry::new(ws.config())?;
@@ -435,6 +437,7 @@ fn build_lock(ws: &Workspace<'_>, orig_pkg: &Package) -> CargoResult<String> {
435437
None,
436438
&[],
437439
true,
440+
max_rust_version,
438441
)?;
439442
let pkg_set = ops::get_resolved_packages(&new_resolve, tmp_reg)?;
440443

0 commit comments

Comments
ย (0)