@@ -162,7 +162,7 @@ public protocol DependencyResolverDelegate {
162
162
/// A bound version for a package within an assignment.
163
163
//
164
164
// FIXME: This should be nested, but cannot be currently.
165
- enum BoundVersion {
165
+ enum BoundVersion : Equatable {
166
166
/// The assignment should not include the package.
167
167
///
168
168
/// This is different from the absence of an assignment for a particular
@@ -173,6 +173,18 @@ enum BoundVersion {
173
173
/// The version of the package to include.
174
174
case version( Version )
175
175
}
176
+ func == ( _ lhs: BoundVersion , _ rhs: BoundVersion ) -> Bool {
177
+ switch ( lhs, rhs) {
178
+ case ( . excluded, . excluded) :
179
+ return true
180
+ case ( . excluded, _) :
181
+ return false
182
+ case ( . version( let lhs) , . version( let rhs) ) :
183
+ return lhs == rhs
184
+ case ( . version, _) :
185
+ return false
186
+ }
187
+ }
176
188
177
189
/// A container for constraints for a set of packages.
178
190
//
@@ -286,6 +298,43 @@ struct VersionAssignmentSet<C: PackageContainer> {
286
298
}
287
299
}
288
300
301
+ /// Merge in the bindings from the given `assignment`.
302
+ ///
303
+ /// - Returns: False if the merge cannot be made (the assignments contain
304
+ /// incompatible versions).
305
+ mutating func merge( _ assignment: VersionAssignmentSet < Container > ) -> Bool {
306
+ // In order to protect the assignment set, we first have to test whether
307
+ // the merged constraint sets are satisfiable.
308
+ //
309
+ // FIXME: Move to non-mutating methods with results, in order to have a
310
+ // nice consistent API with `PackageContainerConstraintSet.merge`.
311
+ //
312
+ // FIXME: This is very inefficient; we should decide whether it is right
313
+ // to handle it here or force the main resolver loop to handle the
314
+ // discovery of this property.
315
+ var mergedConstraints = constraints
316
+ guard mergedConstraints. merge ( assignment. constraints) else {
317
+ return false
318
+ }
319
+
320
+ // The induced constraints are satisfiable, so we *can* union the
321
+ // assignments without breaking our internal invariant on
322
+ // satisfiability.
323
+ for entry in assignment. assignments. values {
324
+ if let existing = self [ entry. container] {
325
+ if existing != entry. binding {
326
+ // NOTE: We are returning here with the data structure
327
+ // partially updated, which feels wrong. See FIXME above.
328
+ return false
329
+ }
330
+ } else {
331
+ self [ entry. container] = entry. binding
332
+ }
333
+ }
334
+
335
+ return true
336
+ }
337
+
289
338
/// The combined version constraints induced by the assignment.
290
339
///
291
340
/// This consists of the merged constraints which need to be satisfied on
0 commit comments