@@ -7,6 +7,7 @@ use crate::core::{PackageId, PackageIdSpec, PackageIdSpecQuery};
77use crate :: core:: { Resolve , SourceId , Workspace } ;
88use crate :: ops;
99use crate :: sources:: source:: QueryKind ;
10+ use crate :: sources:: IndexSummary ;
1011use crate :: util:: cache_lock:: CacheLockMode ;
1112use crate :: util:: context:: GlobalContext ;
1213use crate :: util:: toml_mut:: dependency:: { MaybeWorkspace , Source } ;
@@ -15,6 +16,7 @@ use crate::util::toml_mut::upgrade::upgrade_requirement;
1516use crate :: util:: { style, OptVersionReq } ;
1617use crate :: util:: { CargoResult , VersionExt } ;
1718use anyhow:: Context as _;
19+ use cargo_util_schemas:: core:: PartialVersion ;
1820use itertools:: Itertools ;
1921use semver:: { Op , Version , VersionReq } ;
2022use std:: cmp:: Ordering ;
@@ -498,10 +500,6 @@ fn print_lockfile_generation(
498500 status_locking ( ws, num_pkgs) ?;
499501
500502 for diff in diff {
501- fn format_latest ( version : semver:: Version ) -> String {
502- let warn = style:: WARN ;
503- format ! ( " {warn}(latest: v{version}){warn:#}" )
504- }
505503 let possibilities = if let Some ( query) = diff. alternatives_query ( ) {
506504 loop {
507505 match registry. query_vec ( & query, QueryKind :: Exact ) {
@@ -516,22 +514,14 @@ fn print_lockfile_generation(
516514 } ;
517515
518516 for package in diff. added . iter ( ) {
519- let latest = if !possibilities. is_empty ( ) {
520- possibilities
521- . iter ( )
522- . map ( |s| s. as_summary ( ) )
523- . filter ( |s| is_latest ( s. version ( ) , package. version ( ) ) )
524- . map ( |s| s. version ( ) . clone ( ) )
525- . max ( )
526- . map ( format_latest)
527- } else {
528- None
529- } ;
517+ let required_rust_version = report_required_rust_version ( ws, resolve, * package) ;
518+ let latest = report_latest ( & possibilities, * package) ;
519+ let note = required_rust_version. or ( latest) ;
530520
531- if let Some ( latest ) = latest {
521+ if let Some ( note ) = note {
532522 ws. gctx ( ) . shell ( ) . status_with_color (
533523 "Adding" ,
534- format ! ( "{package}{latest }" ) ,
524+ format ! ( "{package}{note }" ) ,
535525 & style:: NOTE ,
536526 ) ?;
537527 }
@@ -555,10 +545,6 @@ fn print_lockfile_sync(
555545 status_locking ( ws, num_pkgs) ?;
556546
557547 for diff in diff {
558- fn format_latest ( version : semver:: Version ) -> String {
559- let warn = style:: WARN ;
560- format ! ( " {warn}(latest: v{version}){warn:#}" )
561- }
562548 let possibilities = if let Some ( query) = diff. alternatives_query ( ) {
563549 loop {
564550 match registry. query_vec ( & query, QueryKind :: Exact ) {
@@ -610,22 +596,13 @@ fn print_lockfile_sync(
610596 }
611597 } else {
612598 for package in diff. added . iter ( ) {
613- let latest = if !possibilities. is_empty ( ) {
614- possibilities
615- . iter ( )
616- . map ( |s| s. as_summary ( ) )
617- . filter ( |s| is_latest ( s. version ( ) , package. version ( ) ) )
618- . map ( |s| s. version ( ) . clone ( ) )
619- . max ( )
620- . map ( format_latest)
621- } else {
622- None
623- }
624- . unwrap_or_default ( ) ;
599+ let required_rust_version = report_required_rust_version ( ws, resolve, * package) ;
600+ let latest = report_latest ( & possibilities, * package) ;
601+ let note = required_rust_version. or ( latest) . unwrap_or_default ( ) ;
625602
626603 ws. gctx ( ) . shell ( ) . status_with_color (
627604 "Adding" ,
628- format ! ( "{package}{latest }" ) ,
605+ format ! ( "{package}{note }" ) ,
629606 & style:: NOTE ,
630607 ) ?;
631608 }
@@ -650,10 +627,6 @@ fn print_lockfile_updates(
650627
651628 let mut unchanged_behind = 0 ;
652629 for diff in diff {
653- fn format_latest ( version : semver:: Version ) -> String {
654- let warn = style:: WARN ;
655- format ! ( " {warn}(latest: v{version}){warn:#}" )
656- }
657630 let possibilities = if let Some ( query) = diff. alternatives_query ( ) {
658631 loop {
659632 match registry. query_vec ( & query, QueryKind :: Exact ) {
@@ -668,26 +641,17 @@ fn print_lockfile_updates(
668641 } ;
669642
670643 if let Some ( ( removed, added) ) = diff. change ( ) {
671- let latest = if !possibilities. is_empty ( ) {
672- possibilities
673- . iter ( )
674- . map ( |s| s. as_summary ( ) )
675- . filter ( |s| is_latest ( s. version ( ) , added. version ( ) ) )
676- . map ( |s| s. version ( ) . clone ( ) )
677- . max ( )
678- . map ( format_latest)
679- } else {
680- None
681- }
682- . unwrap_or_default ( ) ;
644+ let required_rust_version = report_required_rust_version ( ws, resolve, * added) ;
645+ let latest = report_latest ( & possibilities, * added) ;
646+ let note = required_rust_version. or ( latest) . unwrap_or_default ( ) ;
683647
684648 let msg = if removed. source_id ( ) . is_git ( ) {
685649 format ! (
686- "{removed} -> #{}" ,
650+ "{removed} -> #{}{note} " ,
687651 & added. source_id( ) . precise_git_fragment( ) . unwrap( ) [ ..8 ] ,
688652 )
689653 } else {
690- format ! ( "{removed} -> v{}{latest }" , added. version( ) )
654+ format ! ( "{removed} -> v{}{note }" , added. version( ) )
691655 } ;
692656
693657 // If versions differ only in build metadata, we call it an "update"
@@ -712,45 +676,30 @@ fn print_lockfile_updates(
712676 ) ?;
713677 }
714678 for package in diff. added . iter ( ) {
715- let latest = if !possibilities. is_empty ( ) {
716- possibilities
717- . iter ( )
718- . map ( |s| s. as_summary ( ) )
719- . filter ( |s| is_latest ( s. version ( ) , package. version ( ) ) )
720- . map ( |s| s. version ( ) . clone ( ) )
721- . max ( )
722- . map ( format_latest)
723- } else {
724- None
725- }
726- . unwrap_or_default ( ) ;
679+ let required_rust_version = report_required_rust_version ( ws, resolve, * package) ;
680+ let latest = report_latest ( & possibilities, * package) ;
681+ let note = required_rust_version. or ( latest) . unwrap_or_default ( ) ;
727682
728683 ws. gctx ( ) . shell ( ) . status_with_color (
729684 "Adding" ,
730- format ! ( "{package}{latest }" ) ,
685+ format ! ( "{package}{note }" ) ,
731686 & style:: NOTE ,
732687 ) ?;
733688 }
734689 }
735690 for package in & diff. unchanged {
736- let latest = if !possibilities. is_empty ( ) {
737- possibilities
738- . iter ( )
739- . map ( |s| s. as_summary ( ) )
740- . filter ( |s| is_latest ( s. version ( ) , package. version ( ) ) )
741- . map ( |s| s. version ( ) . clone ( ) )
742- . max ( )
743- . map ( format_latest)
744- } else {
745- None
746- } ;
691+ let required_rust_version = report_required_rust_version ( ws, resolve, * package) ;
692+ let latest = report_latest ( & possibilities, * package) ;
693+ let note = required_rust_version. as_deref ( ) . or ( latest. as_deref ( ) ) ;
747694
748- if let Some ( latest) = latest {
749- unchanged_behind += 1 ;
695+ if let Some ( note) = note {
696+ if latest. is_some ( ) {
697+ unchanged_behind += 1 ;
698+ }
750699 if ws. gctx ( ) . shell ( ) . verbosity ( ) == Verbosity :: Verbose {
751700 ws. gctx ( ) . shell ( ) . status_with_color (
752701 "Unchanged" ,
753- format ! ( "{package}{latest }" ) ,
702+ format ! ( "{package}{note }" ) ,
754703 & anstyle:: Style :: new ( ) . bold ( ) ,
755704 ) ?;
756705 }
@@ -788,14 +737,7 @@ fn status_locking(ws: &Workspace<'_>, num_pkgs: usize) -> CargoResult<()> {
788737 write ! ( & mut cfg, " latest" ) ?;
789738 }
790739
791- if ws. resolve_honors_rust_version ( ) {
792- let rust_version = if let Some ( ver) = ws. rust_version ( ) {
793- ver. clone ( ) . into_partial ( )
794- } else {
795- let rustc = ws. gctx ( ) . load_global_rustc ( Some ( ws) ) ?;
796- let rustc_version = rustc. version . clone ( ) . into ( ) ;
797- rustc_version
798- } ;
740+ if let Some ( rust_version) = required_rust_version ( ws) {
799741 write ! ( & mut cfg, " Rust {rust_version}" ) ?;
800742 }
801743 write ! ( & mut cfg, " compatible version{plural}" ) ?;
@@ -807,6 +749,60 @@ fn status_locking(ws: &Workspace<'_>, num_pkgs: usize) -> CargoResult<()> {
807749 Ok ( ( ) )
808750}
809751
752+ fn required_rust_version ( ws : & Workspace < ' _ > ) -> Option < PartialVersion > {
753+ if !ws. resolve_honors_rust_version ( ) {
754+ return None ;
755+ }
756+
757+ if let Some ( ver) = ws. rust_version ( ) {
758+ Some ( ver. clone ( ) . into_partial ( ) )
759+ } else {
760+ let rustc = ws. gctx ( ) . load_global_rustc ( Some ( ws) ) . ok ( ) ?;
761+ let rustc_version = rustc. version . clone ( ) . into ( ) ;
762+ Some ( rustc_version)
763+ }
764+ }
765+
766+ fn report_required_rust_version (
767+ ws : & Workspace < ' _ > ,
768+ resolve : & Resolve ,
769+ package : PackageId ,
770+ ) -> Option < String > {
771+ if package. source_id ( ) . is_path ( ) {
772+ return None ;
773+ }
774+ let summary = resolve. summary ( package) ;
775+ let package_rust_version = summary. rust_version ( ) ?;
776+ let workspace_rust_version = required_rust_version ( ws) ?;
777+ if package_rust_version. is_compatible_with ( & workspace_rust_version) {
778+ return None ;
779+ }
780+
781+ let warn = style:: WARN ;
782+ Some ( format ! (
783+ " {warn}(requires Rust {package_rust_version}){warn:#}"
784+ ) )
785+ }
786+
787+ fn report_latest ( possibilities : & [ IndexSummary ] , package : PackageId ) -> Option < String > {
788+ if !package. source_id ( ) . is_registry ( ) {
789+ return None ;
790+ }
791+
792+ possibilities
793+ . iter ( )
794+ . map ( |s| s. as_summary ( ) )
795+ . filter ( |s| is_latest ( s. version ( ) , package. version ( ) ) )
796+ . map ( |s| s. version ( ) . clone ( ) )
797+ . max ( )
798+ . map ( format_latest)
799+ }
800+
801+ fn format_latest ( version : semver:: Version ) -> String {
802+ let warn = style:: WARN ;
803+ format ! ( " {warn}(latest: v{version}){warn:#}" )
804+ }
805+
810806fn is_latest ( candidate : & semver:: Version , current : & semver:: Version ) -> bool {
811807 current < candidate
812808 // Only match pre-release if major.minor.patch are the same
0 commit comments