1
+ use super :: activation_key:: ActivationKeyNoHash ;
1
2
use super :: dep_cache:: RegistryQueryer ;
2
3
use super :: errors:: ActivateResult ;
3
4
use super :: types:: { ConflictMap , ConflictReason , FeaturesSet , ResolveOpts } ;
4
5
use super :: RequestedFeatures ;
5
- use crate :: core:: { Dependency , PackageId , SourceId , Summary } ;
6
+ use crate :: core:: { Dependency , PackageId , Summary } ;
6
7
use crate :: util:: interning:: InternedString ;
7
8
use crate :: util:: Graph ;
8
9
use anyhow:: format_err;
9
10
use std:: collections:: HashMap ;
10
- use std:: num:: NonZeroU64 ;
11
11
use tracing:: debug;
12
12
13
13
// A `Context` is basically a bunch of local resolution information which is
@@ -22,56 +22,26 @@ pub struct ResolverContext {
22
22
pub resolve_features : im_rc:: HashMap < PackageId , FeaturesSet , rustc_hash:: FxBuildHasher > ,
23
23
/// get the package that will be linking to a native library by its links attribute
24
24
pub links : im_rc:: HashMap < InternedString , PackageId , rustc_hash:: FxBuildHasher > ,
25
-
26
25
/// a way to look up for a package in activations what packages required it
27
26
/// and all of the exact deps that it fulfilled.
28
27
pub parents : Graph < PackageId , im_rc:: HashSet < Dependency , rustc_hash:: FxBuildHasher > > ,
29
28
}
30
29
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
+
31
38
/// When backtracking it can be useful to know how far back to go.
32
39
/// The `ContextAge` of a `Context` is a monotonically increasing counter of the number
33
40
/// of decisions made to get to this state.
34
41
/// Several structures store the `ContextAge` when it was added,
35
42
/// to be used in `find_candidate` for backtracking.
36
43
pub type ContextAge = usize ;
37
44
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
-
75
45
impl ResolverContext {
76
46
pub fn new ( ) -> ResolverContext {
77
47
ResolverContext {
@@ -98,7 +68,7 @@ impl ResolverContext {
98
68
) -> ActivateResult < bool > {
99
69
let id = summary. package_id ( ) ;
100
70
let age: ContextAge = self . age ;
101
- match self . activations . entry ( id. as_activations_key ( ) ) {
71
+ match self . activations . entry ( id. activation_key ( ) . no_hash ( ) ) {
102
72
im_rc:: hashmap:: Entry :: Occupied ( o) => {
103
73
debug_assert_eq ! (
104
74
& o. get( ) . 0 ,
@@ -137,8 +107,13 @@ impl ResolverContext {
137
107
// versions came from a `[patch]` source.
138
108
if let Some ( ( _, dep) ) = parent {
139
109
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
+
142
117
if let Some ( ( previous_summary, _) ) = prev {
143
118
return Err (
144
119
( previous_summary. package_id ( ) , ConflictReason :: Semver ) . into ( )
@@ -181,9 +156,13 @@ impl ResolverContext {
181
156
182
157
/// If the package is active returns the `ContextAge` when it was added
183
158
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
+ }
187
166
}
188
167
189
168
/// Checks whether all of `parent` and the keys of `conflicting activations`
@@ -199,8 +178,8 @@ impl ResolverContext {
199
178
max = std:: cmp:: max ( max, self . is_active ( parent) ?) ;
200
179
}
201
180
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) ?) ;
204
183
}
205
184
Some ( max)
206
185
}
0 commit comments