Skip to content

Commit

Permalink
feat(resolve): Direct people to working around less optimal MSRV-reso…
Browse files Browse the repository at this point in the history
…lver results

In discussing #14414, the general problem of the resolver picking a
version older than a package needs for its MSRV (or lack of one) because of the MSRV of
other packages came up.
This tries to patch over that problem by telling users that a dependency
might be able to be newer than the resolver selected.

The message is fairly generic and might be misread to be about any MSRV
update which an MSRV `fallback` strategy allows, which would make the
count off.
The reason it is so generic is we don't know with precision why it was
held back
- Direct dependents may have a non-semver upper bound on the version as
  we aren't trying to unify the version requirements across direct
  dependents at this time
- A dependency could have removed a feature without making a breaking
  change
  - This seems like it should instead be an error but thats a
    conversation for another day
- ~~The user enabled `-Zminimal-versions`~~
  - This is now detected and the message skipped

Note: separate from this, we may also print the status suffix for this
case if the package was not selected for update (e.g. passing
`--workspace`).
  • Loading branch information
epage committed Sep 30, 2024
1 parent fefff13 commit 8a99b0e
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 7 deletions.
55 changes: 48 additions & 7 deletions src/cargo/ops/cargo_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,7 @@ fn print_lockfile_generation(
annotate_required_rust_version(ws, resolve, &mut changes);

status_locking(ws, num_pkgs)?;
let mut changed_stats = UpdateStats::default();
for change in changes.values() {
if change.is_member.unwrap_or(false) {
continue;
Expand All @@ -538,8 +539,9 @@ fn print_lockfile_generation(
vec![]
};

let required_rust_version = report_required_rust_version(resolve, change, None);
let latest = report_latest(&possibilities, change, None);
let required_rust_version =
report_required_rust_version(resolve, change, Some(&mut changed_stats));
let latest = report_latest(&possibilities, change, Some(&mut changed_stats));
let note = required_rust_version.or(latest);

if let Some(note) = note {
Expand All @@ -559,6 +561,22 @@ fn print_lockfile_generation(
}
}

let compat_ver_compat_msrv = changed_stats.compat_ver_compat_msrv;
if 0 < compat_ver_compat_msrv
&& !ws.gctx().cli_unstable().direct_minimal_versions
&& !ws.gctx().cli_unstable().minimal_versions
{
if compat_ver_compat_msrv == 1 {
ws.gctx().shell().note(format!(
"{compat_ver_compat_msrv} package may have a higher, compatible version. To update it, run `cargo update <name> --precise <version>"
))?;
} else {
ws.gctx().shell().note(format!(
"{compat_ver_compat_msrv} packages may have a higher, compatible version. To update them, run `cargo update <name> --precise <version>"
))?;
}
}

Ok(())
}

Expand All @@ -580,6 +598,7 @@ fn print_lockfile_sync(
annotate_required_rust_version(ws, resolve, &mut changes);

status_locking(ws, num_pkgs)?;
let mut changed_stats = UpdateStats::default();
for change in changes.values() {
if change.is_member.unwrap_or(false) {
continue;
Expand All @@ -601,8 +620,9 @@ fn print_lockfile_sync(
vec![]
};

let required_rust_version = report_required_rust_version(resolve, change, None);
let latest = report_latest(&possibilities, change, None);
let required_rust_version =
report_required_rust_version(resolve, change, Some(&mut changed_stats));
let latest = report_latest(&possibilities, change, Some(&mut changed_stats));
let note = required_rust_version.or(latest).unwrap_or_default();

ws.gctx().shell().status_with_color(
Expand All @@ -615,6 +635,16 @@ fn print_lockfile_sync(
}
}

let compat_ver_compat_msrv = changed_stats.compat_ver_compat_msrv;
if 0 < compat_ver_compat_msrv
&& !ws.gctx().cli_unstable().direct_minimal_versions
&& !ws.gctx().cli_unstable().minimal_versions
{
ws.gctx().shell().note(format!(
"{compat_ver_compat_msrv} were updated but higher versions may be available by manually updating with `cargo update <name> --precise <version>"
))?;
}

Ok(())
}

Expand All @@ -636,6 +666,7 @@ fn print_lockfile_updates(
status_locking(ws, num_pkgs)?;
}
let mut unchanged_behind = 0;
let mut changed_stats = UpdateStats::default();
for change in changes.values() {
let possibilities = if let Some(query) = change.alternatives_query() {
loop {
Expand All @@ -654,8 +685,9 @@ fn print_lockfile_updates(
PackageChangeKind::Added
| PackageChangeKind::Upgraded
| PackageChangeKind::Downgraded => {
let required_rust_version = report_required_rust_version(resolve, change, None);
let latest = report_latest(&possibilities, change, None);
let required_rust_version =
report_required_rust_version(resolve, change, Some(&mut changed_stats));
let latest = report_latest(&possibilities, change, Some(&mut changed_stats));
let note = required_rust_version.or(latest).unwrap_or_default();

ws.gctx().shell().status_with_color(
Expand Down Expand Up @@ -694,6 +726,15 @@ fn print_lockfile_updates(
}
}

let compat_ver_compat_msrv = changed_stats.compat_ver_compat_msrv;
if 0 < compat_ver_compat_msrv
&& !ws.gctx().cli_unstable().direct_minimal_versions
&& !ws.gctx().cli_unstable().minimal_versions
{
ws.gctx().shell().note(format!(
"{compat_ver_compat_msrv} were updated but higher versions may be available by manually updating with `cargo update <name> --precise <version>"
))?;
}
if ws.gctx().shell().verbosity() == Verbosity::Verbose {
ws.gctx().shell().note(
"to see how you depend on a package, run `cargo tree --invert --package <dep>@<ver>`",
Expand Down Expand Up @@ -890,7 +931,7 @@ fn report_latest(
}
}

#[derive(Default)]
#[derive(Copy, Clone, Default, Debug)]
struct UpdateStats {
required_rust_version: usize,
compat_ver_compat_msrv: usize,
Expand Down
1 change: 1 addition & 0 deletions tests/testsuite/rust_version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1240,6 +1240,7 @@ fn report_rust_versions() {
[ADDING] dep-only-unset-compatible v1.55.0 (available: v1.75.0)
[ADDING] dep-only-unset-incompatible v1.2345.0 (requires Rust 1.2345.0)
[ADDING] dep-shared-incompatible v1.75.0 (requires Rust 1.75.0)
[NOTE] 2 packages may have a higher, compatible version. To update them, run `cargo update <name> --precise <version>
"#]])
.run();
Expand Down
1 change: 1 addition & 0 deletions tests/testsuite/workspaces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,7 @@ fn share_dependencies() {
[UPDATING] `dummy-registry` index
[LOCKING] 1 package to latest compatible version
[ADDING] dep1 v0.1.3 (available: v0.1.8)
[NOTE] 1 package may have a higher, compatible version. To update it, run `cargo update <name> --precise <version>
[DOWNLOADING] crates ...
[DOWNLOADED] dep1 v0.1.3 (registry `dummy-registry`)
[CHECKING] dep1 v0.1.3
Expand Down

0 comments on commit 8a99b0e

Please sign in to comment.