Skip to content

Commit 5db0671

Browse files
committed
feat(resolver): Respect MSRV
1 parent 10196aa commit 5db0671

File tree

14 files changed

+96
-7
lines changed

14 files changed

+96
-7
lines changed

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 = None; // TODO should we use std's? the users? none?
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: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,11 @@ pub fn create_bcx<'a, 'cfg>(
261261
HasDevUnits::No
262262
}
263263
};
264+
let max_rust_version = if ws.is_ephemeral() {
265+
None // TODO
266+
} else {
267+
ws.rust_version()
268+
};
264269
let resolve = ops::resolve_ws_with_opts(
265270
ws,
266271
&mut target_data,
@@ -269,6 +274,7 @@ pub fn create_bcx<'a, 'cfg>(
269274
&specs,
270275
has_dev_units,
271276
crate::core::resolver::features::ForceAllTargets::No,
277+
max_rust_version,
272278
)?;
273279
let WorkspaceResolve {
274280
mut pkg_set,

src/cargo/ops/cargo_generate_lockfile.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ 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 = if ws.is_ephemeral() {
25+
None // TODO
26+
} else {
27+
ws.rust_version()
28+
};
2429
let mut resolve = ops::resolve_with_previous(
2530
&mut registry,
2631
ws,
@@ -30,6 +35,7 @@ pub fn generate_lockfile(ws: &Workspace<'_>) -> CargoResult<()> {
3035
None,
3136
&[],
3237
true,
38+
max_rust_version,
3339
)?;
3440
ops::write_pkg_lockfile(ws, &mut resolve)?;
3541
Ok(())
@@ -48,6 +54,12 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
4854
// that we're synchronized against other Cargos.
4955
let _lock = ws.config().acquire_package_cache_lock()?;
5056

57+
let max_rust_version = if ws.is_ephemeral() {
58+
None // TODO
59+
} else {
60+
ws.rust_version()
61+
};
62+
5163
let previous_resolve = match ops::load_pkg_lockfile(ws)? {
5264
Some(resolve) => resolve,
5365
None => {
@@ -67,6 +79,7 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
6779
None,
6880
&[],
6981
true,
82+
max_rust_version,
7083
)?
7184
}
7285
}
@@ -125,6 +138,7 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
125138
Some(&to_avoid),
126139
&[],
127140
true,
141+
max_rust_version,
128142
)?;
129143

130144
// Summarize what is changing for the user.

src/cargo/ops/cargo_output_metadata.rs

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

138+
let max_rust_version = if ws.is_ephemeral() {
139+
None // TODO
140+
} else {
141+
ws.rust_version()
142+
};
143+
138144
// Note that even with --filter-platform we end up downloading host dependencies as well,
139145
// as that is the behavior of download_accessible.
140146
let ws_resolve = ops::resolve_ws_with_opts(
@@ -145,6 +151,7 @@ fn build_resolve_graph(
145151
&specs,
146152
HasDevUnits::Yes,
147153
force_all,
154+
max_rust_version,
148155
)?;
149156

150157
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

src/cargo/ops/fix.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,11 @@ fn check_resolver_change(ws: &Workspace<'_>, opts: &FixOptions) -> CargoResult<(
246246
let mut target_data =
247247
RustcTargetData::new(ws, &opts.compile_opts.build_config.requested_kinds)?;
248248
let mut resolve_differences = |has_dev_units| -> CargoResult<(WorkspaceResolve<'_>, DiffMap)> {
249+
let max_rust_version = if ws.is_ephemeral() {
250+
None // TODO
251+
} else {
252+
ws.rust_version()
253+
};
249254
let ws_resolve = ops::resolve_ws_with_opts(
250255
ws,
251256
&mut target_data,
@@ -254,6 +259,7 @@ fn check_resolver_change(ws: &Workspace<'_>, opts: &FixOptions) -> CargoResult<(
254259
&specs,
255260
has_dev_units,
256261
crate::core::resolver::features::ForceAllTargets::No,
262+
max_rust_version,
257263
)?;
258264

259265
let feature_opts = FeatureOpts::new_behavior(ResolveBehavior::V2, has_dev_units);

src/cargo/ops/resolve.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ use crate::core::{GitReference, PackageId, PackageIdSpec, PackageSet, SourceId,
6969
use crate::ops;
7070
use crate::sources::PathSource;
7171
use crate::util::errors::CargoResult;
72+
use crate::util::PartialVersion;
7273
use crate::util::{profile, CanonicalUrl};
7374
use anyhow::Context as _;
7475
use std::collections::{HashMap, HashSet};
@@ -106,8 +107,15 @@ version. This may also occur with an optional dependency that is not enabled.";
106107
/// This is a simple interface used by commands like `clean`, `fetch`, and
107108
/// `package`, which don't specify any options or features.
108109
pub fn resolve_ws<'a>(ws: &Workspace<'a>) -> CargoResult<(PackageSet<'a>, Resolve)> {
110+
// TODO `honor_rust_version`
111+
let max_rust_version = if ws.is_ephemeral() {
112+
None // TODO
113+
} else {
114+
ws.rust_version()
115+
};
116+
109117
let mut registry = PackageRegistry::new(ws.config())?;
110-
let resolve = resolve_with_registry(ws, &mut registry)?;
118+
let resolve = resolve_with_registry(ws, &mut registry, max_rust_version)?;
111119
let packages = get_resolved_packages(&resolve, registry)?;
112120
Ok((packages, resolve))
113121
}
@@ -130,6 +138,7 @@ pub fn resolve_ws_with_opts<'cfg>(
130138
specs: &[PackageIdSpec],
131139
has_dev_units: HasDevUnits,
132140
force_all_targets: ForceAllTargets,
141+
max_rust_version: Option<PartialVersion>,
133142
) -> CargoResult<WorkspaceResolve<'cfg>> {
134143
let mut registry = PackageRegistry::new(ws.config())?;
135144
let mut add_patches = true;
@@ -138,7 +147,7 @@ pub fn resolve_ws_with_opts<'cfg>(
138147
} else if ws.require_optional_deps() {
139148
// First, resolve the root_package's *listed* dependencies, as well as
140149
// downloading and updating all remotes and such.
141-
let resolve = resolve_with_registry(ws, &mut registry)?;
150+
let resolve = resolve_with_registry(ws, &mut registry, max_rust_version)?;
142151
// No need to add patches again, `resolve_with_registry` has done it.
143152
add_patches = false;
144153

@@ -184,6 +193,7 @@ pub fn resolve_ws_with_opts<'cfg>(
184193
None,
185194
specs,
186195
add_patches,
196+
max_rust_version,
187197
)?;
188198

189199
let pkg_set = get_resolved_packages(&resolved_with_overrides, registry)?;
@@ -235,6 +245,7 @@ pub fn resolve_ws_with_opts<'cfg>(
235245
fn resolve_with_registry<'cfg>(
236246
ws: &Workspace<'cfg>,
237247
registry: &mut PackageRegistry<'cfg>,
248+
max_rust_version: Option<PartialVersion>,
238249
) -> CargoResult<Resolve> {
239250
let prev = ops::load_pkg_lockfile(ws)?;
240251
let mut resolve = resolve_with_previous(
@@ -246,6 +257,7 @@ fn resolve_with_registry<'cfg>(
246257
None,
247258
&[],
248259
true,
260+
max_rust_version,
249261
)?;
250262

251263
if !ws.is_ephemeral() && ws.require_optional_deps() {
@@ -278,6 +290,7 @@ pub fn resolve_with_previous<'cfg>(
278290
to_avoid: Option<&HashSet<PackageId>>,
279291
specs: &[PackageIdSpec],
280292
register_patches: bool,
293+
max_rust_version: Option<PartialVersion>,
281294
) -> CargoResult<Resolve> {
282295
// We only want one Cargo at a time resolving a crate graph since this can
283296
// involve a lot of frobbing of the global caches.
@@ -505,6 +518,7 @@ pub fn resolve_with_previous<'cfg>(
505518
ws.unstable_features()
506519
.require(Feature::public_dependency())
507520
.is_ok(),
521+
max_rust_version,
508522
)?;
509523
let patches: Vec<_> = registry
510524
.patches()

0 commit comments

Comments
 (0)