-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Fix spurious error when a Drop
local has an assignment in a loop
#102078
Conversation
Some changes occurred to MIR optimizations cc @rust-lang/wg-mir-opt |
r? @nagisa (rust-highfive has picked a reviewer for you, use r? to override) |
@bors r+ |
📌 Commit ba8d1eb689dea77b153b0ebb20bfc3d6eceb338a has been approved by It is now in the queue for this repository. |
@bors r- |
`DropAndReplace` terminators are special - unlike all other terminators, they perform two distinct actions (a drop and a store) to the same `Place`. This complicates various analysis passes that we do, which expect at most one of 'Drop'/'Def'/'Use' for a local at a given MIR location. Previously, we categorized a `DropAndReplace` terminator's `Local` access as `MutatingUseContext::Drop`. As a result, livness computation would not consider the `DropAndReplace` as a store ('Def') of a local. The "use live" set would end up being too large (a use would be seen to extend back to an earlier store, rather than the closure `DropAndReplace`). We now explicitly propagate information about `DropAndReplace` terminators via new enum variants `MutatingUseContext:DropAndReplace` and `DefUse::DropAndReplace`. We use this information in liveness computation to record *both* a Drop and a Def. This prevents creating an extra-large "use live" set, while ensuring that te local is still considered "drop live" at the required locations.
ba8d1eb
to
3bb8c22
Compare
@tmiasko Updated |
@bors r=pnkfelix,tmiasko |
r? @pnkfelix |
After doing additional testing, I've found that this PR has an odd effect on this code: struct HasDrop<T>(T);
impl<T> Drop for HasDrop<T> {
fn drop(&mut self) {}
}
#[allow(unused_assignments)]
#[allow(unused_variables)]
fn foo() {
let mut first: u8 = 0;
let mut has_drop = Some(HasDrop(&first));
loop {
match true {
true => {
has_drop = Some(HasDrop(&first));
}
false => {
drop(has_drop);
has_drop = None;
let reborrow = &mut first;
}
}
}
}
fn main() {} It compiles, but only if you have both I'm getting worried that this change is actually unsound in some subtle way. If I can't figure out a simpler way of doing this, then I think we should try to get rid of |
@bors r- |
Desugaring DropAndReplace at MIR build (rust-lang#107844) fixed issue 70919. Add regressions tests, borrowed from rust-lang#102078, to ensure we check for this in the future. Co-authored-by: Aaron Hill <aa1ronham@gmail.com>
Add regression tests for issue 70919 Desugaring DropAndReplace at MIR build (rust-lang#107844) fixed rust-lang#70919. Add regressions tests, borrowed from rust-lang#102078, to ensure we check for this in the future. cc `@Aaron1011`
Add regression tests for issue 70919 Desugaring DropAndReplace at MIR build (rust-lang#107844) fixed rust-lang#70919. Add regressions tests, borrowed from rust-lang#102078, to ensure we check for this in the future. cc ``@Aaron1011``
☔ The latest upstream changes (presumably #108920) made this pull request unmergeable. Please resolve the merge conflicts. |
Fixes #70919
DropAndReplace
terminators are special - unlike all other terminators, they perform two distinct actions (a drop and a store) to the samePlace
. This complicates various analysis passes that we do, which expect at most one of 'Drop'/'Def'/'Use' for a local at a given MIR location.Previously, we categorized a
DropAndReplace
terminator'sLocal
access asMutatingUseContext::Drop
. As a result, livness computation would not consider theDropAndReplace
as a store ('Def') of a local. The "use live" set would end up being too large (a use would be seen to extend back to an earlier store, rather than the closureDropAndReplace
).We now explicitly propagate information about
DropAndReplace
terminators via new enum variantsMutatingUseContext:DropAndReplace
andDefUse::DropAndReplace
. We use this information in liveness computation to record both a Drop and a Def. This prevents creating an extra-large "use live" set, while ensuring that te local is still considered "drop live" at the required locations.