diff --git a/src/cargo/ops/cargo_update.rs b/src/cargo/ops/cargo_update.rs index fe65fe6b7..fd2a88ca7 100644 --- a/src/cargo/ops/cargo_update.rs +++ b/src/cargo/ops/cargo_update.rs @@ -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 { } } -fn report_required_rust_version( - ws: &Workspace<'_>, - resolve: &Resolve, - package: PackageId, -) -> Option { - if package.source_id().is_path() { +fn report_required_rust_version(resolve: &Resolve, change: &PackageChange) -> Option { + 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, kind: PackageChangeKind, is_member: Option, + required_rust_version: Option, } 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, +) { + let rustc = ws.gctx().load_global_rustc(Some(ws)).ok(); + let rustc_version: Option = + 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(¤t_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)), + ); + } + } +} diff --git a/tests/testsuite/rust_version.rs b/tests/testsuite/rust_version.rs index a33054bf1..2de7e72dc 100644 --- a/tests/testsuite/rust_version.rs +++ b/tests/testsuite/rust_version.rs @@ -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)