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
|
@ -1467,6 +1467,32 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
|
||||
/// Reports StorageDeadOrDrop of `place` conflicts with `borrow`.
|
||||
///
|
||||
/// Depending on the origin of the StorageDeadOrDrop, this may be
|
||||
/// reported as either a drop or an illegal mutation of a borrowed value.
|
||||
/// The latter is preferred when the this is a drop triggered by a
|
||||
/// reassignment, as it's more user friendly to report a problem with the
|
||||
/// explicit assignment than the implicit drop.
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
pub(crate) fn report_storage_dead_or_drop_of_borrowed(
|
||||
&mut self,
|
||||
location: Location,
|
||||
place_span: (Place<'tcx>, Span),
|
||||
borrow: &BorrowData<'tcx>,
|
||||
) {
|
||||
// It's sufficient to check the last desugaring as Replace is the last
|
||||
// one to be applied.
|
||||
if let Some(DesugaringKind::Replace) = place_span.1.desugaring_kind() {
|
||||
self.report_illegal_mutation_of_borrowed(location, place_span, borrow)
|
||||
} else {
|
||||
self.report_borrowed_value_does_not_live_long_enough(
|
||||
location,
|
||||
borrow,
|
||||
place_span,
|
||||
Some(WriteKind::StorageDeadOrDrop),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// This means that some data referenced by `borrow` needs to live
|
||||
/// past the point where the StorageDeadOrDrop of `place` occurs.
|
||||
/// This is usually interpreted as meaning that `place` has too
|
||||
|
|
|
@ -925,7 +925,20 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
return OtherUse(use_span);
|
||||
}
|
||||
|
||||
for stmt in &self.body[location.block].statements[location.statement_index + 1..] {
|
||||
// drop and replace might have moved the assignment to the next block
|
||||
let maybe_additional_statement =
|
||||
if let TerminatorKind::Drop { target: drop_target, .. } =
|
||||
self.body[location.block].terminator().kind
|
||||
{
|
||||
self.body[drop_target].statements.first()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let statements =
|
||||
self.body[location.block].statements[location.statement_index + 1..].iter();
|
||||
|
||||
for stmt in statements.chain(maybe_additional_statement) {
|
||||
if let StatementKind::Assign(box (_, Rvalue::Aggregate(kind, places))) = &stmt.kind {
|
||||
let (&def_id, is_generator) = match kind {
|
||||
box AggregateKind::Closure(def_id, _) => (def_id, false),
|
||||
|
|
|
@ -828,7 +828,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
let Some(hir::Node::Item(item)) = node else { return; };
|
||||
let hir::ItemKind::Fn(.., body_id) = item.kind else { return; };
|
||||
let body = self.infcx.tcx.hir().body(body_id);
|
||||
let mut v = V { assign_span: span, err, ty, suggested: false };
|
||||
let mut assign_span = span;
|
||||
// Drop desugaring is done at MIR build so it's not in the HIR
|
||||
if let Some(DesugaringKind::Replace) = span.desugaring_kind() {
|
||||
assign_span.remove_mark();
|
||||
}
|
||||
|
||||
let mut v = V { assign_span, err, ty, suggested: false };
|
||||
v.visit_body(body);
|
||||
if !v.suggested {
|
||||
err.help(&format!(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue