@@ -7,11 +7,46 @@ use std::fmt::{self, Debug, Display};
77use std:: sync:: Arc ;
88
99use crate :: {
10- internal:: { Arena , Id , SmallMap } ,
10+ internal:: { Arena , DecisionLevel , Id , SmallMap } ,
1111 term, DefaultStringReportFormatter , DependencyProvider , DerivationTree , Derived , External , Map ,
1212 PackageArena , PackageId , ReportFormatter , Set , Term , VersionIndex , VersionSet ,
1313} ;
1414
15+ #[ derive( Debug , Clone ) ]
16+ struct ContradicationInfo {
17+ /// Store the decision level when the incompatibility was found to be contradicted.
18+ /// These will stay contradicted until we have backtracked beyond its associated decision level.
19+ decision_level : DecisionLevel ,
20+ /// Store the backtrack generation for the decision level.
21+ backtrack_generation : u32 ,
22+ }
23+
24+ impl ContradicationInfo {
25+ /// Construct a new value.
26+ fn new ( decision_level : DecisionLevel , backtrack_generation : u32 ) -> Self {
27+ Self {
28+ decision_level,
29+ backtrack_generation,
30+ }
31+ }
32+
33+ /// Construct a value interpreted as not contradicted.
34+ fn not_contradicted ( ) -> Self {
35+ Self {
36+ decision_level : DecisionLevel :: MAX ,
37+ backtrack_generation : 0 ,
38+ }
39+ }
40+
41+ /// Check for contradiction.
42+ fn is_contradicted ( & self , last_valid_decision_levels : & [ DecisionLevel ] ) -> bool {
43+ last_valid_decision_levels
44+ . get ( self . backtrack_generation as usize )
45+ . map ( |& l| self . decision_level <= l)
46+ . unwrap_or ( true )
47+ }
48+ }
49+
1550/// An incompatibility is a set of terms for different packages
1651/// that should never be satisfied all together.
1752/// An incompatibility usually originates from a package dependency.
@@ -31,6 +66,7 @@ use crate::{
3166pub ( crate ) struct Incompatibility < M : Eq + Clone + Debug + Display > {
3267 package_terms : SmallMap < PackageId , Term > ,
3368 kind : Kind < M > ,
69+ contradiction_info : ContradicationInfo ,
3470}
3571
3672/// Type alias of unique identifiers for incompatibilities.
@@ -96,6 +132,7 @@ impl<M: Eq + Clone + Debug + Display> Incompatibility<M> {
96132 Term :: negative ( VersionSet :: singleton ( version_index) ) ,
97133 ) ] ) ,
98134 kind : Kind :: NotRoot ( package_id, version_index) ,
135+ contradiction_info : ContradicationInfo :: not_contradicted ( ) ,
99136 }
100137 }
101138
@@ -109,6 +146,7 @@ impl<M: Eq + Clone + Debug + Display> Incompatibility<M> {
109146 Self {
110147 package_terms : SmallMap :: One ( [ ( package_id, term) ] ) ,
111148 kind : Kind :: NoVersions ( package_id, set) ,
149+ contradiction_info : ContradicationInfo :: not_contradicted ( ) ,
112150 }
113151 }
114152
@@ -123,6 +161,7 @@ impl<M: Eq + Clone + Debug + Display> Incompatibility<M> {
123161 Self {
124162 package_terms : SmallMap :: One ( [ ( package_id, term) ] ) ,
125163 kind : Kind :: Custom ( package_id, set, metadata) ,
164+ contradiction_info : ContradicationInfo :: not_contradicted ( ) ,
126165 }
127166 }
128167
@@ -137,6 +176,7 @@ impl<M: Eq + Clone + Debug + Display> Incompatibility<M> {
137176 Self {
138177 package_terms : SmallMap :: One ( [ ( package_id, term) ] ) ,
139178 kind : Kind :: Custom ( package_id, set, metadata) ,
179+ contradiction_info : ContradicationInfo :: not_contradicted ( ) ,
140180 }
141181 }
142182
@@ -157,6 +197,7 @@ impl<M: Eq + Clone + Debug + Display> Incompatibility<M> {
157197 ] )
158198 } ,
159199 kind : Kind :: FromDependencyOf ( package_id, vs, pid2, set2) ,
200+ contradiction_info : ContradicationInfo :: not_contradicted ( ) ,
160201 }
161202 }
162203
@@ -232,6 +273,7 @@ impl<M: Eq + Clone + Debug + Display> Incompatibility<M> {
232273 Self {
233274 package_terms,
234275 kind,
276+ contradiction_info : ContradicationInfo :: not_contradicted ( ) ,
235277 }
236278 }
237279
@@ -252,6 +294,21 @@ impl<M: Eq + Clone + Debug + Display> Incompatibility<M> {
252294 }
253295 }
254296
297+ /// Check if an incompatibility is contradicted.
298+ pub ( crate ) fn is_contradicted ( & self , last_valid_decision_levels : & [ DecisionLevel ] ) -> bool {
299+ self . contradiction_info
300+ . is_contradicted ( last_valid_decision_levels)
301+ }
302+
303+ /// Set incompatibility contradication info.
304+ pub ( crate ) fn set_contradication_info (
305+ & mut self ,
306+ decision_level : DecisionLevel ,
307+ backtrack_generation : u32 ,
308+ ) {
309+ self . contradiction_info = ContradicationInfo :: new ( decision_level, backtrack_generation) ;
310+ }
311+
255312 /// Get the term related to a given package (if it exists).
256313 pub ( crate ) fn get ( & self , package_id : PackageId ) -> Option < Term > {
257314 self . package_terms . get ( & package_id) . copied ( )
@@ -401,12 +458,14 @@ pub(crate) mod tests {
401458 let mut store = Arena :: new( ) ;
402459 let i1 = store. alloc( Incompatibility {
403460 package_terms: SmallMap :: Two ( [ ( PackageId ( 1 ) , t1) , ( PackageId ( 2 ) , t2. negate( ) ) ] ) ,
404- kind: Kind :: <String >:: FromDependencyOf ( PackageId ( 1 ) , VersionSet :: full( ) , PackageId ( 2 ) , VersionSet :: full( ) )
461+ kind: Kind :: <String >:: FromDependencyOf ( PackageId ( 1 ) , VersionSet :: full( ) , PackageId ( 2 ) , VersionSet :: full( ) ) ,
462+ contradiction_info: ContradicationInfo :: not_contradicted( ) ,
405463 } ) ;
406464
407465 let i2 = store. alloc( Incompatibility {
408466 package_terms: SmallMap :: Two ( [ ( PackageId ( 2 ) , t2) , ( PackageId ( 3 ) , t3) ] ) ,
409- kind: Kind :: <String >:: FromDependencyOf ( PackageId ( 2 ) , VersionSet :: full( ) , PackageId ( 3 ) , VersionSet :: full( ) )
467+ kind: Kind :: <String >:: FromDependencyOf ( PackageId ( 2 ) , VersionSet :: full( ) , PackageId ( 3 ) , VersionSet :: full( ) ) ,
468+ contradiction_info: ContradicationInfo :: not_contradicted( ) ,
410469 } ) ;
411470
412471 let mut i3 = Map :: default ( ) ;
0 commit comments