Skip to content

Commit 7e14aec

Browse files
committed
feat: respect rust-version when generating lockfile
MSRV-aware resolver has been implemented in PR 12560. Based on that effort, generating lockfile can now respect `rust-version` so that a package with an old MSRV will never get an incompatible lockfile, even using the latest Cargo.
1 parent 7e89ba7 commit 7e14aec

File tree

5 files changed

+57
-10
lines changed

5 files changed

+57
-10
lines changed

src/cargo/core/resolver/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,9 @@ pub fn resolve(
150150
Some(config) => config.cli_unstable().direct_minimal_versions,
151151
None => false,
152152
};
153+
154+
let resolve_version = ResolveVersion::with_rust_version(max_rust_version);
155+
153156
if !config
154157
.map(|c| c.cli_unstable().msrv_policy)
155158
.unwrap_or(false)
@@ -203,7 +206,7 @@ pub fn resolve(
203206
cksums,
204207
BTreeMap::new(),
205208
Vec::new(),
206-
ResolveVersion::default(),
209+
resolve_version,
207210
summaries,
208211
);
209212

src/cargo/core/resolver/resolve.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ use crate::core::{Dependency, PackageId, PackageIdSpec, Summary, Target};
44
use crate::util::errors::CargoResult;
55
use crate::util::interning::InternedString;
66
use crate::util::Graph;
7+
use crate::util::PartialVersion;
8+
use crate::util::RustVersion;
79
use std::borrow::Borrow;
810
use std::collections::{HashMap, HashSet};
911
use std::fmt;
@@ -97,6 +99,40 @@ impl ResolveVersion {
9799
pub fn max_stable() -> ResolveVersion {
98100
ResolveVersion::V3
99101
}
102+
103+
/// Gets the default lockfile version for the given Rust version.
104+
pub fn with_rust_version(rust_version: Option<&RustVersion>) -> Self {
105+
let Some(rust_version) = rust_version else {
106+
return ResolveVersion::default();
107+
};
108+
109+
let rust_1_41 = PartialVersion {
110+
major: 1,
111+
minor: Some(41),
112+
patch: None,
113+
pre: None,
114+
build: None,
115+
}
116+
.try_into()
117+
.expect("PartialVersion 1.41");
118+
let rust_1_53 = PartialVersion {
119+
major: 1,
120+
minor: Some(53),
121+
patch: None,
122+
pre: None,
123+
build: None,
124+
}
125+
.try_into()
126+
.expect("PartialVersion 1.53");
127+
128+
if rust_version >= &rust_1_53 {
129+
ResolveVersion::V3
130+
} else if rust_version >= &rust_1_41 {
131+
ResolveVersion::V2
132+
} else {
133+
ResolveVersion::V1
134+
}
135+
}
100136
}
101137

102138
impl Resolve {

src/cargo/ops/lockfile.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,10 @@ pub fn write_pkg_lockfile(ws: &Workspace<'_>, resolve: &mut Resolve) -> CargoRes
6464
// out lock file updates as they're otherwise already updated, and changes
6565
// which don't touch dependencies won't seemingly spuriously update the lock
6666
// file.
67-
let default_version = ResolveVersion::default();
67+
let default_version = ResolveVersion::with_rust_version(ws.rust_version());
6868
let current_version = resolve.version();
6969
let next_lockfile_bump = ws.config().cli_unstable().next_lockfile_bump;
70+
tracing::debug!("lockfile - current: {current_version:?}, default: {default_version:?}");
7071

7172
if current_version < default_version {
7273
resolve.set_version(default_version);

src/cargo/util/semver_ext.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,12 +136,19 @@ impl std::str::FromStr for RustVersion {
136136
type Err = anyhow::Error;
137137

138138
fn from_str(value: &str) -> Result<Self, Self::Err> {
139-
let partial = value.parse::<PartialVersion>()?;
139+
value.parse::<PartialVersion>()?.try_into()
140+
}
141+
}
142+
143+
impl TryFrom<PartialVersion> for RustVersion {
144+
type Error = anyhow::Error;
145+
146+
fn try_from(partial: PartialVersion) -> Result<Self, Self::Error> {
140147
if partial.pre.is_some() {
141148
anyhow::bail!("unexpected prerelease field, expected a version like \"1.32\"")
142149
}
143150
if partial.build.is_some() {
144-
anyhow::bail!("unexpected prerelease field, expected a version like \"1.32\"")
151+
anyhow::bail!("unexpected build metadata field, expected a version like \"1.32\"")
145152
}
146153
Ok(Self(partial))
147154
}

tests/testsuite/lockfile_compat.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,23 +1220,23 @@ dependencies = [
12201220

12211221
let cases = [
12221222
// v1 is the default
1223-
("1.37", None, 3),
1223+
("1.37", None, 1),
12241224
("1.37", Some(1), 1),
12251225
("1.37", Some(2), 2),
12261226
("1.37", Some(3), 3),
12271227
// v2 introduced
1228-
("1.38", None, 3),
1228+
("1.38", None, 1),
12291229
// last version of v1 as the default
1230-
("1.40", None, 3),
1230+
("1.40", None, 1),
12311231
// v2 is the default
1232-
("1.41", None, 3),
1232+
("1.41", None, 2),
12331233
("1.41", Some(1), 1),
12341234
("1.41", Some(2), 2),
12351235
("1.41", Some(3), 3),
12361236
// v3 introduced
1237-
("1.47", None, 3),
1237+
("1.47", None, 2),
12381238
// last version of v2 as the default
1239-
("1.48", None, 3),
1239+
("1.48", None, 2),
12401240
// v3 is the default
12411241
("1.53", None, 3),
12421242
("1.53", Some(1), 1),

0 commit comments

Comments
 (0)