Description
@lqd opened rust-lang/polonius#157 a while ago, which solves the . Essentially, it transforms all occurrences of Location::All
problem in what I think is the "correct" wayorigin_live_at(O, P)
in rule bodies into (origin_live_at(O, P) OR placeholder(O))
. In other words, placeholder regions are live at all points in the CFG.
Unfortunately it's actually kind of difficult to express that simple idea as a datafrog
program with the current API. The PR manually expanded each rule body into two (one for each side of the OR), but this leads to code that is really difficult to maintain. Another option would be to create an intermediate Relation
, origin_live_at_or_placeholder(O, P)
defined below, to hold the disjunction. That would waste memory, however, and we would also need a new is_point
relation that holds all possible points in the CFG.
origin_live_at_or_placeholder(O, P) :- origin_live_at(O, P).
origin_live_at_or_placeholder(O, P) :- placeholder(O), is_point(P).
Ideally, we would express this disjunction directly as a leaper. This is possible, but is more work than you might expect. An impl that's generic over Leaper
s won't work, since (among other things) there's no way to implement a disjunctive intersect
efficiently with the current Leaper
interface. I think you could do something like the following, but you'd need to handle heterogeneous Value
types as well:
struct<A, B> LeaperOr(A, B);
/* This is the combination of concrete leapers we need, though ideally all combinations would be implemented.*/
impl<...> Leaper<...> for LeaperOr<ExtendWith<...>, FilterWith<...>> {
/* ... */
}
Obviously, this doesn't scale, but maybe it's okay to implement just what we need for rust-lang/polonius#157? The alternative is to adjust the Leaper
interface so that it composes better, but I don't see a straightforward way to do this without resorting to boxed trait objects, which is not an option since they would be dispatched in a tight loop (GATs + RPIT in trait fn
s would solve this, however).