Skip to content

Commit 5058386

Browse files
committed
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.
1 parent 89cf552 commit 5058386

File tree

2 files changed

+67
-21
lines changed

2 files changed

+67
-21
lines changed

src/cargo/ops/cargo_update.rs

Lines changed: 67 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ fn print_lockfile_generation(
492492
resolve: &Resolve,
493493
registry: &mut PackageRegistry<'_>,
494494
) -> CargoResult<()> {
495-
let changes = PackageChange::new(ws, resolve);
495+
let mut changes = PackageChange::new(ws, resolve);
496496
let num_pkgs: usize = changes
497497
.values()
498498
.filter(|change| change.kind.is_new() && !change.is_member.unwrap_or(false))
@@ -501,8 +501,9 @@ fn print_lockfile_generation(
501501
// nothing worth reporting
502502
return Ok(());
503503
}
504-
status_locking(ws, num_pkgs)?;
504+
annotate_required_rust_version(ws, resolve, &mut changes);
505505

506+
status_locking(ws, num_pkgs)?;
506507
for change in changes.values() {
507508
if change.is_member.unwrap_or(false) {
508509
continue;
@@ -523,7 +524,7 @@ fn print_lockfile_generation(
523524
};
524525

525526
let package_id = change.package_id;
526-
let required_rust_version = report_required_rust_version(ws, resolve, package_id);
527+
let required_rust_version = report_required_rust_version(resolve, change);
527528
let latest = report_latest(&possibilities, package_id);
528529
let note = required_rust_version.or(latest);
529530

@@ -553,7 +554,7 @@ fn print_lockfile_sync(
553554
resolve: &Resolve,
554555
registry: &mut PackageRegistry<'_>,
555556
) -> CargoResult<()> {
556-
let changes = PackageChange::diff(ws, previous_resolve, resolve);
557+
let mut changes = PackageChange::diff(ws, previous_resolve, resolve);
557558
let num_pkgs: usize = changes
558559
.values()
559560
.filter(|change| change.kind.is_new() && !change.is_member.unwrap_or(false))
@@ -562,8 +563,9 @@ fn print_lockfile_sync(
562563
// nothing worth reporting
563564
return Ok(());
564565
}
565-
status_locking(ws, num_pkgs)?;
566+
annotate_required_rust_version(ws, resolve, &mut changes);
566567

568+
status_locking(ws, num_pkgs)?;
567569
for change in changes.values() {
568570
if change.is_member.unwrap_or(false) {
569571
continue;
@@ -586,7 +588,7 @@ fn print_lockfile_sync(
586588
};
587589

588590
let package_id = change.package_id;
589-
let required_rust_version = report_required_rust_version(ws, resolve, package_id);
591+
let required_rust_version = report_required_rust_version(resolve, change);
590592
let latest = report_latest(&possibilities, package_id);
591593
let note = required_rust_version.or(latest).unwrap_or_default();
592594

@@ -610,15 +612,16 @@ fn print_lockfile_updates(
610612
precise: bool,
611613
registry: &mut PackageRegistry<'_>,
612614
) -> CargoResult<()> {
613-
let changes = PackageChange::diff(ws, previous_resolve, resolve);
615+
let mut changes = PackageChange::diff(ws, previous_resolve, resolve);
614616
let num_pkgs: usize = changes
615617
.values()
616618
.filter(|change| change.kind.is_new())
617619
.count();
620+
annotate_required_rust_version(ws, resolve, &mut changes);
621+
618622
if !precise {
619623
status_locking(ws, num_pkgs)?;
620624
}
621-
622625
let mut unchanged_behind = 0;
623626
for change in changes.values() {
624627
let possibilities = if let Some(query) = change.alternatives_query() {
@@ -639,7 +642,7 @@ fn print_lockfile_updates(
639642
| PackageChangeKind::Upgraded
640643
| PackageChangeKind::Downgraded => {
641644
let package_id = change.package_id;
642-
let required_rust_version = report_required_rust_version(ws, resolve, package_id);
645+
let required_rust_version = report_required_rust_version(resolve, change);
643646
let latest = report_latest(&possibilities, package_id);
644647
let note = required_rust_version.or(latest).unwrap_or_default();
645648

@@ -658,7 +661,7 @@ fn print_lockfile_updates(
658661
}
659662
PackageChangeKind::Unchanged => {
660663
let package_id = change.package_id;
661-
let required_rust_version = report_required_rust_version(ws, resolve, package_id);
664+
let required_rust_version = report_required_rust_version(resolve, change);
662665
let latest = report_latest(&possibilities, package_id);
663666
let note = required_rust_version.as_deref().or(latest.as_deref());
664667

@@ -734,18 +737,14 @@ fn required_rust_version(ws: &Workspace<'_>) -> Option<PartialVersion> {
734737
}
735738
}
736739

737-
fn report_required_rust_version(
738-
ws: &Workspace<'_>,
739-
resolve: &Resolve,
740-
package: PackageId,
741-
) -> Option<String> {
742-
if package.source_id().is_path() {
740+
fn report_required_rust_version(resolve: &Resolve, change: &PackageChange) -> Option<String> {
741+
if change.package_id.source_id().is_path() {
743742
return None;
744743
}
745-
let summary = resolve.summary(package);
744+
let summary = resolve.summary(change.package_id);
746745
let package_rust_version = summary.rust_version()?;
747-
let workspace_rust_version = required_rust_version(ws)?;
748-
if package_rust_version.is_compatible_with(&workspace_rust_version) {
746+
let required_rust_version = change.required_rust_version.as_ref()?;
747+
if package_rust_version.is_compatible_with(required_rust_version) {
749748
return None;
750749
}
751750

@@ -804,6 +803,7 @@ struct PackageChange {
804803
previous_id: Option<PackageId>,
805804
kind: PackageChangeKind,
806805
is_member: Option<bool>,
806+
required_rust_version: Option<PartialVersion>,
807807
}
808808

809809
impl PackageChange {
@@ -847,6 +847,7 @@ impl PackageChange {
847847
previous_id: Some(previous_id),
848848
kind,
849849
is_member,
850+
required_rust_version: None,
850851
};
851852
changes.insert(change.package_id, change);
852853
} else {
@@ -858,6 +859,7 @@ impl PackageChange {
858859
previous_id: None,
859860
kind,
860861
is_member,
862+
required_rust_version: None,
861863
};
862864
changes.insert(change.package_id, change);
863865
}
@@ -869,6 +871,7 @@ impl PackageChange {
869871
previous_id: None,
870872
kind,
871873
is_member,
874+
required_rust_version: None,
872875
};
873876
changes.insert(change.package_id, change);
874877
}
@@ -881,6 +884,7 @@ impl PackageChange {
881884
previous_id: None,
882885
kind,
883886
is_member,
887+
required_rust_version: None,
884888
};
885889
changes.insert(change.package_id, change);
886890
}
@@ -1076,3 +1080,47 @@ impl PackageDiff {
10761080
}
10771081
}
10781082
}
1083+
1084+
fn annotate_required_rust_version(
1085+
ws: &Workspace<'_>,
1086+
resolve: &Resolve,
1087+
changes: &mut IndexMap<PackageId, PackageChange>,
1088+
) {
1089+
let rustc = ws.gctx().load_global_rustc(Some(ws)).ok();
1090+
let rustc_version: Option<PartialVersion> =
1091+
rustc.as_ref().map(|rustc| rustc.version.clone().into());
1092+
1093+
if ws.resolve_honors_rust_version() {
1094+
let mut queue: std::collections::VecDeque<_> = ws
1095+
.members()
1096+
.map(|p| {
1097+
(
1098+
p.rust_version()
1099+
.map(|r| r.clone().into_partial())
1100+
.or_else(|| rustc_version.clone()),
1101+
p.package_id(),
1102+
)
1103+
})
1104+
.collect();
1105+
while let Some((required_rust_version, current_id)) = queue.pop_front() {
1106+
let Some(required_rust_version) = required_rust_version else {
1107+
continue;
1108+
};
1109+
if let Some(change) = changes.get_mut(&current_id) {
1110+
if let Some(existing) = change.required_rust_version.take() {
1111+
if existing <= required_rust_version {
1112+
// Stop early; we already walked down this path with a better match
1113+
change.required_rust_version = Some(existing);
1114+
continue;
1115+
}
1116+
}
1117+
change.required_rust_version = Some(required_rust_version.clone());
1118+
}
1119+
queue.extend(
1120+
resolve
1121+
.deps(current_id)
1122+
.map(|(dep, _)| (Some(required_rust_version.clone()), dep)),
1123+
);
1124+
}
1125+
}
1126+
}

tests/testsuite/rust_version.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,10 +1180,8 @@ fn report_rust_versions() {
11801180
.with_stderr_data(str![[r#"
11811181
[UPDATING] `dummy-registry` index
11821182
[LOCKING] 9 packages to latest Rust 1.60.0 compatible versions
1183-
[ADDING] dep-only-high-compatible v1.65.0 (requires Rust 1.65.0)
11841183
[ADDING] dep-only-high-incompatible v1.75.0 (requires Rust 1.75.0)
11851184
[ADDING] dep-only-low-incompatible v1.75.0 (requires Rust 1.75.0)
1186-
[ADDING] dep-only-unset-compatible v1.75.0 (requires Rust 1.75.0)
11871185
[ADDING] dep-only-unset-incompatible v1.2345.0 (requires Rust 1.2345.0)
11881186
[ADDING] dep-shared-incompatible v1.75.0 (requires Rust 1.75.0)
11891187

0 commit comments

Comments
 (0)