@@ -35,25 +35,37 @@ pub(super) fn compute(dump_enabled: bool, mut all_facts: AllFacts) -> Output {
35
35
36
36
let mut result = Output :: new ( dump_enabled) ;
37
37
38
- let borrow_live_at = {
38
+ let errors = {
39
39
// Create a new iteration context, ...
40
40
let mut iteration = Iteration :: new ( ) ;
41
41
42
- // .. some variables and different indices for `subset`.
42
+ // static inputs
43
+ let cfg_edge = iteration. variable :: < ( Point , Point ) > ( "cfg_edge" ) ;
44
+ let killed = all_facts. killed . into ( ) ;
45
+
46
+ // `invalidates` facts, stored ready for joins
47
+ let invalidates = iteration. variable :: < ( ( Loan , Point ) , ( ) ) > ( "invalidates" ) ;
48
+
49
+ // we need `region_live_at` in both variable and relation forms.
50
+ // (respectively, for join and antijoin).
51
+ let region_live_at_rel =
52
+ Relation :: from ( all_facts. region_live_at . iter ( ) . map ( |& ( r, p) | ( r, p) ) ) ;
53
+ let region_live_at_var = iteration. variable :: < ( ( Region , Point ) , ( ) ) > ( "region_live_at" ) ;
54
+
55
+ // variables, indices for the computation rules, and temporaries for the multi-way joins
43
56
let subset = iteration. variable :: < ( Region , Region , Point ) > ( "subset" ) ;
44
57
let subset_1 = iteration. variable_indistinct ( "subset_1" ) ;
45
58
let subset_2 = iteration. variable_indistinct ( "subset_2" ) ;
46
59
let subset_r1p = iteration. variable_indistinct ( "subset_r1p" ) ;
47
60
let subset_p = iteration. variable_indistinct ( "subset_p" ) ;
48
61
49
- // temporaries as we perform a multi-way join, and more indices
50
62
let requires = iteration. variable :: < ( Region , Loan , Point ) > ( "requires" ) ;
51
63
let requires_1 = iteration. variable_indistinct ( "requires_1" ) ;
52
64
let requires_2 = iteration. variable_indistinct ( "requires_2" ) ;
53
65
let requires_bp = iteration. variable_indistinct ( "requires_bp" ) ;
54
66
let requires_rp = iteration. variable_indistinct ( "requires_rp" ) ;
55
67
56
- let borrow_live_at = iteration. variable :: < ( Loan , Point ) > ( "borrow_live_at" ) ;
68
+ let borrow_live_at = iteration. variable :: < ( ( Loan , Point ) , ( ) ) > ( "borrow_live_at" ) ;
57
69
58
70
let live_to_dead_regions =
59
71
iteration. variable :: < ( Region , Region , Point , Point ) > ( "live_to_dead_regions" ) ;
@@ -78,22 +90,19 @@ pub(super) fn compute(dump_enabled: bool, mut all_facts: AllFacts) -> Output {
78
90
iteration. variable :: < ( ( Region , Point , Point ) , Region ) > ( "dead_can_reach_live" ) ;
79
91
let dead_can_reach_live_r1pq = iteration. variable_indistinct ( "dead_can_reach_live_r1pq" ) ;
80
92
81
- // We need both relation and variable forms of this (for join and antijoin).
82
- let region_live_at_rel =
83
- Relation :: from ( all_facts. region_live_at . iter ( ) . map ( |& ( r, p) | ( r, p) ) ) ;
84
- let region_live_at_var = iteration. variable :: < ( ( Region , Point ) , ( ) ) > ( "region_live_at" ) ;
85
-
86
- let cfg_edge_p = iteration. variable :: < ( Point , Point ) > ( "cfg_edge_p" ) ;
87
-
88
- let killed = all_facts. killed . into ( ) ;
93
+ // output
94
+ let errors = iteration. variable ( "errors" ) ;
89
95
90
96
// load initial facts.
91
- subset. insert ( all_facts. outlives . into ( ) ) ;
92
- requires. insert ( all_facts. borrow_region . into ( ) ) ;
97
+ cfg_edge. insert ( all_facts. cfg_edge . into ( ) ) ;
98
+ invalidates. insert ( Relation :: from (
99
+ all_facts. invalidates . iter ( ) . map ( |& ( p, b) | ( ( b, p) , ( ) ) ) ,
100
+ ) ) ;
93
101
region_live_at_var. insert ( Relation :: from (
94
102
all_facts. region_live_at . iter ( ) . map ( |& ( r, p) | ( ( r, p) , ( ) ) ) ,
95
103
) ) ;
96
- cfg_edge_p. insert ( all_facts. cfg_edge . into ( ) ) ;
104
+ subset. insert ( all_facts. outlives . into ( ) ) ;
105
+ requires. insert ( all_facts. borrow_region . into ( ) ) ;
97
106
98
107
// .. and then start iterating rules!
99
108
while iteration. changed ( ) {
@@ -142,9 +151,8 @@ pub(super) fn compute(dump_enabled: bool, mut all_facts: AllFacts) -> Output {
142
151
// cfg_edge(P, Q),
143
152
// region_live_at(R1, Q),
144
153
// !region_live_at(R2, Q).
145
- live_to_dead_regions_1. from_join ( & subset_p, & cfg_edge_p, |& p, & ( r1, r2) , & q| {
146
- ( ( r1, q) , ( r2, p) )
147
- } ) ;
154
+ live_to_dead_regions_1
155
+ . from_join ( & subset_p, & cfg_edge, |& p, & ( r1, r2) , & q| ( ( r1, q) , ( r2, p) ) ) ;
148
156
live_to_dead_regions_2. from_join (
149
157
& live_to_dead_regions_1,
150
158
& region_live_at_var,
@@ -169,7 +177,7 @@ pub(super) fn compute(dump_enabled: bool, mut all_facts: AllFacts) -> Output {
169
177
dead_region_requires_1. from_antijoin ( & requires_bp, & killed, |& ( b, p) , & r| ( p, ( b, r) ) ) ;
170
178
dead_region_requires_2. from_join (
171
179
& dead_region_requires_1,
172
- & cfg_edge_p ,
180
+ & cfg_edge ,
173
181
|& p, & ( b, r) , & q| ( ( r, q) , ( b, p) ) ,
174
182
) ;
175
183
dead_region_requires. from_antijoin (
@@ -236,14 +244,14 @@ pub(super) fn compute(dump_enabled: bool, mut all_facts: AllFacts) -> Output {
236
244
) ;
237
245
238
246
// subset(R1, R2, Q) :-
239
- // subset(R1, R2, P) :-
247
+ // subset(R1, R2, P),
240
248
// cfg_edge(P, Q),
241
249
// region_live_at(R1, Q),
242
250
// region_live_at(R2, Q).
243
251
//
244
252
// Carry `R1 <= R2` from P into Q if both `R1` and
245
253
// `R2` are live in Q.
246
- subset_1. from_join ( & subset_p, & cfg_edge_p , |& _p, & ( r1, r2) , & q| ( ( r1, q) , r2) ) ;
254
+ subset_1. from_join ( & subset_p, & cfg_edge , |& _p, & ( r1, r2) , & q| ( ( r1, q) , r2) ) ;
247
255
subset_2. from_join ( & subset_1, & region_live_at_var, |& ( r1, q) , & r2, & ( ) | {
248
256
( ( r2, q) , r1)
249
257
} ) ;
@@ -281,7 +289,7 @@ pub(super) fn compute(dump_enabled: bool, mut all_facts: AllFacts) -> Output {
281
289
// cfg_edge(P, Q),
282
290
// region_live_at(R, Q).
283
291
requires_1. from_antijoin ( & requires_bp, & killed, |& ( b, p) , & r| ( p, ( r, b) ) ) ;
284
- requires_2. from_join ( & requires_1, & cfg_edge_p , |& _p, & ( r, b) , & q| ( ( r, q) , b) ) ;
292
+ requires_2. from_join ( & requires_1, & cfg_edge , |& _p, & ( r, b) , & q| ( ( r, q) , b) ) ;
285
293
requires. from_join ( & requires_2, & region_live_at_var, |& ( r, q) , & b, & ( ) | {
286
294
( r, b, q)
287
295
} ) ;
@@ -291,8 +299,11 @@ pub(super) fn compute(dump_enabled: bool, mut all_facts: AllFacts) -> Output {
291
299
//
292
300
// borrow_live_at(B, P) :- requires(R, B, P), region_live_at(R, P)
293
301
borrow_live_at. from_join ( & requires_rp, & region_live_at_var, |& ( _r, p) , & b, & ( ) | {
294
- ( b, p)
302
+ ( ( b, p) , ( ) )
295
303
} ) ;
304
+
305
+ // .decl errors(B, P) :- invalidates(B, P), borrow_live_at(B, P).
306
+ errors. from_join ( & invalidates, & borrow_live_at, |& ( b, p) , & ( ) , & ( ) | ( b, p) ) ;
296
307
}
297
308
298
309
if dump_enabled {
@@ -326,22 +337,31 @@ pub(super) fn compute(dump_enabled: bool, mut all_facts: AllFacts) -> Output {
326
337
. or_insert ( BTreeSet :: new ( ) )
327
338
. insert ( * borrow) ;
328
339
}
340
+
341
+ let borrow_live_at = borrow_live_at. complete ( ) ;
342
+ for ( ( borrow, location) , ( ) ) in & borrow_live_at. elements {
343
+ result
344
+ . borrow_live_at
345
+ . entry ( * location)
346
+ . or_insert ( Vec :: new ( ) )
347
+ . push ( * borrow) ;
348
+ }
329
349
}
330
350
331
- borrow_live_at . complete ( )
351
+ errors . complete ( )
332
352
} ;
333
353
334
354
if dump_enabled {
335
355
println ! (
336
- "borrow_live_at is complete: {} tuples, {:?}" ,
337
- borrow_live_at . len( ) ,
356
+ "errors is complete: {} tuples, {:?}" ,
357
+ errors . len( ) ,
338
358
timer. elapsed( )
339
359
) ;
340
360
}
341
361
342
- for ( borrow, location) in & borrow_live_at . elements {
362
+ for ( borrow, location) in & errors . elements {
343
363
result
344
- . borrow_live_at
364
+ . potential_errors
345
365
. entry ( * location)
346
366
. or_insert ( Vec :: new ( ) )
347
367
. push ( * borrow) ;
0 commit comments