@@ -58,7 +58,7 @@ impl Debug for ConflictAnalysisContext<'_> {
58
58
}
59
59
}
60
60
61
- impl < ' a > ConflictAnalysisContext < ' a > {
61
+ impl ConflictAnalysisContext < ' _ > {
62
62
/// Returns the last decision which was made by the solver.
63
63
pub ( crate ) fn find_last_decision ( & mut self ) -> Option < Predicate > {
64
64
self . assignments . find_last_decision ( )
@@ -132,15 +132,20 @@ impl<'a> ConflictAnalysisContext<'a> {
132
132
133
133
/// Returns the reason for a propagation; if it is implied then the reason will be the decision
134
134
/// which implied the predicate.
135
+ #[ allow(
136
+ clippy:: too_many_arguments,
137
+ reason = "borrow checker complains either here or elsewhere"
138
+ ) ]
135
139
pub ( crate ) fn get_propagation_reason (
136
140
predicate : Predicate ,
137
141
assignments : & Assignments ,
138
142
current_nogood : CurrentNogood < ' _ > ,
139
- reason_store : & ' a mut ReasonStore ,
140
- propagators : & ' a mut PropagatorStore ,
141
- proof_log : & ' a mut ProofLog ,
143
+ reason_store : & mut ReasonStore ,
144
+ propagators : & mut PropagatorStore ,
145
+ proof_log : & mut ProofLog ,
142
146
unit_nogood_step_ids : & HashMap < Predicate , StepId > ,
143
- ) -> & ' a [ Predicate ] {
147
+ reason_out : & mut ( impl Extend < Predicate > + AsRef < [ Predicate ] > ) ,
148
+ ) {
144
149
// TODO: this function could be put into the reason store
145
150
146
151
// Note that this function can only be called with propagations, and never decision
@@ -156,9 +161,8 @@ impl<'a> ConflictAnalysisContext<'a> {
156
161
// there would be only one predicate from the current decision level. For this
157
162
// reason, it is safe to assume that in the following, that any input predicate is
158
163
// indeed a propagated predicate.
159
- reason_store. helper . clear ( ) ;
160
164
if assignments. is_initial_bound ( predicate) {
161
- return reason_store . helper . as_slice ( ) ;
165
+ return ;
162
166
}
163
167
164
168
let trail_position = assignments
@@ -179,11 +183,17 @@ impl<'a> ConflictAnalysisContext<'a> {
179
183
180
184
let explanation_context = ExplanationContext :: new ( assignments, current_nogood) ;
181
185
182
- let reason = reason_store
183
- . get_or_compute ( reason_ref, explanation_context, propagators)
184
- . expect ( "reason reference should not be stale" ) ;
186
+ let reason_exists = reason_store. get_or_compute (
187
+ reason_ref,
188
+ explanation_context,
189
+ propagators,
190
+ reason_out,
191
+ ) ;
192
+
193
+ assert ! ( reason_exists, "reason reference should not be stale" ) ;
194
+
185
195
if propagator_id == ConstraintSatisfactionSolver :: get_nogood_propagator_id ( )
186
- && reason . is_empty ( )
196
+ && reason_out . as_ref ( ) . is_empty ( )
187
197
{
188
198
// This means that a unit nogood was propagated, we indicate that this nogood step
189
199
// was used
@@ -207,12 +217,10 @@ impl<'a> ConflictAnalysisContext<'a> {
207
217
// Otherwise we log the inference which was used to derive the nogood
208
218
let _ = proof_log. log_inference (
209
219
constraint_tag,
210
- reason . iter ( ) . copied ( ) ,
220
+ reason_out . as_ref ( ) . iter ( ) . copied ( ) ,
211
221
Some ( predicate) ,
212
222
) ;
213
223
}
214
- reason
215
- // The predicate is implicitly due as a result of a decision.
216
224
}
217
225
// 2) The predicate is true due to a propagation, and not explicitly on the trail.
218
226
// It is necessary to further analyse what was the reason for setting the predicate true.
@@ -240,7 +248,7 @@ impl<'a> ConflictAnalysisContext<'a> {
240
248
// todo: could consider lifting here, since the trail bound
241
249
// might be too strong.
242
250
if trail_lower_bound > input_lower_bound {
243
- reason_store . helper . push ( trail_entry. predicate ) ;
251
+ reason_out . extend ( std :: iter :: once ( trail_entry. predicate ) ) ;
244
252
}
245
253
// Otherwise, the input bound is strictly greater than the trailed
246
254
// bound. This means the reason is due to holes in the domain.
@@ -270,8 +278,8 @@ impl<'a> ConflictAnalysisContext<'a> {
270
278
domain_id,
271
279
not_equal_constant : input_lower_bound - 1 ,
272
280
} ;
273
- reason_store . helper . push ( one_less_bound_predicate) ;
274
- reason_store . helper . push ( not_equals_predicate) ;
281
+ reason_out . extend ( std :: iter :: once ( one_less_bound_predicate) ) ;
282
+ reason_out . extend ( std :: iter :: once ( not_equals_predicate) ) ;
275
283
}
276
284
}
277
285
(
@@ -291,7 +299,7 @@ impl<'a> ConflictAnalysisContext<'a> {
291
299
// so it safe to take the reason from the trail.
292
300
// todo: lifting could be used here
293
301
pumpkin_assert_simple ! ( trail_lower_bound > not_equal_constant) ;
294
- reason_store . helper . push ( trail_entry. predicate ) ;
302
+ reason_out . extend ( std :: iter :: once ( trail_entry. predicate ) ) ;
295
303
}
296
304
(
297
305
Predicate :: LowerBound {
@@ -323,8 +331,8 @@ impl<'a> ConflictAnalysisContext<'a> {
323
331
domain_id,
324
332
upper_bound : equality_constant,
325
333
} ;
326
- reason_store . helper . push ( predicate_lb) ;
327
- reason_store . helper . push ( predicate_ub) ;
334
+ reason_out . extend ( std :: iter :: once ( predicate_lb) ) ;
335
+ reason_out . extend ( std :: iter :: once ( predicate_ub) ) ;
328
336
}
329
337
(
330
338
Predicate :: UpperBound {
@@ -344,7 +352,7 @@ impl<'a> ConflictAnalysisContext<'a> {
344
352
// reason for the input predicate.
345
353
// todo: lifting could be applied here.
346
354
if trail_upper_bound < input_upper_bound {
347
- reason_store . helper . push ( trail_entry. predicate ) ;
355
+ reason_out . extend ( std :: iter :: once ( trail_entry. predicate ) ) ;
348
356
} else {
349
357
// I think it cannot be that the bounds are equal, since otherwise we
350
358
// would have found the predicate explicitly on the trail.
@@ -365,8 +373,8 @@ impl<'a> ConflictAnalysisContext<'a> {
365
373
domain_id,
366
374
not_equal_constant : input_upper_bound + 1 ,
367
375
} ;
368
- reason_store . helper . push ( new_ub_predicate) ;
369
- reason_store . helper . push ( not_equal_predicate) ;
376
+ reason_out . extend ( std :: iter :: once ( new_ub_predicate) ) ;
377
+ reason_out . extend ( std :: iter :: once ( not_equal_predicate) ) ;
370
378
}
371
379
}
372
380
(
@@ -387,7 +395,7 @@ impl<'a> ConflictAnalysisContext<'a> {
387
395
388
396
// The bound was set past the not equals, so we can safely returns the trail
389
397
// reason. todo: can do lifting here.
390
- reason_store . helper . push ( trail_entry. predicate ) ;
398
+ reason_out . extend ( std :: iter :: once ( trail_entry. predicate ) ) ;
391
399
}
392
400
(
393
401
Predicate :: UpperBound {
@@ -422,8 +430,8 @@ impl<'a> ConflictAnalysisContext<'a> {
422
430
domain_id,
423
431
upper_bound : equality_constant,
424
432
} ;
425
- reason_store . helper . push ( predicate_lb) ;
426
- reason_store . helper . push ( predicate_ub) ;
433
+ reason_out . extend ( std :: iter :: once ( predicate_lb) ) ;
434
+ reason_out . extend ( std :: iter :: once ( predicate_ub) ) ;
427
435
}
428
436
(
429
437
Predicate :: NotEqual {
@@ -457,8 +465,8 @@ impl<'a> ConflictAnalysisContext<'a> {
457
465
not_equal_constant : input_lower_bound - 1 ,
458
466
} ;
459
467
460
- reason_store . helper . push ( new_lb_predicate) ;
461
- reason_store . helper . push ( new_not_equals_predicate) ;
468
+ reason_out . extend ( std :: iter :: once ( new_lb_predicate) ) ;
469
+ reason_out . extend ( std :: iter :: once ( new_not_equals_predicate) ) ;
462
470
}
463
471
(
464
472
Predicate :: NotEqual {
@@ -492,8 +500,8 @@ impl<'a> ConflictAnalysisContext<'a> {
492
500
not_equal_constant : input_upper_bound + 1 ,
493
501
} ;
494
502
495
- reason_store . helper . push ( new_ub_predicate) ;
496
- reason_store . helper . push ( new_not_equals_predicate) ;
503
+ reason_out . extend ( std :: iter :: once ( new_ub_predicate) ) ;
504
+ reason_out . extend ( std :: iter :: once ( new_not_equals_predicate) ) ;
497
505
}
498
506
(
499
507
Predicate :: NotEqual {
@@ -522,15 +530,14 @@ impl<'a> ConflictAnalysisContext<'a> {
522
530
upper_bound : equality_constant,
523
531
} ;
524
532
525
- reason_store . helper . push ( predicate_lb) ;
526
- reason_store . helper . push ( predicate_ub) ;
533
+ reason_out . extend ( std :: iter :: once ( predicate_lb) ) ;
534
+ reason_out . extend ( std :: iter :: once ( predicate_ub) ) ;
527
535
}
528
536
_ => unreachable ! (
529
537
"Unreachable combination of {} and {}" ,
530
538
trail_entry. predicate, predicate
531
539
) ,
532
540
} ;
533
- reason_store. helper . as_slice ( )
534
541
}
535
542
}
536
543
}
0 commit comments