-
Notifications
You must be signed in to change notification settings - Fork 13.3k
MIR-borrowck: emit "foo
does not live long enough" instead of borrow errors
#45360
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
Comments
foo
does not live long enough" instead of borrow errorsfoo
does not live long enough" instead of borrow errors
I don't have time for detailed mentoring notes, but I suspect what we want to do is something like this. We'll add some sort of map in the borrowck context -- when we check either a storagedead or a drop (some things won't have drop), we enter the lvalue being affected into the map and check if we've already reported an error. If so, we do nothing (or, better, use A very first step might be to introduce the map and just use it to suppress some of the current errors, so that we get down to one instance of this message:
instead of 3. (I'm actually not sure where all 3 come from.) |
There's a 1 But sure, we should do the following:
|
So, @arielb1 and I chatted a bit on gitter. Seems like we were thinking in similar directions. Here are some more tips to help get started. First off, the rust/src/librustc_mir/borrow_check.rs Lines 291 to 296 in b7ccb0a
The other place where these errors arise is for the various kinds of DROP terminators (a "terminator" in MIR is an instruction that only runs at the end of a basic block; they are the places where branches in the control flow can occur): rust/src/librustc_mir/borrow_check.rs Lines 314 to 331 in b7ccb0a
DROP terminators correspond to running the destructor, so they also line up with exiting a scope. They precede the rust/src/librustc_mir/borrow_check.rs Lines 592 to 607 in b7ccb0a
Ultimately, a drop always generate a superset of the errors that storage dead do. So, to suppress the duplicates, we can add a map to the MIR borrowck context struct: rust/src/librustc_mir/borrow_check.rs Lines 154 to 162 in b7ccb0a
One question is what type should go into this set. The Hence we would add a field sort of like StatementKind::StorageDead(local) => {
if self.storage_dead_or_drop_error_reported.insert(local) {
self.access_lvalue(ContextKind::StorageDead.new(location),
(&Lvalue::Local(local), span),
(Shallow(None), Write(WriteKind::StorageDead)),
flow_state);
}
} (Similarly for the drop calls.) That ought to at least suppress the duplicates! |
Won't that cause a soundness issue if a local can be borrowed on the normal termination path and can't be borrowed on the unwind path? I think we need to:
|
Hmm, yes, I originally intended to only use the map when an error is reported, but that's not what I wrote, is it?
This seems ok to start. I do think we should at some point pay careful attention to the drop error messages: I think talking about "in the destructor" could help clarify to people why they are getting errors, and it's something we can't clearly say if we use
If we customize the error, then we can't lean on rustc's built-in deduplication, right? |
I haven't had a chance to read the last two comments as apparently GitHub's loading of new comments w/out a refresh stopped working while I was implementing your previous comments. I have a WIP pull request with the previous instructions here: #45989. I'll wait on implementing anything further until we're sure as to the approach we'd like to take. |
The distinction we want to make is between shallow and deep borrows. If there's a shallow borrow, we want to emit a "borrow does not live long enough" regardless of whether we first see a |
MIR-borrowck: emit "`foo` does not live long enough" instead of borrow errors Fixes #45360. As of writing, contains deduplication of existing errors. r? @nikomatsakis
…evant. Since we are now checking activation points, I removed one of the checks at the reservation point. (You can see the effect this had on two-phase-reservation-sharing-interference-2.rs) Also, since we now have checks at both the reservation point and the activation point, we sometimes would observe duplicate errors (since either one independently interferes with another mutable borrow). To deal with this, I used a similar strategy to one used as discussed on issue rust-lang#45360: keep a set of errors reported (in this case for reservations), and then avoid doing the checks for the corresponding activations. (This does mean that some errors could get masked, namely for conflicting borrows that start after the reservation but still conflict with the activation, which is unchecked when there was an error for the reservation. But this seems like a reasonable price to pay.)
…evant. Since we are now checking activation points, I removed one of the checks at the reservation point. (You can see the effect this had on two-phase-reservation-sharing-interference-2.rs) Also, since we now have checks at both the reservation point and the activation point, we sometimes would observe duplicate errors (since either one independently interferes with another mutable borrow). To deal with this, I used a similar strategy to one used as discussed on issue rust-lang#45360: keep a set of errors reported (in this case for reservations), and then avoid doing the checks for the corresponding activations. (This does mean that some errors could get masked, namely for conflicting borrows that start after the reservation but still conflict with the activation, which is unchecked when there was an error for the reservation. But this seems like a reasonable price to pay.)
e.g. in the test
issue-36082.rs
:rust/src/test/compile-fail/issue-36082.rs
Lines 1 to 25 in f6d7514
MIR borrowck currently emits the following errors:
The MIR borrowck errors are correctly detected when the MIR storagedead and drop conflict with the pre-existing borrow.
That is the exact definition of a "does not live long enough" error, so we need to detect this case and instead of showing multiple borrow errors, show a single "does not live long enough" error.
The text was updated successfully, but these errors were encountered: