@@ -492,18 +492,19 @@ 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
497- . iter ( )
497+ . values ( )
498498 . filter ( |change| change. kind . is_new ( ) && !change. is_member . unwrap_or ( false ) )
499499 . count ( ) ;
500500 if num_pkgs == 0 {
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- for change in changes {
506+ status_locking ( ws, num_pkgs) ?;
507+ for change in changes. values ( ) {
507508 if change. is_member . unwrap_or ( false ) {
508509 continue ;
509510 } ;
@@ -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,18 +554,19 @@ 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
558- . iter ( )
559+ . values ( )
559560 . filter ( |change| change. kind . is_new ( ) && !change. is_member . unwrap_or ( false ) )
560561 . count ( ) ;
561562 if num_pkgs == 0 {
562563 // nothing worth reporting
563564 return Ok ( ( ) ) ;
564565 }
565- status_locking ( ws, num_pkgs ) ? ;
566+ annotate_required_rust_version ( ws, resolve , & mut changes ) ;
566567
567- for change in changes {
568+ status_locking ( ws, num_pkgs) ?;
569+ for change in changes. values ( ) {
568570 if change. is_member . unwrap_or ( false ) {
569571 continue ;
570572 } ;
@@ -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,14 +612,18 @@ fn print_lockfile_updates(
610612 precise : bool ,
611613 registry : & mut PackageRegistry < ' _ > ,
612614) -> CargoResult < ( ) > {
613- let changes = PackageChange :: diff ( ws, previous_resolve, resolve) ;
614- let num_pkgs: usize = changes. iter ( ) . filter ( |change| change. kind . is_new ( ) ) . count ( ) ;
615+ let mut changes = PackageChange :: diff ( ws, previous_resolve, resolve) ;
616+ let num_pkgs: usize = changes
617+ . values ( )
618+ . filter ( |change| change. kind . is_new ( ) )
619+ . count ( ) ;
620+ annotate_required_rust_version ( ws, resolve, & mut changes) ;
621+
615622 if !precise {
616623 status_locking ( ws, num_pkgs) ?;
617624 }
618-
619625 let mut unchanged_behind = 0 ;
620- for change in changes {
626+ for change in changes. values ( ) {
621627 let possibilities = if let Some ( query) = change. alternatives_query ( ) {
622628 loop {
623629 match registry. query_vec ( & query, QueryKind :: Exact ) {
@@ -636,7 +642,7 @@ fn print_lockfile_updates(
636642 | PackageChangeKind :: Upgraded
637643 | PackageChangeKind :: Downgraded => {
638644 let package_id = change. package_id ;
639- let required_rust_version = report_required_rust_version ( ws , resolve, package_id ) ;
645+ let required_rust_version = report_required_rust_version ( resolve, change ) ;
640646 let latest = report_latest ( & possibilities, package_id) ;
641647 let note = required_rust_version. or ( latest) . unwrap_or_default ( ) ;
642648
@@ -655,7 +661,7 @@ fn print_lockfile_updates(
655661 }
656662 PackageChangeKind :: Unchanged => {
657663 let package_id = change. package_id ;
658- let required_rust_version = report_required_rust_version ( ws , resolve, package_id ) ;
664+ let required_rust_version = report_required_rust_version ( resolve, change ) ;
659665 let latest = report_latest ( & possibilities, package_id) ;
660666 let note = required_rust_version. as_deref ( ) . or ( latest. as_deref ( ) ) ;
661667
@@ -731,24 +737,20 @@ fn required_rust_version(ws: &Workspace<'_>) -> Option<PartialVersion> {
731737 }
732738}
733739
734- fn report_required_rust_version (
735- ws : & Workspace < ' _ > ,
736- resolve : & Resolve ,
737- package : PackageId ,
738- ) -> Option < String > {
739- 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 ( ) {
740742 return None ;
741743 }
742- let summary = resolve. summary ( package ) ;
744+ let summary = resolve. summary ( change . package_id ) ;
743745 let package_rust_version = summary. rust_version ( ) ?;
744- let workspace_rust_version = required_rust_version ( ws ) ?;
745- 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 ) {
746748 return None ;
747749 }
748750
749- let warn = style:: WARN ;
751+ let error = style:: ERROR ;
750752 Some ( format ! (
751- " {warn }(requires Rust {package_rust_version}){warn :#}"
753+ " {error }(requires Rust {package_rust_version}){error :#}"
752754 ) )
753755}
754756
@@ -801,20 +803,28 @@ struct PackageChange {
801803 previous_id : Option < PackageId > ,
802804 kind : PackageChangeKind ,
803805 is_member : Option < bool > ,
806+ required_rust_version : Option < PartialVersion > ,
804807}
805808
806809impl PackageChange {
807- pub fn new ( ws : & Workspace < ' _ > , resolve : & Resolve ) -> Vec < Self > {
810+ pub fn new ( ws : & Workspace < ' _ > , resolve : & Resolve ) -> IndexMap < PackageId , Self > {
808811 let diff = PackageDiff :: new ( resolve) ;
809812 Self :: with_diff ( diff, ws)
810813 }
811814
812- pub fn diff ( ws : & Workspace < ' _ > , previous_resolve : & Resolve , resolve : & Resolve ) -> Vec < Self > {
815+ pub fn diff (
816+ ws : & Workspace < ' _ > ,
817+ previous_resolve : & Resolve ,
818+ resolve : & Resolve ,
819+ ) -> IndexMap < PackageId , Self > {
813820 let diff = PackageDiff :: diff ( previous_resolve, resolve) ;
814821 Self :: with_diff ( diff, ws)
815822 }
816823
817- fn with_diff ( diff : impl Iterator < Item = PackageDiff > , ws : & Workspace < ' _ > ) -> Vec < Self > {
824+ fn with_diff (
825+ diff : impl Iterator < Item = PackageDiff > ,
826+ ws : & Workspace < ' _ > ,
827+ ) -> IndexMap < PackageId , Self > {
818828 let member_ids: HashSet < _ > = ws. members ( ) . map ( |p| p. package_id ( ) ) . collect ( ) ;
819829
820830 let mut changes = IndexMap :: new ( ) ;
@@ -837,6 +847,7 @@ impl PackageChange {
837847 previous_id : Some ( previous_id) ,
838848 kind,
839849 is_member,
850+ required_rust_version : None ,
840851 } ;
841852 changes. insert ( change. package_id , change) ;
842853 } else {
@@ -848,6 +859,7 @@ impl PackageChange {
848859 previous_id : None ,
849860 kind,
850861 is_member,
862+ required_rust_version : None ,
851863 } ;
852864 changes. insert ( change. package_id , change) ;
853865 }
@@ -859,6 +871,7 @@ impl PackageChange {
859871 previous_id : None ,
860872 kind,
861873 is_member,
874+ required_rust_version : None ,
862875 } ;
863876 changes. insert ( change. package_id , change) ;
864877 }
@@ -871,12 +884,13 @@ impl PackageChange {
871884 previous_id : None ,
872885 kind,
873886 is_member,
887+ required_rust_version : None ,
874888 } ;
875889 changes. insert ( change. package_id , change) ;
876890 }
877891 }
878892
879- changes. into_values ( ) . collect ( )
893+ changes
880894 }
881895
882896 /// For querying [`PackageRegistry`] for alternative versions to report to the user
@@ -1066,3 +1080,46 @@ impl PackageDiff {
10661080 }
10671081 }
10681082}
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 . as_ref ( ) {
1111+ if * existing <= required_rust_version {
1112+ // Stop early; we already walked down this path with a better match
1113+ continue ;
1114+ }
1115+ }
1116+ change. required_rust_version = Some ( required_rust_version. clone ( ) ) ;
1117+ }
1118+ queue. extend (
1119+ resolve
1120+ . deps ( current_id)
1121+ . map ( |( dep, _) | ( Some ( required_rust_version. clone ( ) ) , dep) ) ,
1122+ ) ;
1123+ }
1124+ }
1125+ }
0 commit comments