@@ -155,6 +155,8 @@ pub(super) fn compute<T: FactTypes>(
155
155
. map ( |& ( origin, point) | ( ( origin, point) , ( ) ) ) ,
156
156
) ;
157
157
158
+ // Rule 1: the initial subsets are the non-transitive `subset_base` static input.
159
+ //
158
160
// subset(origin1, origin2, point) :-
159
161
// subset_base(origin1, origin2, point).
160
162
subset_o1p. extend (
@@ -163,6 +165,8 @@ pub(super) fn compute<T: FactTypes>(
163
165
. map ( |& ( origin1, origin2, point) | ( ( origin1, point) , origin2) ) ,
164
166
) ;
165
167
168
+ // Rule 2: the issuing origins are the ones initially containing loans.
169
+ //
166
170
// origin_contains_loan_on_entry(origin, loan, point) :-
167
171
// loan_issued_at(origin, loan, point).
168
172
origin_contains_loan_on_entry_op. extend (
@@ -192,25 +196,47 @@ pub(super) fn compute<T: FactTypes>(
192
196
. borrow_mut ( )
193
197
. elements
194
198
. retain ( |& ( origin1, origin2, _) | origin1 != origin2) ;
199
+
195
200
subset_placeholder_o2p. from_map ( & subset_placeholder, |& ( origin1, origin2, point) | {
196
201
( ( origin2, point) , origin1)
197
202
} ) ;
198
203
204
+ // Rule 3
205
+ //
199
206
// live_to_dying_regions(origin1, origin2, point1, point2) :-
200
207
// subset(origin1, origin2, point1),
201
208
// cfg_edge(point1, point2),
202
- // origin_live_on_entry(origin1, point2),
209
+ // ( origin_live_on_entry(origin1, point2); placeholder_origin(origin1)), // -> A
203
210
// !origin_live_on_entry(origin2, point2).
211
+ //
212
+ // Since there is one alternative predicate, A, this will result in two expansions
213
+ // of this rule: one for each alternative for predicate A.
214
+ //
215
+ // 1) Rule 3, expansion 1 of 2
216
+ // - predicate A: `origin_live_on_entry(origin1, point2)`
204
217
live_to_dying_regions_o2pq. from_leapjoin (
205
218
& subset_o1p,
206
219
(
207
220
cfg_edge_rel. extend_with ( |& ( ( _, point1) , _) | point1) ,
208
- origin_live_on_entry_rel. extend_with ( |& ( ( origin1, _) , _) | origin1) ,
221
+ origin_live_on_entry_rel. extend_with ( |& ( ( origin1, _) , _) | origin1) , // -> A
222
+ origin_live_on_entry_rel. extend_anti ( |& ( ( _, _) , origin2) | origin2) ,
223
+ ) ,
224
+ |& ( ( origin1, point1) , origin2) , & point2| ( ( origin2, point1, point2) , origin1) ,
225
+ ) ;
226
+ // 2) Rule 3, expansion 2 of 2
227
+ // - predicate A: `placeholder_origin(origin1)`
228
+ live_to_dying_regions_o2pq. from_leapjoin (
229
+ & subset_o1p,
230
+ (
231
+ cfg_edge_rel. extend_with ( |& ( ( _, point1) , _) | point1) ,
232
+ placeholder_origin. filter_with ( |& ( ( origin1, _) , _) | ( origin1, ( ) ) ) , // -> A
209
233
origin_live_on_entry_rel. extend_anti ( |& ( ( _, _) , origin2) | origin2) ,
210
234
) ,
211
235
|& ( ( origin1, point1) , origin2) , & point2| ( ( origin2, point1, point2) , origin1) ,
212
236
) ;
213
237
238
+ // Rule 4
239
+ //
214
240
// dying_region_requires((origin, point1, point2), loan) :-
215
241
// origin_contains_loan_on_entry(origin, loan, point1),
216
242
// !loan_killed_at(loan, point1),
@@ -226,20 +252,26 @@ pub(super) fn compute<T: FactTypes>(
226
252
|& ( ( origin, point1) , loan) , & point2| ( ( origin, point1, point2) , loan) ,
227
253
) ;
228
254
255
+ // Rule 5
256
+ //
229
257
// dying_can_reach_origins(origin2, point1, point2) :-
230
258
// live_to_dying_regions(_, origin2, point1, point2).
231
259
dying_can_reach_origins. from_map (
232
260
& live_to_dying_regions_o2pq,
233
261
|& ( ( origin2, point1, point2) , _origin1) | ( ( origin2, point1) , point2) ,
234
262
) ;
235
263
264
+ // Rule 6
265
+ //
236
266
// dying_can_reach_origins(origin, point1, point2) :-
237
267
// dying_region_requires(origin, point1, point2, _loan).
238
268
dying_can_reach_origins. from_map (
239
269
& dying_region_requires,
240
270
|& ( ( origin, point1, point2) , _loan) | ( ( origin, point1) , point2) ,
241
271
) ;
242
272
273
+ // Rule 7
274
+ //
243
275
// dying_can_reach(origin1, origin2, point1, point2) :-
244
276
// dying_can_reach_origins(origin1, point1, point2),
245
277
// subset(origin1, origin2, point1).
@@ -249,6 +281,8 @@ pub(super) fn compute<T: FactTypes>(
249
281
|& ( origin1, point1) , & point2, & origin2| ( ( origin2, point2) , ( origin1, point1) ) ,
250
282
) ;
251
283
284
+ // Rule 8
285
+ //
252
286
// dying_can_reach(origin1, origin3, point1, point2) :-
253
287
// dying_can_reach(origin1, origin2, point1, point2),
254
288
// !origin_live_on_entry(origin2, point2),
@@ -270,33 +304,96 @@ pub(super) fn compute<T: FactTypes>(
270
304
} ,
271
305
) ;
272
306
307
+ // Rule 9
308
+ //
273
309
// dying_can_reach_live(origin1, origin2, point1, point2) :-
274
310
// dying_can_reach(origin1, origin2, point1, point2),
275
- // origin_live_on_entry(origin2, point2).
311
+ // (origin_live_on_entry(origin2, point2); placeholder_origin(origin2)). // -> A
312
+ //
313
+ // Since there is one alternative predicate, A, this will result in two expansions
314
+ // of this rule: one for each alternative for predicate A.
315
+ //
316
+ // 1) Rule 9, expansion 1 of 2
317
+ // - predicate A: `origin_live_on_entry(origin2, point2)`
276
318
dying_can_reach_live. from_join (
277
319
& dying_can_reach_o2q,
278
- & origin_live_on_entry_var,
320
+ & origin_live_on_entry_var, // -> A
279
321
|& ( origin2, point2) , & ( origin1, point1) , _| ( ( origin1, point1, point2) , origin2) ,
280
322
) ;
323
+ // 2) Rule 9, expansion 2 of 2
324
+ // - predicate A: `placeholder_origin(origin2)`
325
+ dying_can_reach_live. from_leapjoin (
326
+ & dying_can_reach_o2q,
327
+ placeholder_origin. extend_with ( |& ( ( origin2, _) , ( _, _) ) | origin2) , // -> A
328
+ |& ( ( origin2, point2) , ( origin1, point1) ) , _| ( ( origin1, point1, point2) , origin2) ,
329
+ ) ;
281
330
331
+ // Rule 10
332
+ //
282
333
// subset(origin1, origin2, point2) :-
283
334
// subset(origin1, origin2, point1),
284
335
// cfg_edge(point1, point2),
285
- // origin_live_on_entry(origin1, point2),
286
- // origin_live_on_entry(origin2, point2).
336
+ // (origin_live_on_entry(origin1, point2); placeholder_origin(origin1)), // -> A
337
+ // (origin_live_on_entry(origin2, point2); placeholder_origin(origin2)). // -> B
338
+ //
339
+ // Since there are two alternative predicates, A and B, this will result in four
340
+ // expansions of this rule: two alternatives for predicate A, and two alternatives for
341
+ // predicate B.
287
342
//
288
343
// Carry `origin1 <= origin2` from `point1` into `point2` if both `origin1` and
289
344
// `origin2` are live in `point2`.
345
+ //
346
+ // 1) Rule 10, expansion 1 of 4
347
+ // - predicate A: `origin_live_on_entry(origin1, point2)`
348
+ // - predicate B: `origin_live_on_entry(origin2, point2)`
349
+ subset_o1p. from_leapjoin (
350
+ & subset_o1p,
351
+ (
352
+ cfg_edge_rel. extend_with ( |& ( ( _, point1) , _) | point1) ,
353
+ origin_live_on_entry_rel. extend_with ( |& ( ( origin1, _) , _) | origin1) , // -> A
354
+ origin_live_on_entry_rel. extend_with ( |& ( ( _, _) , origin2) | origin2) , // -> B
355
+ ) ,
356
+ |& ( ( origin1, _point1) , origin2) , & point2| ( ( origin1, point2) , origin2) ,
357
+ ) ;
358
+ // 2) Rule 10, expansion 2 of 4
359
+ // - predicate A: `origin_live_on_entry(origin1, point2)`
360
+ // - predicate B: `placeholder_origin(origin2)`
361
+ subset_o1p. from_leapjoin (
362
+ & subset_o1p,
363
+ (
364
+ cfg_edge_rel. extend_with ( |& ( ( _, point1) , _) | point1) ,
365
+ origin_live_on_entry_rel. extend_with ( |& ( ( origin1, _) , _) | origin1) , // -> A
366
+ placeholder_origin. filter_with ( |& ( ( _, _) , origin2) | ( origin2, ( ) ) ) , // -> B
367
+ ) ,
368
+ |& ( ( origin1, _point1) , origin2) , & point2| ( ( origin1, point2) , origin2) ,
369
+ ) ;
370
+ // 3) Rule 10, expansion 3 of 4
371
+ // - predicate A: `placeholder_origin(origin1)`
372
+ // - predicate B: `origin_live_on_entry(origin2, point2)`
290
373
subset_o1p. from_leapjoin (
291
374
& subset_o1p,
292
375
(
293
376
cfg_edge_rel. extend_with ( |& ( ( _, point1) , _) | point1) ,
294
- origin_live_on_entry_rel. extend_with ( |& ( ( origin1, _) , _) | origin1) ,
295
- origin_live_on_entry_rel. extend_with ( |& ( ( _, _) , origin2) | origin2) ,
377
+ placeholder_origin. filter_with ( |& ( ( origin1, _) , _) | ( origin1, ( ) ) ) , // -> A
378
+ origin_live_on_entry_rel. extend_with ( |& ( ( _, _) , origin2) | origin2) , // -> B
379
+ ) ,
380
+ |& ( ( origin1, _point1) , origin2) , & point2| ( ( origin1, point2) , origin2) ,
381
+ ) ;
382
+ // 4) Rule 10, expansion 4 of 4
383
+ // - predicate A: `placeholder_origin(origin1)`
384
+ // - predicate B: `placeholder_origin(origin2)`
385
+ subset_o1p. from_leapjoin (
386
+ & subset_o1p,
387
+ (
388
+ cfg_edge_rel. extend_with ( |& ( ( _, point1) , _) | point1) ,
389
+ placeholder_origin. filter_with ( |& ( ( origin1, _) , _) | ( origin1, ( ) ) ) , // -> A
390
+ placeholder_origin. filter_with ( |& ( ( _, _) , origin2) | ( origin2, ( ) ) ) , // -> B
296
391
) ,
297
392
|& ( ( origin1, _point1) , origin2) , & point2| ( ( origin1, point2) , origin2) ,
298
393
) ;
299
394
395
+ // Rule 11
396
+ //
300
397
// subset(origin1, origin3, point2) :-
301
398
// live_to_dying_regions(origin1, origin2, point1, point2),
302
399
// dying_can_reach_live(origin2, origin3, point1, point2).
@@ -306,6 +403,8 @@ pub(super) fn compute<T: FactTypes>(
306
403
|& ( _origin2, _point1, point2) , & origin1, & origin3| ( ( origin1, point2) , origin3) ,
307
404
) ;
308
405
406
+ // Rule 12
407
+ //
309
408
// origin_contains_loan_on_entry(origin2, loan, point2) :-
310
409
// dying_region_requires(origin1, loan, point1, point2),
311
410
// dying_can_reach_live(origin1, origin2, point1, point2).
@@ -321,35 +420,70 @@ pub(super) fn compute<T: FactTypes>(
321
420
|& ( _origin1, _point1, point2) , & loan, & origin2| ( ( origin2, point2) , loan) ,
322
421
) ;
323
422
423
+ // Rule 13
424
+ //
324
425
// origin_contains_loan_on_entry(origin, loan, point2) :-
325
426
// origin_contains_loan_on_entry(origin, loan, point1),
326
427
// !loan_killed_at(loan, point1),
327
428
// cfg_edge(point1, point2),
328
- // origin_live_on_entry(origin, point2).
429
+ // (origin_live_on_entry(origin, point2); placeholder_origin(origin)). // -> A
430
+ //
431
+ // Since there is one alternative predicate, A, this will result in two expansions
432
+ // of this rule: one for each alternative for predicate A.
433
+ //
434
+ // 1) Rule 13, expansion 1 of 2
435
+ // - predicate A: `origin_live_on_entry(origin, point2)`
436
+ origin_contains_loan_on_entry_op. from_leapjoin (
437
+ & origin_contains_loan_on_entry_op,
438
+ (
439
+ loan_killed_at. filter_anti ( |& ( ( _, point1) , loan) | ( loan, point1) ) ,
440
+ cfg_edge_rel. extend_with ( |& ( ( _, point1) , _) | point1) ,
441
+ origin_live_on_entry_rel. extend_with ( |& ( ( origin, _) , _) | origin) , // -> A
442
+ ) ,
443
+ |& ( ( origin, _) , loan) , & point2| ( ( origin, point2) , loan) ,
444
+ ) ;
445
+ // 2) Rule 13, expansion 2 of 2
446
+ // - predicate A: `placeholder_origin(origin)`
329
447
origin_contains_loan_on_entry_op. from_leapjoin (
330
448
& origin_contains_loan_on_entry_op,
331
449
(
332
450
loan_killed_at. filter_anti ( |& ( ( _, point1) , loan) | ( loan, point1) ) ,
333
451
cfg_edge_rel. extend_with ( |& ( ( _, point1) , _) | point1) ,
334
- origin_live_on_entry_rel . extend_with ( |& ( ( origin, _) , _) | origin) ,
452
+ placeholder_origin . filter_with ( |& ( ( origin, _) , _) | ( origin, ( ) ) ) , // -> A
335
453
) ,
336
454
|& ( ( origin, _) , loan) , & point2| ( ( origin, point2) , loan) ,
337
455
) ;
338
456
457
+ // Rule 14
458
+ //
339
459
// dead_borrow_region_can_reach_root((origin, point), loan) :-
340
460
// loan_issued_at(origin, loan, point),
341
461
// !origin_live_on_entry(origin, point).
462
+ //
463
+ // Even though `loan_issued_at_op` is a Variable here for the antijoin API (and
464
+ // nowadays datafrog's Relations can be built with `Relation::from_antijoin`), this is
465
+ // a join over two static inputs. It should not produce facts each round, and could be
466
+ // moved out of the loop (and most likely should be inlined into rule 15).
467
+ //
342
468
dead_borrow_region_can_reach_root. from_antijoin (
343
469
& loan_issued_at_op,
344
470
& origin_live_on_entry_rel,
345
471
|& ( origin, point) , & loan| ( ( origin, point) , loan) ,
346
472
) ;
347
473
474
+ // Rule 15
475
+ //
348
476
// dead_borrow_region_can_reach_dead((origin, point), loan) :-
349
477
// dead_borrow_region_can_reach_root((origin, point), loan).
478
+ //
479
+ // Note: this is effectively mapping over a static input, and
480
+ // `dead_borrow_region_can_reach_root` could probably be inlined in this relation.
481
+ //
350
482
dead_borrow_region_can_reach_dead
351
483
. from_map ( & dead_borrow_region_can_reach_root, |& tuple| tuple) ;
352
484
485
+ // Rule 16
486
+ //
353
487
// dead_borrow_region_can_reach_dead((origin2, point), loan) :-
354
488
// dead_borrow_region_can_reach_dead(origin1, loan, point),
355
489
// subset(origin1, origin2, point),
@@ -365,30 +499,62 @@ pub(super) fn compute<T: FactTypes>(
365
499
|& ( origin2, point) , & loan| ( ( origin2, point) , loan) ,
366
500
) ;
367
501
502
+ // Rule 17
503
+ //
368
504
// loan_live_at(loan, point) :-
369
505
// origin_contains_loan_on_entry(origin, loan, point),
370
- // origin_live_on_entry(origin, point).
506
+ // (origin_live_on_entry(origin, point); placeholder_origin(origin)). // -> A
507
+ //
508
+ // Since there is one alternative predicate, A, this will result in two expansions
509
+ // of this rule: one for each alternative for predicate A.
510
+ //
511
+ // 1) Rule 17, expansion 1 of 2
512
+ // - predicate A: `origin_live_on_entry(origin, point)`
371
513
loan_live_at. from_join (
372
514
& origin_contains_loan_on_entry_op,
373
- & origin_live_on_entry_var,
515
+ & origin_live_on_entry_var, // -> A
374
516
|& ( _origin, point) , & loan, _| ( ( loan, point) , ( ) ) ,
375
517
) ;
518
+ // 2) Rule 17, expansion 2 of 2
519
+ // - predicate A: `placeholder_origin(origin)`
520
+ loan_live_at. from_leapjoin (
521
+ & origin_contains_loan_on_entry_op,
522
+ placeholder_origin. extend_with ( |& ( ( origin, _point) , _loan) | origin) , // -> A
523
+ |& ( ( _origin, point) , loan) , _| ( ( loan, point) , ( ) ) ,
524
+ ) ;
376
525
526
+ // Rule 18
527
+ //
377
528
// loan_live_at(loan, point) :-
378
529
// dead_borrow_region_can_reach_dead(origin1, loan, point),
379
530
// subset(origin1, origin2, point),
380
- // origin_live_on_entry(origin2, point).
531
+ // (origin_live_on_entry(origin2, point); placeholder_origin(origin2)). // -> A
532
+ //
533
+ // Since there is one alternative predicate, A, this will result in two expansions
534
+ // of this rule: one for each alternative for predicate A.
381
535
//
382
536
// NB: the datafrog code below uses
383
537
// `dead_borrow_region_can_reach_dead_1`, which is equal
384
538
// to `dead_borrow_region_can_reach_dead` and `subset`
385
539
// joined together.
540
+ //
541
+ // 1) Rule 18, expansion 1 of 2
542
+ // - predicate A: `origin_live_on_entry(origin2, point)`
386
543
loan_live_at. from_join (
387
544
& dead_borrow_region_can_reach_dead_1,
388
- & origin_live_on_entry_var,
545
+ & origin_live_on_entry_var, // -> A
389
546
|& ( _origin2, point) , & loan, _| ( ( loan, point) , ( ) ) ,
390
547
) ;
548
+ // 2) Rule 18, expansion 2 of 2
549
+ // - predicate A: `placeholder_origin(origin2)`
550
+ loan_live_at. from_leapjoin (
551
+ & dead_borrow_region_can_reach_dead_1,
552
+ placeholder_origin. extend_with ( |& ( ( origin2, _point) , _loan) | origin2) , // -> A
553
+ |& ( ( _origin2, point) , loan) , _| ( ( loan, point) , ( ) ) ,
554
+ ) ;
391
555
556
+ // Rule 19: compute illegal access errors, i.e. an invalidation of a live loan.
557
+ //
392
558
// errors(loan, point) :-
393
559
// loan_invalidated_at(loan, point),
394
560
// loan_live_at(loan, point).
@@ -398,6 +564,8 @@ pub(super) fn compute<T: FactTypes>(
398
564
|& ( loan, point) , _, _| ( loan, point) ,
399
565
) ;
400
566
567
+ // Rule 20: compute the subsets of the placeholder origins, at a given point.
568
+ //
401
569
// subset_placeholder(Origin1, Origin2, Point) :-
402
570
// subset(Origin1, Origin2, Point),
403
571
// placeholder_origin(Origin1).
@@ -413,6 +581,8 @@ pub(super) fn compute<T: FactTypes>(
413
581
|& ( ( origin1, point) , origin2) , _| ( origin1, origin2, point) ,
414
582
) ;
415
583
584
+ // Rule 21: compute the subset transitive closure of placeholder origins.
585
+ //
416
586
// subset_placeholder(Origin1, Origin3, Point) :-
417
587
// subset_placeholder(Origin1, Origin2, Point),
418
588
// subset(Origin2, Origin3, Point).
@@ -422,7 +592,10 @@ pub(super) fn compute<T: FactTypes>(
422
592
|& ( _origin2, point) , & origin1, & origin3| ( origin1, origin3, point) ,
423
593
) ;
424
594
425
- // subset_error(Origin1, Origin2, Point) :-
595
+ // Rule 22: compute illegal subset relations errors, i.e. the undeclared subsets
596
+ // between two placeholder origins.
597
+ //
598
+ // subset_errors(Origin1, Origin2, Point) :-
426
599
// subset_placeholder(Origin1, Origin2, Point),
427
600
// placeholder_origin(Origin2),
428
601
// !known_placeholder_subset(Origin1, Origin2).
0 commit comments