-
Notifications
You must be signed in to change notification settings - Fork 13k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
make causal tracking lazy #46590
Comments
Before we make things lazy, we could also just do some optimization here. The current causal tracking maintains "maximal information", basically, by keeping the entire "cause chain". The current code uses an I propose that we alter the definition of the pub(crate) struct Cause {
/// Length of the outlives chain. This is intentionally first so that we
/// prefer causes that are more directly related (fewer outlives links).
outlives: u32,
/// The "root cause" -- basically, what is live?
root_cause: RootCause,
}
// (this is the old cause enum, minus the `Outlives` variant)
pub(crate) enum RootCause {
/// point inserted because Local was live at the given Location
LiveVar(Local, Location),
/// point inserted because Local was dropped at the given Location
DropVar(Local, Location),
/// point inserted because the type was live at the given Location,
/// but not as part of some local variable
LiveOther(Location),
/// part of the initial set of values for a universally quantified region
UniversalRegion(RegionVid),
} This only tracks the root cause and the number of outlives obligations it took to get there. We can then alter the cause map type to remove the type CauseMap = FxHashMap<(RegionVid, RegionElementIndex), Cause>; In fact, since the number of regions and region-elements are fixed, we could change it to a big vector: Vec<Option<Cause>> If the old key was Finally, we would no longer need the |
It'd be good to measure the running time on various examples. Just test by configuring |
I'll take a look here. If you don't mind. |
OK, so, I talked to @spastorino a bunch in a private chat on how to implement this. I want to leave some brief notes on the plan I drew up. It doesn't yet support a query for use by IDEs, but it should let us fix the immediate problem of not having good diagnostic output. The key ideas are: Always enable causal tracking when creating the When propagating constraints, instead of just cloning Add a new type crate struct RegionCausalInfo {
inferred_values: RegionValues
} and add a method to impl RegionInferenceContext {
crate fn compute_causal_info(&self) -> RegionCausalInfo {
// same thing as `propagate_constraints` today:
// - clone the liveness values (keeping the causal information this time!)
// - propagate the constraints on those values
}
} Move the Then add a field to nonlexical_cause_info: Option<RegionCauseInfo<'tcx>> and modify if self.nonlexical_cause_info.is_none() {
let region_cx = self.nonlexical_regioncx.as_ref().unwrap();
self.nonlexical_cause_info = Some(region_cx.compute_cause_info());
} Then it can invoke Fin. |
[NLL] Avoid borrowed value must be valid for lifetime '_#2r..." in errors Closes #48428 - [x] If NLL is enabled, [do not invoke `note_and_explain_region`](#48428 (comment)) - [x] Modify `-Zdump-nll-cause` to not print [the overwhelming debug output here](https://github.com/rust-lang/rust/blob/master/src/librustc_mir/borrow_check/nll/region_infer/mod.rs#L1288-L1299). This way we should I believe at least get nice-ish output for [our original example](#48428 (comment)). - [x] Extend `explain_why_borrow_contains_point` to also work for "universal lifetimes" like the `'a` in [the example at the end of this comment](#48428 (comment)). - [ ] Figure out how to enable causal information all the time (but that is #46590).
For reference, @chrisvittal made the Rc-improvements I described: they posted a link on gitter to their branch |
After a bit of work, I've put my changes on top of @spastorino's branch, and also squashed them. That branch is here |
…matsakis [NLL] Make causal tracking lazy Close rust-lang#46590 cc @nikomatsakis
The current NLL code tracks "causal" information so that we can give nice errors (see #45988 for more information). The intention is that we will only compute this information once an error is detected. At present, though, we compute it all the time. We should not do that.
The causal tracking code can be found in
values.rs
. In fact, theRegionValues::new
method already takes a boolean parametertrack_causes
indicating whether to track causes, but theRegionInferenceContext
, which creates the value sets, currently always passestrue
.We have to think on the best way to do this. My preference would be to package this "extended causal information" up as a kind of query, so that the MIR borrowck can perform the query only when needed. We would alter the NLL analysis so that it passes
false
for causal information, but then this new query would re-run the NLL analysis, but passingtrue
(like we do today). There are some challenges here though: what format should the result of the query be in, for example?(The reason I wanted a query is that I wanted IDEs and other things to be able to query this information for borrow visualization, and having it be "local" to the borrowck wouldn't offer any visibility for those tools.)
It may however be easier to start by having the borrowck itself just re-run the NLL analysis locally (with tracking enabled) when needed.
The text was updated successfully, but these errors were encountered: