-
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
First attempt at removing DropAndReplace #104488
Conversation
(rustbot has picked a reviewer for you, use r? to override) |
8fdcab4
to
aec002f
Compare
This comment has been minimized.
This comment has been minimized.
r? @nikomatsakis since I think he wrote the MCP. |
☔ The latest upstream changes (presumably #103138) made this pull request unmergeable. Please resolve the merge conflicts. |
Figured out what the problem with the future size was. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initial round of comments
Some(Option::unwrap_or(unwind, resume_block)) | ||
}, | ||
is_replace, | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't follow this logic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's this case here
// drop and replace behind a pointer/array/whatever. The location |
Some changes occurred to MIR optimizations cc @rust-lang/wg-mir-opt Some changes occurred in src/tools/clippy cc @rust-lang/clippy This PR changes MIR cc @oli-obk, @RalfJung, @JakobDegen, @davidtwco, @celinval, @vakaras Some changes occurred to the CTFE / Miri engine cc @rust-lang/miri Some changes occurred in compiler/rustc_codegen_cranelift cc @bjorn3 |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
☔ The latest upstream changes (presumably #106472) made this pull request unmergeable. Please resolve the merge conflicts. |
2303e04
to
54adf94
Compare
This comment has been minimized.
This comment has been minimized.
* document is_replace field in Drop terminator * clarify drop and replace of untracked value
Add DesugaringKind::Replace to emit better diagnostic messages. At the moment it is used for drop and replaces and only the spans that actually contain a `Drop` terminator are marked as such. As there are no explicit drop correspondents in the HIR, marking happens during MIR build.
@oli-obk suggestion to use https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html#method.mark_with_reason seems to be very promising. |
This comment has been minimized.
This comment has been minimized.
DesugaringKind::Replace is added at MIR build and does not show up in the HIR. Remove the desugaring from the span when walking down the HIR in diagnostic so that the span from the HIR correctly matches the span from MIR.
The job Click to see the possible cause of the failure (guessed by this bot)
|
location: Location, | ||
) { | ||
if let mir::TerminatorKind::Drop { place, .. } = terminator.kind { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why this change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The variable shouldn't be considered initialized anymore but it's not handled by drop_flag_effects
as it's not a move.
I think we can't rely on StorageDead
because a drop could panic before reaching that location.
I discovered this problem in
rust/tests/ui/drop/repeat-drop.rs
Line 102 in c8e6a9e
let _v = (DropChecker(1), [panic; 0]); |
The compiler moves
panic
into a temp variable, but since the array it's zero sized, that variable never gets moved anywere and it's immediately dropped.
_8 = move _3; // scope 2 at tests/ui/drop/repeat-drop.rs:105:36: 105:41
drop(_8) -> [return: bb1, unwind: bb9];
bb9 (cleanup): {
drop(_8) -> bb10; // scope 2 at tests/ui/drop/repeat-drop.rs:105:44: 105:45
}
When this unwinds _8
is still considered initialized and drop elab does not remove the drop in bb9, which results in a double drop.
Now, not sure that this mir building is ideal (a panic in dropping a local shouldn't unwind to a block that drops the same local), but I think that what I said above about considering a variable uninitialized the moment it gets dropped still holds.
location: Location, | ||
) { | ||
if let mir::TerminatorKind::Drop { place, .. } = terminator.kind { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why this change?
) | ||
}); | ||
let source_info = this.source_info(span); | ||
unpack!( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any reason you changed build_drop_and_replace
to only include the sad path replace?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initially I removed all assigns and added the sad path one later. In the happy path you need the assign anyway at call site because you may not emit a replace if the type does not need a drop, so you can just add the assign regardless of whether you created a new block for a drop and replace or not.
Anyway, not a strong opinion, I'll revert to the original behavior
Switching to waiting on author until all comments are ticked ✔️ . Feel free to request a review with @rustbot author |
☔ The latest upstream changes (presumably #107727) made this pull request unmergeable. Please resolve the merge conflicts. |
Going to close this for now and split into smaller chunks like #107271 |
Treat Drop as a rmw operation Previously, a Drop terminator was considered a move in MIR. This commit changes the behavior to only treat Drop as a mutable access to the dropped place. In order for this change to be correct, we need to guarantee that 1. A dropped value won't be used again 2. Places that appear in a drop won't be used again before a subsequent initialization. We can ensure this to be correct at MIR construction because Drop will only be emitted when a variable goes out of scope, thus having: * (1) as there is no way of reaching the old value. drop-elaboration will also remove any uninitialized drop. * (2) as the place can't be named following the end of the scope. However, the initialization status, previously tracked by moves, should also be tied to the execution of a Drop, hence the additional logic in the dataflow analyses. From discussion in [this thread](https://rust-lang.zulipchat.com/#narrow/stream/233931-t-compiler.2Fmajor-changes/topic/.60DROP.60.20to.20.60DROP_IF.60.20compiler-team.23558), originating from rust-lang/compiler-team#558. See also rust-lang#104488 (comment)
Treat Drop as a rmw operation Previously, a Drop terminator was considered a move in MIR. This commit changes the behavior to only treat Drop as a mutable access to the dropped place. In order for this change to be correct, we need to guarantee that 1. A dropped value won't be used again 2. Places that appear in a drop won't be used again before a subsequent initialization. We can ensure this to be correct at MIR construction because Drop will only be emitted when a variable goes out of scope, thus having: * (1) as there is no way of reaching the old value. drop-elaboration will also remove any uninitialized drop. * (2) as the place can't be named following the end of the scope. However, the initialization status, previously tracked by moves, should also be tied to the execution of a Drop, hence the additional logic in the dataflow analyses. From discussion in [this thread](https://rust-lang.zulipchat.com/#narrow/stream/233931-t-compiler.2Fmajor-changes/topic/.60DROP.60.20to.20.60DROP_IF.60.20compiler-team.23558), originating from rust-lang/compiler-team#558. See also rust-lang#104488 (comment)
Treat Drop as a rmw operation Previously, a Drop terminator was considered a move in MIR. This commit changes the behavior to only treat Drop as a mutable access to the dropped place. In order for this change to be correct, we need to guarantee that 1. A dropped value won't be used again 2. Places that appear in a drop won't be used again before a subsequent initialization. We can ensure this to be correct at MIR construction because Drop will only be emitted when a variable goes out of scope, thus having: * (1) as there is no way of reaching the old value. drop-elaboration will also remove any uninitialized drop. * (2) as the place can't be named following the end of the scope. However, the initialization status, previously tracked by moves, should also be tied to the execution of a Drop, hence the additional logic in the dataflow analyses. From discussion in [this thread](https://rust-lang.zulipchat.com/#narrow/stream/233931-t-compiler.2Fmajor-changes/topic/.60DROP.60.20to.20.60DROP_IF.60.20compiler-team.23558), originating from rust-lang/compiler-team#558. See also rust-lang#104488 (comment)
Desugaring of drop and replace at MIR build This commit desugars the drop and replace deriving from an assignment at MIR build, avoiding the construction of the `DropAndReplace` terminator (which will be removed in a following PR). In order to retain the same error messages for replaces a new `DesugaringKind::Replace` variant is introduced. The changes in the borrowck are also useful for future work in moving drop elaboration before borrowck, as no `DropAndReplace` would be present there anymore. Notes on test diffs: * `tests/ui/borrowck/issue-58776-borrowck-scans-children`: the assignment deriving from the desugaring kills the borrow. * `tests/ui/async-await/async-fn-size-uninit-locals.rs`, `tests/mir-opt/issue_41110.test.ElaborateDrops.after.mir`, `tests/mir-opt/issue_41888.main.ElaborateDrops.after.mir`: drop elaboration generates (or reads from) a useless drop flag due to an issue with the dataflow analysis. Will be fixed independently by rust-lang#106430. See rust-lang#104488 for more context
Desugaring of drop and replace at MIR build This commit desugars the drop and replace deriving from an assignment at MIR build, avoiding the construction of the `DropAndReplace` terminator (which will be removed in a following PR). In order to retain the same error messages for replaces a new `DesugaringKind::Replace` variant is introduced. The changes in the borrowck are also useful for future work in moving drop elaboration before borrowck, as no `DropAndReplace` would be present there anymore. Notes on test diffs: * `tests/ui/borrowck/issue-58776-borrowck-scans-children`: the assignment deriving from the desugaring kills the borrow. * `tests/ui/async-await/async-fn-size-uninit-locals.rs`, `tests/mir-opt/issue_41110.test.ElaborateDrops.after.mir`, `tests/mir-opt/issue_41888.main.ElaborateDrops.after.mir`: drop elaboration generates (or reads from) a useless drop flag due to an issue with the dataflow analysis. Will be fixed independently by rust-lang/rust#106430. See rust-lang/rust#104488 for more context
First attempt at removing the
DropAndReplace
terminator which complicates things a bit in some cases.Based on zulip/drop-to-drop-if
Eventually, I re-introduced a flag in the
Drop
terminator to indicate whether this drop is from a drop and replace operation. This is used mainly for better diagnostic and to check some invariants.Failing UI Tests
Diagnostic underline whole assignment instead of just the left value
ex:
[ui] src/test/ui/borrowck/borrowck-field-sensitivity.rs
[ui] src/test/ui/borrowck/borrowck-issue-48962.rs
[ui] src/test/ui/borrowck/borrowck-loan-of-static-data-issue-27616.rs
[ui] src/test/ui/borrowck/borrowck-partial-reinit-1.rs
[ui] src/test/ui/borrowck/borrowck-partial-reinit-2.rs
[ui] src/test/ui/borrowck/borrowck-partial-reinit-4.rs
[ui] src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs
[ui] src/test/ui/borrowck/index-mut-help.rs
[ui] src/test/ui/borrowck/issue-45199.rs
[ui] src/test/ui/c-variadic/variadic-ffi-4.rs
[ui] src/test/ui/closures/2229_closure_analysis/diagnostics/box.rs
[ui] src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs
[ui] src/test/ui/nll/issue-27868.rs
[ui] src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs
[ui] src/test/ui/regions/regions-infer-paramd-indirect.rs
[ui] src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.rs
Replace kills loans on previous value
destructured assignment from drop and replace now kills loans. I don't think it's too big of an issue as the assignment should already trigger the borrowck, but the compiler now reports fewer errors in some cases
[ui] src/test/ui/borrowck/issue-58776-borrowck-scans-children.rs
Also fixes #70919 but I didn't add any regression tests for it, might borrow them from #102078 in a separate PR once this lands