Description
Solving region constraints currently accounts for 8% of MIR borrowck time in clap-rs. However, we are doing more work than we need to do. This part of the inference engine processes outlives constraints like 'a: 'b
, which says that the region 'a
outlives 'b
and therefore should be a superset of the points in 'b
. To process such a constraint we therefore take all the points in 'b
and add them to 'a
:
rust/src/librustc_mir/borrow_check/nll/region_infer/values.rs
Lines 246 to 250 in 2808460
You can see therefore that a constraint like 'a: 'a
is pretty uninteresting. It is also uninterested to have two of the same constraints ('b: 'c
, 'b: 'c
), since processing the first one will also solve the second one.
However, a cursory examination of the constraints from many examples reveals that we have both a lot of duplicates and a lot of X: X
identity constraints. I find about ~30% of the constraints are duplicated.
Part of the reason for this is that, in the original NLL proposal and in Polonius, we distinguished not only 'a: 'b
but also the location where it occurs ('a: 'b @ P
). We are no longer using this P
information so it would be good to discard it (and the next gen region inference engine, polonius, uses a different data structures for its constraints anyway). (Interestingly, even if we take the location P
into account, it is still true that most of the constraints are duplicated, so there is likely a win here waiting for polonius as well at some future point.)
The constraints in question are instances of this struct:
rust/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
Lines 120 to 146 in 2808460
They are stored in a vector here:
rust/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
Lines 70 to 71 in 2808460
Most elements of this vector I believe are given in RegionInferenceContext::new
:
but some are later added via add_outlives
:
rust/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
Lines 390 to 407 in 2808460
The initial vector is populated by the MIR type check in this call here:
rust/src/librustc_mir/borrow_check/nll/type_check/mod.rs
Lines 759 to 768 in 7008a95
So to solve this problem we would want to detect duplicates somehow, probably taking just sub+sup into account. The only reason to also include the location is that it may be useful in reporting errors later. It probably makes sense to do this by adding a FxHashSet<(RegionVid, RegionVid)>
to detect duplicates, though it might make sense to extract the vector itself from both the RegionInferenceContext
and the MIR type check into a common data structure (OutlivesConstraintSet
or something) that keeps the FxHashSet
and the Vec
in one.