fix(resolve): Report incompatible packages with precise Rust version

The nesting in `annotate_required_rust_version` might seem weird but its
for a follow up commit.
This commit is contained in:
Ed Page 2024-08-23 15:06:38 -05:00
parent 89cf552c06
commit 437b73ceb3
2 changed files with 66 additions and 21 deletions

View File

@ -492,7 +492,7 @@ fn print_lockfile_generation(
resolve: &Resolve,
registry: &mut PackageRegistry<'_>,
) -> CargoResult<()> {
let changes = PackageChange::new(ws, resolve);
let mut changes = PackageChange::new(ws, resolve);
let num_pkgs: usize = changes
.values()
.filter(|change| change.kind.is_new() && !change.is_member.unwrap_or(false))
@ -501,8 +501,9 @@ fn print_lockfile_generation(
// nothing worth reporting
return Ok(());
}
status_locking(ws, num_pkgs)?;
annotate_required_rust_version(ws, resolve, &mut changes);
status_locking(ws, num_pkgs)?;
for change in changes.values() {
if change.is_member.unwrap_or(false) {
continue;
@ -523,7 +524,7 @@ fn print_lockfile_generation(
};
let package_id = change.package_id;
let required_rust_version = report_required_rust_version(ws, resolve, package_id);
let required_rust_version = report_required_rust_version(resolve, change);
let latest = report_latest(&possibilities, package_id);
let note = required_rust_version.or(latest);
@ -553,7 +554,7 @@ fn print_lockfile_sync(
resolve: &Resolve,
registry: &mut PackageRegistry<'_>,
) -> CargoResult<()> {
let changes = PackageChange::diff(ws, previous_resolve, resolve);
let mut changes = PackageChange::diff(ws, previous_resolve, resolve);
let num_pkgs: usize = changes
.values()
.filter(|change| change.kind.is_new() && !change.is_member.unwrap_or(false))
@ -562,8 +563,9 @@ fn print_lockfile_sync(
// nothing worth reporting
return Ok(());
}
status_locking(ws, num_pkgs)?;
annotate_required_rust_version(ws, resolve, &mut changes);
status_locking(ws, num_pkgs)?;
for change in changes.values() {
if change.is_member.unwrap_or(false) {
continue;
@ -586,7 +588,7 @@ fn print_lockfile_sync(
};
let package_id = change.package_id;
let required_rust_version = report_required_rust_version(ws, resolve, package_id);
let required_rust_version = report_required_rust_version(resolve, change);
let latest = report_latest(&possibilities, package_id);
let note = required_rust_version.or(latest).unwrap_or_default();
@ -610,15 +612,16 @@ fn print_lockfile_updates(
precise: bool,
registry: &mut PackageRegistry<'_>,
) -> CargoResult<()> {
let changes = PackageChange::diff(ws, previous_resolve, resolve);
let mut changes = PackageChange::diff(ws, previous_resolve, resolve);
let num_pkgs: usize = changes
.values()
.filter(|change| change.kind.is_new())
.count();
annotate_required_rust_version(ws, resolve, &mut changes);
if !precise {
status_locking(ws, num_pkgs)?;
}
let mut unchanged_behind = 0;
for change in changes.values() {
let possibilities = if let Some(query) = change.alternatives_query() {
@ -639,7 +642,7 @@ fn print_lockfile_updates(
| PackageChangeKind::Upgraded
| PackageChangeKind::Downgraded => {
let package_id = change.package_id;
let required_rust_version = report_required_rust_version(ws, resolve, package_id);
let required_rust_version = report_required_rust_version(resolve, change);
let latest = report_latest(&possibilities, package_id);
let note = required_rust_version.or(latest).unwrap_or_default();
@ -658,7 +661,7 @@ fn print_lockfile_updates(
}
PackageChangeKind::Unchanged => {
let package_id = change.package_id;
let required_rust_version = report_required_rust_version(ws, resolve, package_id);
let required_rust_version = report_required_rust_version(resolve, change);
let latest = report_latest(&possibilities, package_id);
let note = required_rust_version.as_deref().or(latest.as_deref());
@ -734,18 +737,14 @@ fn required_rust_version(ws: &Workspace<'_>) -> Option<PartialVersion> {
}
}
fn report_required_rust_version(
ws: &Workspace<'_>,
resolve: &Resolve,
package: PackageId,
) -> Option<String> {
if package.source_id().is_path() {
fn report_required_rust_version(resolve: &Resolve, change: &PackageChange) -> Option<String> {
if change.package_id.source_id().is_path() {
return None;
}
let summary = resolve.summary(package);
let summary = resolve.summary(change.package_id);
let package_rust_version = summary.rust_version()?;
let workspace_rust_version = required_rust_version(ws)?;
if package_rust_version.is_compatible_with(&workspace_rust_version) {
let required_rust_version = change.required_rust_version.as_ref()?;
if package_rust_version.is_compatible_with(required_rust_version) {
return None;
}
@ -804,6 +803,7 @@ struct PackageChange {
previous_id: Option<PackageId>,
kind: PackageChangeKind,
is_member: Option<bool>,
required_rust_version: Option<PartialVersion>,
}
impl PackageChange {
@ -847,6 +847,7 @@ impl PackageChange {
previous_id: Some(previous_id),
kind,
is_member,
required_rust_version: None,
};
changes.insert(change.package_id, change);
} else {
@ -858,6 +859,7 @@ impl PackageChange {
previous_id: None,
kind,
is_member,
required_rust_version: None,
};
changes.insert(change.package_id, change);
}
@ -869,6 +871,7 @@ impl PackageChange {
previous_id: None,
kind,
is_member,
required_rust_version: None,
};
changes.insert(change.package_id, change);
}
@ -881,6 +884,7 @@ impl PackageChange {
previous_id: None,
kind,
is_member,
required_rust_version: None,
};
changes.insert(change.package_id, change);
}
@ -1076,3 +1080,46 @@ impl PackageDiff {
}
}
}
fn annotate_required_rust_version(
ws: &Workspace<'_>,
resolve: &Resolve,
changes: &mut IndexMap<PackageId, PackageChange>,
) {
let rustc = ws.gctx().load_global_rustc(Some(ws)).ok();
let rustc_version: Option<PartialVersion> =
rustc.as_ref().map(|rustc| rustc.version.clone().into());
if ws.resolve_honors_rust_version() {
let mut queue: std::collections::VecDeque<_> = ws
.members()
.map(|p| {
(
p.rust_version()
.map(|r| r.clone().into_partial())
.or_else(|| rustc_version.clone()),
p.package_id(),
)
})
.collect();
while let Some((required_rust_version, current_id)) = queue.pop_front() {
let Some(required_rust_version) = required_rust_version else {
continue;
};
if let Some(change) = changes.get_mut(&current_id) {
if let Some(existing) = change.required_rust_version.as_ref() {
if *existing <= required_rust_version {
// Stop early; we already walked down this path with a better match
continue;
}
}
change.required_rust_version = Some(required_rust_version.clone());
}
queue.extend(
resolve
.deps(current_id)
.map(|(dep, _)| (Some(required_rust_version.clone()), dep)),
);
}
}
}

View File

@ -1180,10 +1180,8 @@ fn report_rust_versions() {
.with_stderr_data(str![[r#"
[UPDATING] `dummy-registry` index
[LOCKING] 9 packages to latest Rust 1.60.0 compatible versions
[ADDING] dep-only-high-compatible v1.65.0 (requires Rust 1.65.0)
[ADDING] dep-only-high-incompatible v1.75.0 (requires Rust 1.75.0)
[ADDING] dep-only-low-incompatible v1.75.0 (requires Rust 1.75.0)
[ADDING] dep-only-unset-compatible v1.75.0 (requires Rust 1.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)