1+ use super :: activation_key:: ActivationKeyNoHash ;
12use super :: dep_cache:: RegistryQueryer ;
23use super :: errors:: ActivateResult ;
34use super :: types:: { ConflictMap , ConflictReason , FeaturesSet , ResolveOpts } ;
45use super :: RequestedFeatures ;
5- use crate :: core:: { Dependency , PackageId , SourceId , Summary } ;
6+ use crate :: core:: { Dependency , PackageId , Summary } ;
67use crate :: util:: interning:: InternedString ;
78use crate :: util:: Graph ;
89use anyhow:: format_err;
910use std:: collections:: HashMap ;
10- use std:: num:: NonZeroU64 ;
1111use tracing:: debug;
1212
1313// A `Context` is basically a bunch of local resolution information which is
@@ -22,56 +22,26 @@ pub struct ResolverContext {
2222 pub resolve_features : im_rc:: HashMap < PackageId , FeaturesSet , rustc_hash:: FxBuildHasher > ,
2323 /// get the package that will be linking to a native library by its links attribute
2424 pub links : im_rc:: HashMap < InternedString , PackageId , rustc_hash:: FxBuildHasher > ,
25-
2625 /// a way to look up for a package in activations what packages required it
2726 /// and all of the exact deps that it fulfilled.
2827 pub parents : Graph < PackageId , im_rc:: HashSet < Dependency , rustc_hash:: FxBuildHasher > > ,
2928}
3029
30+ /// By storing activation keys in a `HashMap` we ensure that there is only one
31+ /// semver compatible version of each crate.
32+ type Activations = im_rc:: HashMap <
33+ ActivationKeyNoHash ,
34+ ( Summary , ContextAge ) ,
35+ nohash_hasher:: BuildNoHashHasher < ActivationKeyNoHash > ,
36+ > ;
37+
3138/// When backtracking it can be useful to know how far back to go.
3239/// The `ContextAge` of a `Context` is a monotonically increasing counter of the number
3340/// of decisions made to get to this state.
3441/// Several structures store the `ContextAge` when it was added,
3542/// to be used in `find_candidate` for backtracking.
3643pub type ContextAge = usize ;
3744
38- /// Find the activated version of a crate based on the name, source, and semver compatibility.
39- /// By storing this in a hash map we ensure that there is only one
40- /// semver compatible version of each crate.
41- /// This all so stores the `ContextAge`.
42- pub type ActivationsKey = ( InternedString , SourceId , SemverCompatibility ) ;
43-
44- pub type Activations =
45- im_rc:: HashMap < ActivationsKey , ( Summary , ContextAge ) , rustc_hash:: FxBuildHasher > ;
46-
47- /// A type that represents when cargo treats two Versions as compatible.
48- /// Versions `a` and `b` are compatible if their left-most nonzero digit is the
49- /// same.
50- #[ derive( Clone , Copy , Eq , PartialEq , Hash , Debug , PartialOrd , Ord ) ]
51- pub enum SemverCompatibility {
52- Major ( NonZeroU64 ) ,
53- Minor ( NonZeroU64 ) ,
54- Patch ( u64 ) ,
55- }
56-
57- impl From < & semver:: Version > for SemverCompatibility {
58- fn from ( ver : & semver:: Version ) -> Self {
59- if let Some ( m) = NonZeroU64 :: new ( ver. major ) {
60- return SemverCompatibility :: Major ( m) ;
61- }
62- if let Some ( m) = NonZeroU64 :: new ( ver. minor ) {
63- return SemverCompatibility :: Minor ( m) ;
64- }
65- SemverCompatibility :: Patch ( ver. patch )
66- }
67- }
68-
69- impl PackageId {
70- pub fn as_activations_key ( self ) -> ActivationsKey {
71- ( self . name ( ) , self . source_id ( ) , self . version ( ) . into ( ) )
72- }
73- }
74-
7545impl ResolverContext {
7646 pub fn new ( ) -> ResolverContext {
7747 ResolverContext {
@@ -98,7 +68,7 @@ impl ResolverContext {
9868 ) -> ActivateResult < bool > {
9969 let id = summary. package_id ( ) ;
10070 let age: ContextAge = self . age ;
101- match self . activations . entry ( id. as_activations_key ( ) ) {
71+ match self . activations . entry ( id. activation_key ( ) . no_hash ( ) ) {
10272 im_rc:: hashmap:: Entry :: Occupied ( o) => {
10373 debug_assert_eq ! (
10474 & o. get( ) . 0 ,
@@ -137,8 +107,13 @@ impl ResolverContext {
137107 // versions came from a `[patch]` source.
138108 if let Some ( ( _, dep) ) = parent {
139109 if dep. source_id ( ) != id. source_id ( ) {
140- let key = ( id. name ( ) , dep. source_id ( ) , id. version ( ) . into ( ) ) ;
141- let prev = self . activations . insert ( key, ( summary. clone ( ) , age) ) ;
110+ let new_id =
111+ PackageId :: new ( id. name ( ) , id. version ( ) . clone ( ) , dep. source_id ( ) ) ;
112+
113+ let prev = self
114+ . activations
115+ . insert ( new_id. activation_key ( ) . no_hash ( ) , ( summary. clone ( ) , age) ) ;
116+
142117 if let Some ( ( previous_summary, _) ) = prev {
143118 return Err (
144119 ( previous_summary. package_id ( ) , ConflictReason :: Semver ) . into ( )
@@ -181,9 +156,13 @@ impl ResolverContext {
181156
182157 /// If the package is active returns the `ContextAge` when it was added
183158 pub fn is_active ( & self , id : PackageId ) -> Option < ContextAge > {
184- self . activations
185- . get ( & id. as_activations_key ( ) )
186- . and_then ( |( s, l) | if s. package_id ( ) == id { Some ( * l) } else { None } )
159+ let ( summary, age) = self . activations . get ( & id. activation_key ( ) . no_hash ( ) ) ?;
160+
161+ if summary. package_id ( ) == id {
162+ Some ( * age)
163+ } else {
164+ None
165+ }
187166 }
188167
189168 /// Checks whether all of `parent` and the keys of `conflicting activations`
@@ -199,8 +178,8 @@ impl ResolverContext {
199178 max = std:: cmp:: max ( max, self . is_active ( parent) ?) ;
200179 }
201180
202- for id in conflicting_activations. keys ( ) {
203- max = std:: cmp:: max ( max, self . is_active ( * id) ?) ;
181+ for & id in conflicting_activations. keys ( ) {
182+ max = std:: cmp:: max ( max, self . is_active ( id) ?) ;
204183 }
205184 Some ( max)
206185 }
0 commit comments