Skip to content

Commit

Permalink
feat: respect rust-version when generating lockfile
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
weihanglo committed Oct 23, 2023
1 parent 7e89ba7 commit 7e14aec
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 10 deletions.
5 changes: 4 additions & 1 deletion src/cargo/core/resolver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ pub fn resolve(
Some(config) => config.cli_unstable().direct_minimal_versions,
None => false,
};

let resolve_version = ResolveVersion::with_rust_version(max_rust_version);

if !config
.map(|c| c.cli_unstable().msrv_policy)
.unwrap_or(false)
Expand Down Expand Up @@ -203,7 +206,7 @@ pub fn resolve(
cksums,
BTreeMap::new(),
Vec::new(),
ResolveVersion::default(),
resolve_version,
summaries,
);

Expand Down
36 changes: 36 additions & 0 deletions src/cargo/core/resolver/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use crate::core::{Dependency, PackageId, PackageIdSpec, Summary, Target};
use crate::util::errors::CargoResult;
use crate::util::interning::InternedString;
use crate::util::Graph;
use crate::util::PartialVersion;
use crate::util::RustVersion;
use std::borrow::Borrow;
use std::collections::{HashMap, HashSet};
use std::fmt;
Expand Down Expand Up @@ -97,6 +99,40 @@ impl ResolveVersion {
pub fn max_stable() -> ResolveVersion {
ResolveVersion::V3
}

/// Gets the default lockfile version for the given Rust version.
pub fn with_rust_version(rust_version: Option<&RustVersion>) -> Self {
let Some(rust_version) = rust_version else {
return ResolveVersion::default();
};

let rust_1_41 = PartialVersion {
major: 1,
minor: Some(41),
patch: None,
pre: None,
build: None,
}
.try_into()
.expect("PartialVersion 1.41");
let rust_1_53 = PartialVersion {
major: 1,
minor: Some(53),
patch: None,
pre: None,
build: None,
}
.try_into()
.expect("PartialVersion 1.53");

if rust_version >= &rust_1_53 {
ResolveVersion::V3
} else if rust_version >= &rust_1_41 {
ResolveVersion::V2
} else {
ResolveVersion::V1
}
}
}

impl Resolve {
Expand Down
3 changes: 2 additions & 1 deletion src/cargo/ops/lockfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,10 @@ pub fn write_pkg_lockfile(ws: &Workspace<'_>, resolve: &mut Resolve) -> CargoRes
// out lock file updates as they're otherwise already updated, and changes
// which don't touch dependencies won't seemingly spuriously update the lock
// file.
let default_version = ResolveVersion::default();
let default_version = ResolveVersion::with_rust_version(ws.rust_version());
let current_version = resolve.version();
let next_lockfile_bump = ws.config().cli_unstable().next_lockfile_bump;
tracing::debug!("lockfile - current: {current_version:?}, default: {default_version:?}");

if current_version < default_version {
resolve.set_version(default_version);
Expand Down
11 changes: 9 additions & 2 deletions src/cargo/util/semver_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,19 @@ impl std::str::FromStr for RustVersion {
type Err = anyhow::Error;

fn from_str(value: &str) -> Result<Self, Self::Err> {
let partial = value.parse::<PartialVersion>()?;
value.parse::<PartialVersion>()?.try_into()
}
}

impl TryFrom<PartialVersion> for RustVersion {
type Error = anyhow::Error;

fn try_from(partial: PartialVersion) -> Result<Self, Self::Error> {
if partial.pre.is_some() {
anyhow::bail!("unexpected prerelease field, expected a version like \"1.32\"")
}
if partial.build.is_some() {
anyhow::bail!("unexpected prerelease field, expected a version like \"1.32\"")
anyhow::bail!("unexpected build metadata field, expected a version like \"1.32\"")
}
Ok(Self(partial))
}
Expand Down
12 changes: 6 additions & 6 deletions tests/testsuite/lockfile_compat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1220,23 +1220,23 @@ dependencies = [

let cases = [
// v1 is the default
("1.37", None, 3),
("1.37", None, 1),
("1.37", Some(1), 1),
("1.37", Some(2), 2),
("1.37", Some(3), 3),
// v2 introduced
("1.38", None, 3),
("1.38", None, 1),
// last version of v1 as the default
("1.40", None, 3),
("1.40", None, 1),
// v2 is the default
("1.41", None, 3),
("1.41", None, 2),
("1.41", Some(1), 1),
("1.41", Some(2), 2),
("1.41", Some(3), 3),
// v3 introduced
("1.47", None, 3),
("1.47", None, 2),
// last version of v2 as the default
("1.48", None, 3),
("1.48", None, 2),
// v3 is the default
("1.53", None, 3),
("1.53", Some(1), 1),
Expand Down

0 comments on commit 7e14aec

Please sign in to comment.