@@ -39,7 +39,9 @@ use semver::VersionReq;
3939use crate :: Paths ;
4040use crate :: fixups:: ResolverDependencyFixup ;
4141use crate :: fixups:: resolver_fixups_for_package;
42+ use crate :: semver_ext:: CompatibilityLane ;
4243use crate :: semver_ext:: version_bounds_subset;
44+ use crate :: semver_ext:: version_compatibility_lane;
4345use crate :: semver_ext:: version_req_bounds;
4446use crate :: semver_ext:: version_req_is_broad;
4547use crate :: semver_ext:: version_req_to_compatibility_lane;
@@ -64,7 +66,7 @@ struct DependencyEdgeKey {
6466#[ derive( Clone , Debug , Eq , Ord , PartialEq , PartialOrd ) ]
6567struct PackageKey {
6668 name : String ,
67- version : Version ,
69+ compatibility_lane : CompatibilityLane ,
6870 source : SourceKey ,
6971}
7072
@@ -162,9 +164,11 @@ impl<'gctx, S: CargoSource> DeterministicSource<'gctx, S> {
162164 }
163165 }
164166
165- let narrowed_req = if let Some ( previous) =
166- self . previous_locked_edge ( parent, & dependency, & effective_req)
167- {
167+ let previous = match self . previous_locked_edge ( parent, & dependency, & effective_req) {
168+ Ok ( previous) => previous,
169+ Err ( err) => return Poll :: Ready ( Err ( err) ) ,
170+ } ;
171+ let narrowed_req = if let Some ( previous) = previous {
168172 match version_req_to_compatibility_lane ( & effective_req, previous. version ( ) ) {
169173 Ok ( req) => req,
170174 Err ( err) => return Poll :: Ready ( Err ( err) ) ,
@@ -227,16 +231,17 @@ impl<'gctx, S: CargoSource> DeterministicSource<'gctx, S> {
227231 parent : PackageId ,
228232 dependency : & Dependency ,
229233 effective_req : & VersionReq ,
230- ) -> Option < PackageId > {
231- let previous = self
232- . context
233- . previous_edges
234- . get ( & dependency_edge_key ( parent, dependency) ) ?;
234+ ) -> anyhow:: Result < Option < PackageId > > {
235+ let key = dependency_edge_key ( parent, dependency) ?;
236+ let previous = self . context . previous_edges . get ( & key) ;
237+ let Some ( previous) = previous else {
238+ return Ok ( None ) ;
239+ } ;
235240 if previous. name ( ) == dependency. package_name ( ) && effective_req. matches ( previous. version ( ) )
236241 {
237- Some ( * previous)
242+ Ok ( Some ( * previous) )
238243 } else {
239- None
244+ Ok ( None )
240245 }
241246 }
242247
@@ -335,31 +340,34 @@ fn query_candidate_versions(
335340 Poll :: Ready ( Ok ( candidate_versions_from_summaries ( candidates) ) )
336341}
337342
338- fn dependency_edge_key ( parent : PackageId , dependency : & Dependency ) -> DependencyEdgeKey {
339- DependencyEdgeKey {
340- parent : package_key ( parent) ,
343+ fn dependency_edge_key (
344+ parent : PackageId ,
345+ dependency : & Dependency ,
346+ ) -> anyhow:: Result < DependencyEdgeKey > {
347+ Ok ( DependencyEdgeKey {
348+ parent : package_key ( parent) ?,
341349 dependency_name_in_toml : dependency. name_in_toml ( ) . as_str ( ) . to_owned ( ) ,
342350 dependency_source : source_key ( dependency. source_id ( ) ) ,
343- }
351+ } )
344352}
345353
346354fn selected_package_edge_key (
347355 parent : PackageId ,
348356 selected_dependency : PackageId ,
349- ) -> DependencyEdgeKey {
350- DependencyEdgeKey {
351- parent : package_key ( parent) ,
357+ ) -> anyhow :: Result < DependencyEdgeKey > {
358+ Ok ( DependencyEdgeKey {
359+ parent : package_key ( parent) ? ,
352360 dependency_name_in_toml : selected_dependency. name ( ) . as_str ( ) . to_owned ( ) ,
353361 dependency_source : source_key ( selected_dependency. source_id ( ) ) ,
354- }
362+ } )
355363}
356364
357- fn package_key ( package : PackageId ) -> PackageKey {
358- PackageKey {
365+ fn package_key ( package : PackageId ) -> anyhow :: Result < PackageKey > {
366+ Ok ( PackageKey {
359367 name : package. name ( ) . as_str ( ) . to_owned ( ) ,
360- version : package. version ( ) . clone ( ) ,
368+ compatibility_lane : version_compatibility_lane ( package. version ( ) ) ? ,
361369 source : source_key ( package. source_id ( ) ) ,
362- }
370+ } )
363371}
364372
365373fn source_key ( source_id : SourceId ) -> SourceKey {
@@ -491,6 +499,7 @@ pub(crate) fn resolve_ws_deterministically_with_original_sources<'gctx>(
491499 let previous_edges = previous_resolve
492500 . as_ref ( )
493501 . map ( previous_dependency_edges)
502+ . transpose ( ) ?
494503 . unwrap_or_default ( ) ;
495504 let root_patch_summaries = root_patch_summaries ( workspace, & source_config) ?;
496505 let mut source_ids = deterministic_source_ids ( workspace, previous_resolve. as_ref ( ) , gctx) ?;
@@ -775,24 +784,27 @@ fn validate_version_req_subset(narrowed: &VersionReq, original: &VersionReq) ->
775784
776785fn previous_dependency_edges (
777786 previous_resolve : & cargo:: core:: resolver:: Resolve ,
778- ) -> BTreeMap < DependencyEdgeKey , PackageId > {
787+ ) -> anyhow :: Result < BTreeMap < DependencyEdgeKey , PackageId > > {
779788 let mut edges = BTreeMap :: new ( ) ;
780789 for parent in previous_resolve. iter ( ) {
781790 for ( selected_dependency, dependencies) in previous_resolve. deps ( parent) {
782791 let mut inserted_dependency = false ;
783792 for dependency in dependencies {
784793 inserted_dependency = true ;
785- edges. insert ( dependency_edge_key ( parent, dependency) , selected_dependency) ;
794+ edges. insert (
795+ dependency_edge_key ( parent, dependency) ?,
796+ selected_dependency,
797+ ) ;
786798 }
787799 if !inserted_dependency {
788800 edges. insert (
789- selected_package_edge_key ( parent, selected_dependency) ,
801+ selected_package_edge_key ( parent, selected_dependency) ? ,
790802 selected_dependency,
791803 ) ;
792804 }
793805 }
794806 }
795- edges
807+ Ok ( edges)
796808}
797809
798810#[ cfg( test) ]
@@ -1970,11 +1982,11 @@ narrow_to = "1"
19701982 ) ;
19711983 context. previous_edges = BTreeMap :: from ( [
19721984 (
1973- super :: dependency_edge_key ( parent, & alpha_01x) ,
1985+ super :: dependency_edge_key ( parent, & alpha_01x) . unwrap ( ) ,
19741986 PackageId :: try_new ( "alpha" , "0.1.0" , source_id) . unwrap ( ) ,
19751987 ) ,
19761988 (
1977- super :: dependency_edge_key ( parent, & alpha_02x) ,
1989+ super :: dependency_edge_key ( parent, & alpha_02x) . unwrap ( ) ,
19781990 PackageId :: try_new ( "alpha" , "0.2.0" , source_id) . unwrap ( ) ,
19791991 ) ,
19801992 ] ) ;
@@ -2015,6 +2027,64 @@ narrow_to = "1"
20152027 assert_eq ! ( dependency_reqs[ "alpha-02x" ] , ">=0.2.0, <0.3.0" ) ;
20162028 }
20172029
2030+ #[ test]
2031+ fn test_previous_locked_edges_apply_across_parent_semver_lane ( ) {
2032+ let tempdir = tempfile:: tempdir ( ) . unwrap ( ) ;
2033+ let cargo_home = tempdir. path ( ) . join ( ".cargo" ) ;
2034+
2035+ let shell = cargo:: core:: Shell :: new ( ) ;
2036+ let mut gctx =
2037+ cargo:: GlobalContext :: new ( shell, tempdir. path ( ) . to_owned ( ) , cargo_home. clone ( ) ) ;
2038+ gctx. configure ( 0 , true , None , false , false , false , & None , & [ ] , & [ ] )
2039+ . unwrap ( ) ;
2040+ let source_id = SourceId :: crates_io ( & gctx) . unwrap ( ) ;
2041+ let source_config = SourceConfigMap :: new ( & gctx) . unwrap ( ) ;
2042+ let previous_parent = PackageId :: try_new ( "a" , "1.0.0" , source_id) . unwrap ( ) ;
2043+ let previous_dependency = dependency ( "b" , ">=1, <3" , source_id) ;
2044+ let mut context = deterministic_source_context (
2045+ source_config,
2046+ tempdir. path ( ) . to_owned ( ) ,
2047+ [ source_id] ,
2048+ Rc :: new ( RefCell :: new ( BTreeSet :: new ( ) ) ) ,
2049+ ) ;
2050+ context. previous_edges = BTreeMap :: from ( [ (
2051+ super :: dependency_edge_key ( previous_parent, & previous_dependency) . unwrap ( ) ,
2052+ PackageId :: try_new ( "b" , "1.2.3" , source_id) . unwrap ( ) ,
2053+ ) ] ) ;
2054+ let mut source = DeterministicSource :: new (
2055+ RecordingSource :: new (
2056+ source_id,
2057+ vec ! [
2058+ summary_with_deps(
2059+ "a" ,
2060+ "1.0.1" ,
2061+ source_id,
2062+ vec![ dependency( "b" , ">=1, <3" , source_id) ] ,
2063+ ) ,
2064+ summary( "b" , "1.2.3" , source_id) ,
2065+ summary( "b" , "2.0.0" , source_id) ,
2066+ ] ,
2067+ ) ,
2068+ context,
2069+ ) ;
2070+
2071+ let mut rewritten_req = None ;
2072+ let result = source. query (
2073+ & dependency ( "a" , "=1.0.1" , source_id) ,
2074+ QueryKind :: Exact ,
2075+ & mut |summary| {
2076+ rewritten_req = Some (
2077+ summary. as_summary ( ) . dependencies ( ) [ 0 ]
2078+ . version_req ( )
2079+ . to_string ( ) ,
2080+ ) ;
2081+ } ,
2082+ ) ;
2083+
2084+ assert ! ( matches!( result, Poll :: Ready ( Ok ( ( ) ) ) ) ) ;
2085+ assert_eq ! ( rewritten_req. as_deref( ) , Some ( ">=1.0.0, <2.0.0" ) ) ;
2086+ }
2087+
20182088 #[ test]
20192089 fn test_previous_locked_edges_treat_crates_io_registry_and_sparse_as_same_source ( ) {
20202090 let tempdir = tempfile:: tempdir ( ) . unwrap ( ) ;
@@ -2038,7 +2108,7 @@ narrow_to = "1"
20382108 Rc :: new ( RefCell :: new ( BTreeSet :: new ( ) ) ) ,
20392109 ) ;
20402110 context. previous_edges = BTreeMap :: from ( [ (
2041- super :: dependency_edge_key ( previous_parent, & previous_dependency) ,
2111+ super :: dependency_edge_key ( previous_parent, & previous_dependency) . unwrap ( ) ,
20422112 PackageId :: try_new ( "reqwest" , "0.12.28" , registry_source_id) . unwrap ( ) ,
20432113 ) ] ) ;
20442114 let mut source = DeterministicSource :: new (
@@ -2112,7 +2182,7 @@ narrow_to = "1"
21122182 [ sparse_source_id] ,
21132183 Rc :: new ( RefCell :: new ( BTreeSet :: new ( ) ) ) ,
21142184 ) ;
2115- context. previous_edges = super :: previous_dependency_edges ( & previous_resolve) ;
2185+ context. previous_edges = super :: previous_dependency_edges ( & previous_resolve) . unwrap ( ) ;
21162186 let mut source = DeterministicSource :: new (
21172187 RecordingSource :: new (
21182188 sparse_source_id,
0 commit comments