Auto merge of #107844 - Zeegomo:no-drop-and-rep, r=cjgillot
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 https://github.com/rust-lang/rust/pull/106430. See https://github.com/rust-lang/rust/pull/104488 for more context
This commit is contained in:
commit
14c54b637b
22 changed files with 286 additions and 157 deletions
|
@ -40,7 +40,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
// Generate better code for things that don't need to be
|
||||
// dropped.
|
||||
if lhs.ty.needs_drop(this.tcx, this.param_env) {
|
||||
let rhs = unpack!(block = this.as_local_operand(block, rhs));
|
||||
let rhs = unpack!(block = this.as_local_rvalue(block, rhs));
|
||||
let lhs = unpack!(block = this.as_place(block, lhs));
|
||||
unpack!(block = this.build_drop_and_replace(block, lhs_span, lhs, rhs));
|
||||
} else {
|
||||
|
|
|
@ -91,7 +91,7 @@ use rustc_middle::middle::region;
|
|||
use rustc_middle::mir::*;
|
||||
use rustc_middle::thir::{Expr, LintLevel};
|
||||
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_span::{DesugaringKind, Span, DUMMY_SP};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Scopes<'tcx> {
|
||||
|
@ -1118,24 +1118,35 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
}
|
||||
|
||||
/// Utility function for *non*-scope code to build their own drops
|
||||
/// Force a drop at this point in the MIR by creating a new block.
|
||||
pub(crate) fn build_drop_and_replace(
|
||||
&mut self,
|
||||
block: BasicBlock,
|
||||
span: Span,
|
||||
place: Place<'tcx>,
|
||||
value: Operand<'tcx>,
|
||||
value: Rvalue<'tcx>,
|
||||
) -> BlockAnd<()> {
|
||||
let span = self.tcx.with_stable_hashing_context(|hcx| {
|
||||
span.mark_with_reason(None, DesugaringKind::Replace, self.tcx.sess.edition(), hcx)
|
||||
});
|
||||
let source_info = self.source_info(span);
|
||||
let next_target = self.cfg.start_new_block();
|
||||
|
||||
// create the new block for the assignment
|
||||
let assign = self.cfg.start_new_block();
|
||||
self.cfg.push_assign(assign, source_info, place, value.clone());
|
||||
|
||||
// create the new block for the assignment in the case of unwinding
|
||||
let assign_unwind = self.cfg.start_new_cleanup_block();
|
||||
self.cfg.push_assign(assign_unwind, source_info, place, value.clone());
|
||||
|
||||
self.cfg.terminate(
|
||||
block,
|
||||
source_info,
|
||||
TerminatorKind::DropAndReplace { place, value, target: next_target, unwind: None },
|
||||
TerminatorKind::Drop { place, target: assign, unwind: Some(assign_unwind) },
|
||||
);
|
||||
self.diverge_from(block);
|
||||
|
||||
next_target.unit()
|
||||
assign.unit()
|
||||
}
|
||||
|
||||
/// Creates an `Assert` terminator and return the success block.
|
||||
|
@ -1413,8 +1424,15 @@ impl<'tcx> DropTreeBuilder<'tcx> for Unwind {
|
|||
fn add_entry(cfg: &mut CFG<'tcx>, from: BasicBlock, to: BasicBlock) {
|
||||
let term = &mut cfg.block_data_mut(from).terminator_mut();
|
||||
match &mut term.kind {
|
||||
TerminatorKind::Drop { unwind, .. }
|
||||
| TerminatorKind::DropAndReplace { unwind, .. }
|
||||
TerminatorKind::Drop { unwind, .. } => {
|
||||
if let Some(unwind) = *unwind {
|
||||
let source_info = term.source_info;
|
||||
cfg.terminate(unwind, source_info, TerminatorKind::Goto { target: to });
|
||||
} else {
|
||||
*unwind = Some(to);
|
||||
}
|
||||
}
|
||||
TerminatorKind::DropAndReplace { unwind, .. }
|
||||
| TerminatorKind::FalseUnwind { unwind, .. }
|
||||
| TerminatorKind::Call { cleanup: unwind, .. }
|
||||
| TerminatorKind::Assert { cleanup: unwind, .. }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue