@@ -118,27 +118,52 @@ impl DataflowConstraints {
118
118
) -> PermissionSet {
119
119
* val & !perms
120
120
}
121
+
122
+ fn restrict_updates (
123
+ & mut self ,
124
+ old : & PermissionSet ,
125
+ new : & PermissionSet ,
126
+ updates_forbidden : & PermissionSet ,
127
+ ) -> PermissionSet {
128
+ let ( old, new, updates_forbidden) = ( * old, * new, * updates_forbidden) ;
129
+ ( new & !updates_forbidden) | ( old & updates_forbidden)
130
+ }
121
131
}
122
132
123
- match self . propagate_inner ( hypothesis, & mut PropagatePerms ) {
133
+ match self . propagate_inner ( hypothesis, & mut PropagatePerms , None ) {
124
134
Ok ( changed) => changed,
125
135
Err ( msg) => {
126
136
panic ! ( "{}" , msg) ;
127
137
}
128
138
}
129
139
}
130
140
141
+ /// Update `xs` by propagating dataflow information of type `T` according to the constraints
142
+ /// recorded in `self`.
143
+ ///
144
+ /// If `updates_forbidden` is provided, then the parts of `xs` indicated by `updates_forbidden`
145
+ /// will not be modified. (Specifically, all updates will be filtered through the method
146
+ /// `PropagateRules::restrict_updates`.)
131
147
fn propagate_inner < T , R > (
132
148
& self ,
133
149
xs : & mut PointerTableMut < T > ,
134
150
rules : & mut R ,
151
+ updates_forbidden : Option < & PointerTable < T > > ,
135
152
) -> Result < bool , String >
136
153
where
137
154
T : PartialEq ,
138
155
R : PropagateRules < T > ,
139
156
{
140
157
let mut xs = TrackedPointerTable :: new ( xs. borrow_mut ( ) ) ;
141
158
159
+ let restrict_updates = |rules : & mut R , ptr, old : & T , new : T | {
160
+ if let Some ( updates_forbidden) = updates_forbidden {
161
+ rules. restrict_updates ( old, & new, & updates_forbidden[ ptr] )
162
+ } else {
163
+ new
164
+ }
165
+ } ;
166
+
142
167
let mut changed = false ;
143
168
let mut i = 0 ;
144
169
loop {
@@ -157,6 +182,8 @@ impl DataflowConstraints {
157
182
let old_a = xs. get ( a) ;
158
183
let old_b = xs. get ( b) ;
159
184
let ( new_a, new_b) = rules. subset ( a, old_a, b, old_b) ;
185
+ let new_a = restrict_updates ( rules, a, old_a, new_a) ;
186
+ let new_b = restrict_updates ( rules, b, old_b, new_b) ;
160
187
xs. set ( a, new_a) ;
161
188
xs. set ( b, new_b) ;
162
189
}
@@ -169,6 +196,8 @@ impl DataflowConstraints {
169
196
let old_a = xs. get ( a) ;
170
197
let old_b = xs. get ( b) ;
171
198
let ( new_a, new_b) = rules. subset_except ( a, old_a, b, old_b, except) ;
199
+ let new_a = restrict_updates ( rules, a, old_a, new_a) ;
200
+ let new_b = restrict_updates ( rules, b, old_b, new_b) ;
172
201
xs. set ( a, new_a) ;
173
202
xs. set ( b, new_b) ;
174
203
}
@@ -180,6 +209,7 @@ impl DataflowConstraints {
180
209
181
210
let old = xs. get ( ptr) ;
182
211
let new = rules. all_perms ( ptr, perms, old) ;
212
+ let new = restrict_updates ( rules, ptr, old, new) ;
183
213
xs. set ( ptr, new) ;
184
214
}
185
215
@@ -190,6 +220,7 @@ impl DataflowConstraints {
190
220
191
221
let old = xs. get ( ptr) ;
192
222
let new = rules. no_perms ( ptr, perms, old) ;
223
+ let new = restrict_updates ( rules, ptr, old, new) ;
193
224
xs. set ( ptr, new) ;
194
225
}
195
226
}
@@ -277,9 +308,19 @@ impl DataflowConstraints {
277
308
) -> FlagSet {
278
309
* val
279
310
}
311
+
312
+ fn restrict_updates (
313
+ & mut self ,
314
+ old : & FlagSet ,
315
+ new : & FlagSet ,
316
+ updates_forbidden : & FlagSet ,
317
+ ) -> FlagSet {
318
+ let ( old, new, updates_forbidden) = ( * old, * new, * updates_forbidden) ;
319
+ ( new & !updates_forbidden) | ( old & updates_forbidden)
320
+ }
280
321
}
281
322
282
- match self . propagate_inner ( & mut flags, & mut Rules { perms } ) {
323
+ match self . propagate_inner ( & mut flags, & mut Rules { perms } , None ) {
283
324
Ok ( _changed) => { }
284
325
Err ( msg) => {
285
326
panic ! ( "{}" , msg) ;
@@ -373,6 +414,9 @@ trait PropagateRules<T> {
373
414
) -> ( T , T ) ;
374
415
fn all_perms ( & mut self , ptr : PointerId , perms : PermissionSet , val : & T ) -> T ;
375
416
fn no_perms ( & mut self , ptr : PointerId , perms : PermissionSet , val : & T ) -> T ;
417
+ /// Apply a filter to restrict updates. The result is similar to `new`, but all flags marked
418
+ /// in `updates_forbidden` are adjusted to match their `old` values.
419
+ fn restrict_updates ( & mut self , old : & T , new : & T , updates_forbidden : & T ) -> T ;
376
420
}
377
421
378
422
pub fn generate_constraints < ' tcx > (
0 commit comments