diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 9e0aa57b2553f..6b5075aa6f414 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -2200,10 +2200,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ProjectionElem::Deref => match kind { StorageDeadOrDrop::LocalStorageDead | StorageDeadOrDrop::BoxedStorageDead => { - assert!( - place_ty.ty.is_box(), - "Drop of value behind a reference or raw pointer" - ); + // assert!( + // place_ty.ty.is_box(), + // "Drop of value behind a reference or raw pointer" + // ); StorageDeadOrDrop::BoxedStorageDead } StorageDeadOrDrop::Destructor(_) => kind, diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 7f26af67c71b2..ba0325ce96f34 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -937,7 +937,22 @@ 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 Some(Terminator { + kind: TerminatorKind::DropIfInit { target: drop_target, is_replace: true, .. }, + .. + }) = self.body[location.block].terminator + { + self.body[drop_target].statements.iter().take(1) + } else { + [].iter().take(0) + }; + + let statements = self.body[location.block].statements[location.statement_index + 1..] + .iter() + .chain(maybe_additional_statement); + + for stmt in statements { if let StatementKind::Assign(box (_, Rvalue::Aggregate(ref kind, ref places))) = stmt.kind { diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs index f5317a143aed7..ebdf860e05263 100644 --- a/compiler/rustc_borrowck/src/invalidation.rs +++ b/compiler/rustc_borrowck/src/invalidation.rs @@ -10,8 +10,8 @@ use rustc_middle::ty::TyCtxt; use crate::{ borrow_set::BorrowSet, facts::AllFacts, location::LocationTable, path_utils::*, AccessDepth, - Activation, ArtificialField, BorrowIndex, Deep, LocalMutationIsAllowed, Read, ReadKind, - ReadOrWrite, Reservation, Shallow, Write, WriteKind, + Activation, ArtificialField, BorrowIndex, Deep, FxHashSet, LocalMutationIsAllowed, Read, + ReadKind, ReadOrWrite, Reservation, Shallow, Write, WriteKind, }; pub(super) fn generate_invalidates<'tcx>( @@ -36,6 +36,7 @@ pub(super) fn generate_invalidates<'tcx>( location_table, body: &body, dominators, + to_skip: Default::default(), }; ig.visit_body(body); } @@ -48,6 +49,7 @@ struct InvalidationGenerator<'cx, 'tcx> { body: &'cx Body<'tcx>, dominators: Dominators, borrow_set: &'cx BorrowSet<'tcx>, + to_skip: FxHashSet, } /// Visits the whole MIR and generates `invalidates()` facts. @@ -59,8 +61,9 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { match &statement.kind { StatementKind::Assign(box (lhs, rhs)) => { self.consume_rvalue(location, rhs); - - self.mutate_place(location, *lhs, Shallow(None)); + if !self.to_skip.contains(&location) { + self.mutate_place(location, *lhs, Shallow(None)); + } } StatementKind::FakeRead(box (_, _)) => { // Only relevant for initialized/liveness/safety checks. @@ -109,22 +112,37 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { TerminatorKind::SwitchInt { ref discr, switch_ty: _, targets: _ } => { self.consume_operand(location, discr); } - TerminatorKind::Drop { place: drop_place, target: _, unwind: _ } => { - self.access_place( - location, - *drop_place, - (AccessDepth::Drop, Write(WriteKind::StorageDeadOrDrop)), - LocalMutationIsAllowed::Yes, - ); - } - TerminatorKind::DropAndReplace { - place: drop_place, - value: ref new_value, - target: _, - unwind: _, - } => { - self.mutate_place(location, *drop_place, Deep); - self.consume_operand(location, new_value); + TerminatorKind::DropIfInit { place: drop_place, target, unwind, is_replace } + | TerminatorKind::DropIf { place: drop_place, target, unwind, is_replace, test: _ } => { + let next_statement = if *is_replace { + self.body + .basic_blocks + .get(*target) + .expect("MIR should be complete at this point") + .statements + .first() + } else { + None + }; + + match next_statement { + Some(Statement { kind: StatementKind::Assign(_), source_info: _ }) => { + // this is a drop from a replace operation, for better diagnostic report + // here possible conflicts and mute the assign statement errors + self.to_skip.insert(Location { block: *target, statement_index: 0 }); + self.to_skip + .insert(Location { block: unwind.unwrap(), statement_index: 0 }); + self.mutate_place(location, *drop_place, AccessDepth::Deep); + } + _ => { + self.access_place( + location, + *drop_place, + (AccessDepth::Drop, Write(WriteKind::StorageDeadOrDrop)), + LocalMutationIsAllowed::Yes, + ); + } + } } TerminatorKind::Call { ref func, diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 4a4887f19702f..89ea5c7386927 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -343,6 +343,7 @@ fn do_mir_borrowck<'tcx>( next_region_name: RefCell::new(1), polonius_output: None, errors, + to_skip: Default::default(), }; promoted_mbcx.report_move_errors(move_errors); errors = promoted_mbcx.errors; @@ -374,6 +375,7 @@ fn do_mir_borrowck<'tcx>( next_region_name: RefCell::new(1), polonius_output, errors, + to_skip: Default::default(), }; // Compute and report region errors, if any. @@ -556,6 +558,8 @@ struct MirBorrowckCtxt<'cx, 'tcx> { polonius_output: Option>, errors: error::BorrowckErrors<'tcx>, + + to_skip: FxHashSet, } // Check that: @@ -580,8 +584,9 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx match &stmt.kind { StatementKind::Assign(box (lhs, ref rhs)) => { self.consume_rvalue(location, (rhs, span), flow_state); - - self.mutate_place(location, (*lhs, span), Shallow(None), flow_state); + if !self.to_skip.contains(&location) { + self.mutate_place(location, (*lhs, span), Shallow(None), flow_state); + } } StatementKind::FakeRead(box (_, ref place)) => { // Read for match doesn't access any memory and is used to @@ -647,29 +652,44 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx TerminatorKind::SwitchInt { ref discr, switch_ty: _, targets: _ } => { self.consume_operand(loc, (discr, span), flow_state); } - TerminatorKind::Drop { place, target: _, unwind: _ } => { + TerminatorKind::DropIfInit { place, target, unwind, is_replace } + | TerminatorKind::DropIf { place, target, unwind, is_replace, test: _ } => { debug!( "visit_terminator_drop \ loc: {:?} term: {:?} place: {:?} span: {:?}", loc, term, place, span ); - self.access_place( - loc, - (place, span), - (AccessDepth::Drop, Write(WriteKind::StorageDeadOrDrop)), - LocalMutationIsAllowed::Yes, - flow_state, - ); - } - TerminatorKind::DropAndReplace { - place: drop_place, - value: ref new_value, - target: _, - unwind: _, - } => { - self.mutate_place(loc, (drop_place, span), Deep, flow_state); - self.consume_operand(loc, (new_value, span), flow_state); + let next_statement = if is_replace { + self.body() + .basic_blocks + .get(target) + .expect("MIR should be complete at this point") + .statements + .first() + } else { + None + }; + + match next_statement { + Some(Statement { kind: StatementKind::Assign(_), source_info: _ }) => { + // this is a drop from a replace operation, for better diagnostic report + // here possible conflicts and mute the assign statement errors + self.to_skip.insert(Location { block: target, statement_index: 0 }); + self.to_skip + .insert(Location { block: unwind.unwrap(), statement_index: 0 }); + self.mutate_place(loc, (place, span), AccessDepth::Deep, flow_state); + } + _ => { + self.access_place( + loc, + (place, span), + (AccessDepth::Drop, Write(WriteKind::StorageDeadOrDrop)), + LocalMutationIsAllowed::Yes, + flow_state, + ); + } + } } TerminatorKind::Call { ref func, @@ -784,8 +804,8 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx TerminatorKind::Abort | TerminatorKind::Assert { .. } | TerminatorKind::Call { .. } - | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } + | TerminatorKind::DropIfInit { .. } + | TerminatorKind::DropIf { .. } | TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ } | TerminatorKind::FalseUnwind { real_target: _, unwind: _ } | TerminatorKind::Goto { .. } @@ -1627,7 +1647,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { (prefix, place_span.0, place_span.1), mpi, ); - } // Only query longest prefix with a MovePath, not further + } + // Only query longest prefix with a MovePath, not further // ancestors; dataflow recurs on children when parents // move (to support partial (re)inits). // diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 6ccc29b09c0a5..c89c56732f57d 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1342,31 +1342,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { | TerminatorKind::Return | TerminatorKind::GeneratorDrop | TerminatorKind::Unreachable - | TerminatorKind::Drop { .. } + | TerminatorKind::DropIfInit { .. } + | TerminatorKind::DropIf { .. } | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } | TerminatorKind::InlineAsm { .. } => { // no checks needed for these } - - TerminatorKind::DropAndReplace { ref place, ref value, target: _, unwind: _ } => { - let place_ty = place.ty(body, tcx).ty; - let rv_ty = value.ty(body, tcx); - - let locations = term_location.to_locations(); - if let Err(terr) = - self.sub_types(rv_ty, place_ty, locations, ConstraintCategory::Assignment) - { - span_mirbug!( - self, - term, - "bad DropAndReplace ({:?} = {:?}): {:?}", - place_ty, - rv_ty, - terr - ); - } - } TerminatorKind::SwitchInt { ref discr, switch_ty, .. } => { self.check_operand(discr, term_location); @@ -1664,8 +1646,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } TerminatorKind::Unreachable => {} - TerminatorKind::Drop { target, unwind, .. } - | TerminatorKind::DropAndReplace { target, unwind, .. } + TerminatorKind::DropIfInit { target, unwind, .. } + | TerminatorKind::DropIf { target, unwind, .. } | TerminatorKind::Assert { target, cleanup: unwind, .. } => { self.assert_iscleanup(body, block_data, target, is_cleanup); if let Some(unwind) = unwind { diff --git a/compiler/rustc_borrowck/src/used_muts.rs b/compiler/rustc_borrowck/src/used_muts.rs index e297b1230ea0c..f4eeca78cc6b1 100644 --- a/compiler/rustc_borrowck/src/used_muts.rs +++ b/compiler/rustc_borrowck/src/used_muts.rs @@ -71,9 +71,9 @@ impl<'visit, 'cx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'cx, 'tc TerminatorKind::Call { destination, .. } => { self.remove_never_initialized_mut_locals(*destination); } - TerminatorKind::DropAndReplace { place, .. } => { - self.remove_never_initialized_mut_locals(*place); - } + // TerminatorKind::DropIfInit { place, .. } => { + // self.remove_never_initialized_mut_locals(*place); + // } _ => {} } diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 1db44502742e9..f2b75c39ac958 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -474,11 +474,11 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { TerminatorKind::Yield { .. } | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::GeneratorDrop => { bug!("shouldn't exist at codegen {:?}", bb_data.terminator()); } - TerminatorKind::Drop { place, target, unwind: _ } => { + TerminatorKind::DropIfInit { place, target, unwind: _, is_replace: _ } + | TerminatorKind::DropIf { place, target, unwind: _, is_replace: _, test: _ } => { let drop_place = codegen_place(fx, *place); crate::abi::codegen_drop(fx, source_info, drop_place); diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index c0c6c76473ba8..da348318a56b4 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -539,10 +539,10 @@ pub(crate) fn mir_operand_get_const_val<'tcx>( | TerminatorKind::Abort | TerminatorKind::Return | TerminatorKind::Unreachable - | TerminatorKind::Drop { .. } + | TerminatorKind::DropIfInit { .. } + | TerminatorKind::DropIf { .. } | TerminatorKind::Assert { .. } => {} - TerminatorKind::DropAndReplace { .. } - | TerminatorKind::Yield { .. } + TerminatorKind::Yield { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } => unreachable!(), diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index c7617d2e464fa..a7c25f651a616 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -281,8 +281,8 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec { + | TerminatorKind::DropIf { unwind, .. } + | TerminatorKind::DropIfInit { unwind, .. } => { if let Some(unwind) = unwind { debug!( "cleanup_kinds: {:?}/{:?} registering {:?} as funclet", diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 0802067cde65d..fed25f6b7aac3 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -413,7 +413,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { location: mir::Place<'tcx>, target: mir::BasicBlock, unwind: Option, + test: &mir::Operand<'tcx>, ) { + let drop_flag = self.codegen_operand(&mut bx, test); + let drop_block = bx.append_sibling_block("drop"); + let lltarget = helper.llbb_with_cleanup(self, target); + bx.cond_br(drop_flag.immediate(), drop_block, lltarget); + + bx.switch_to_block(drop_block); + self.set_debug_loc(&mut bx, helper.terminator.source_info); + let ty = location.ty(self.mir, bx.tcx()).ty; let ty = self.monomorphize(ty); let drop_fn = Instance::resolve_drop_in_place(bx.tcx(), ty); @@ -1207,8 +1216,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.unreachable(); } - mir::TerminatorKind::Drop { place, target, unwind } => { - self.codegen_drop_terminator(helper, bx, place, target, unwind); + mir::TerminatorKind::DropIf { place, target, unwind, is_replace: _, ref test } => { + self.codegen_drop_terminator(helper, bx, place, target, unwind, test); } mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, cleanup } => { @@ -1217,10 +1226,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ); } - mir::TerminatorKind::DropAndReplace { .. } => { - bug!("undesugared DropAndReplace in codegen: {:?}", terminator); - } - mir::TerminatorKind::Call { ref func, ref args, @@ -1245,6 +1250,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::TerminatorKind::GeneratorDrop | mir::TerminatorKind::Yield { .. } => { bug!("generator ops in codegen") } + mir::TerminatorKind::DropIfInit { .. } => { + bug!( + "drop elaboration should have removed this terminator in codegen {:?}", + self.mir + ) + } mir::TerminatorKind::FalseEdge { .. } | mir::TerminatorKind::FalseUnwind { .. } => { bug!("borrowck false edges in codegen") } diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 57e40e168fa48..e255504b3e3b9 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -119,10 +119,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } - Drop { place, target, unwind } => { + DropIf { place, target, unwind, .. } => { let place = self.eval_place(place)?; let ty = place.layout.ty; - trace!("TerminatorKind::drop: {:?}, type {}", place, ty); + trace!("TerminatorKind::DropIf: {:?}, type {}", place, ty); let instance = Instance::resolve_drop_in_place(*self.tcx, ty); self.drop_in_place(&place, instance, target, unwind)?; @@ -156,7 +156,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Unreachable => throw_ub!(Unreachable), // These should never occur for MIR we actually run. - DropAndReplace { .. } + DropIfInit { .. } | FalseEdge { .. } | FalseUnwind { .. } | Yield { .. } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 5a8b3e30b9fc0..2205990f9e135 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -965,8 +965,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // Forbid all `Drop` terminators unless the place being dropped is a local with no // projections that cannot be `NeedsNonConstDrop`. - TerminatorKind::Drop { place: dropped_place, .. } - | TerminatorKind::DropAndReplace { place: dropped_place, .. } => { + TerminatorKind::DropIfInit { place: dropped_place, .. } + | TerminatorKind::DropIf { place: dropped_place, .. } => { // If we are checking live drops after drop-elaboration, don't emit duplicate // errors here. if super::post_drop_elaboration::checking_enabled(self.ccx) { diff --git a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs index d4570c5988914..c75673bcb242e 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs @@ -80,8 +80,9 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> { trace!("visit_terminator: terminator={:?} location={:?}", terminator, location); match &terminator.kind { - mir::TerminatorKind::Drop { place: dropped_place, .. } - | mir::TerminatorKind::DropAndReplace { place: dropped_place, .. } => { + // FIXME + mir::TerminatorKind::DropIfInit { place: dropped_place, .. } + | mir::TerminatorKind::DropIf { place: dropped_place, .. } => { let dropped_ty = dropped_place.ty(self.body, self.tcx).ty; if !NeedsNonConstDrop::in_any_value_of_ty(self.ccx, dropped_ty) { // Instead of throwing a bug, we just return here. This is because we have to diff --git a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs index 805e6096b35c8..609d6381ba76f 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs @@ -222,17 +222,18 @@ where // The effect of assignment to the return place in `TerminatorKind::Call` is not applied // here; that occurs in `apply_call_return_effect`. - if let mir::TerminatorKind::DropAndReplace { value, place, .. } = &terminator.kind { - let qualif = qualifs::in_operand::( - self.ccx, - &mut |l| self.state.qualif.contains(l), - value, - ); - - if !place.is_indirect() { - self.assign_qualif_direct(place, qualif); - } - } + // FIXME ?? + // if let mir::TerminatorKind::DropIfInitAndReplace { value, place, .. } = &terminator.kind { + // let qualif = qualifs::in_operand::( + // self.ccx, + // &mut |l| self.state.qualif.contains(l), + // value, + // ); + + // if !place.is_indirect() { + // self.assign_qualif_direct(place, qualif); + // } + // } // We ignore borrow on drop because custom drop impls are not allowed in consts. // FIXME: Reconsider if accounting for borrows in drops is necessary for const drop. diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index f48bcd9080966..a1938b915dfaa 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -1006,7 +1006,7 @@ pub fn promote_candidates<'tcx>( _ => true, }); let terminator = block.terminator_mut(); - if let TerminatorKind::Drop { place, target, .. } = &terminator.kind { + if let TerminatorKind::DropIfInit { place, target, .. } = &terminator.kind { if let Some(index) = place.as_local() { if promoted(index) { terminator.kind = TerminatorKind::Goto { target: *target }; diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 81b82a21fa1a7..98323fbc6a6e0 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -786,24 +786,26 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ); } } - TerminatorKind::Drop { target, unwind, .. } => { - self.check_edge(location, *target, EdgeKind::Normal); - if let Some(unwind) = unwind { - self.check_edge(location, *unwind, EdgeKind::Unwind); - } - } - TerminatorKind::DropAndReplace { target, unwind, .. } => { - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { - self.fail( - location, - "`DropAndReplace` should have been removed during drop elaboration", - ); - } + TerminatorKind::DropIfInit { target, unwind, .. } + | TerminatorKind::DropIf { target, unwind, .. } => { self.check_edge(location, *target, EdgeKind::Normal); if let Some(unwind) = unwind { self.check_edge(location, *unwind, EdgeKind::Unwind); } } + // FIXME ?? + // TerminatorKind::DropIfInitAndReplace { target, unwind, .. } => { + // if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { + // self.fail( + // location, + // "`DropAndReplace` should have been removed during drop elaboration", + // ); + // } + // self.check_edge(location, *target, EdgeKind::Normal); + // if let Some(unwind) = unwind { + // self.check_edge(location, *unwind, EdgeKind::Unwind); + // } + // } TerminatorKind::Call { func, args, destination, target, cleanup, .. } => { let func_ty = func.ty(&self.body.local_decls, self.tcx); match func_ty.kind() { diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs index 4e06d91012c0d..105e382a597d8 100644 --- a/compiler/rustc_middle/src/mir/spanview.rs +++ b/compiler/rustc_middle/src/mir/spanview.rs @@ -263,8 +263,8 @@ pub fn terminator_kind_name(term: &Terminator<'_>) -> &'static str { Abort => "Abort", Return => "Return", Unreachable => "Unreachable", - Drop { .. } => "Drop", - DropAndReplace { .. } => "DropAndReplace", + DropIfInit { .. } => "DropIfInit", + DropIf { .. } => "DropIf", Call { .. } => "Call", Assert { .. } => "Assert", Yield { .. } => "Yield", diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index fed943169dfb5..bee1fbdd1eb79 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -112,7 +112,6 @@ pub enum AnalysisPhase { pub enum RuntimePhase { /// In addition to the semantic changes, beginning with this phase, the following variants are /// disallowed: - /// * [`TerminatorKind::DropAndReplace`] /// * [`TerminatorKind::Yield`] /// * [`TerminatorKind::GeneratorDrop`] /// * [`Rvalue::Aggregate`] for any `AggregateKind` except `Array` @@ -546,61 +545,21 @@ pub enum TerminatorKind<'tcx> { /// Executing this terminator is UB. Unreachable, - /// The behavior of this statement differs significantly before and after drop elaboration. - /// After drop elaboration, `Drop` executes the drop glue for the specified place, after which - /// it continues execution/unwinds at the given basic blocks. It is possible that executing drop - /// glue is special - this would be part of Rust's memory model. (**FIXME**: due we have an - /// issue tracking if drop glue has any interesting semantics in addition to those of a function - /// call?) - /// - /// `Drop` before drop elaboration is a *conditional* execution of the drop glue. Specifically, the - /// `Drop` will be executed if... - /// - /// **Needs clarification**: End of that sentence. This in effect should document the exact - /// behavior of drop elaboration. The following sounds vaguely right, but I'm not quite sure: - /// - /// > The drop glue is executed if, among all statements executed within this `Body`, an assignment to - /// > the place or one of its "parents" occurred more recently than a move out of it. This does not - /// > consider indirect assignments. - Drop { place: Place<'tcx>, target: BasicBlock, unwind: Option }, - - /// Drops the place and assigns a new value to it. - /// - /// This first performs the exact same operation as the pre drop-elaboration `Drop` terminator; - /// it then additionally assigns the `value` to the `place` as if by an assignment statement. - /// This assignment occurs both in the unwind and the regular code paths. The semantics are best - /// explained by the elaboration: - /// - /// ```ignore (MIR) - /// BB0 { - /// DropAndReplace(P <- V, goto BB1, unwind BB2) - /// } - /// ``` - /// - /// becomes - /// - /// ```ignore (MIR) - /// BB0 { - /// Drop(P, goto BB1, unwind BB2) - /// } - /// BB1 { - /// // P is now uninitialized - /// P <- V - /// } - /// BB2 { - /// // P is now uninitialized -- its dtor panicked - /// P <- V - /// } - /// ``` - /// - /// Disallowed after drop elaboration. - DropAndReplace { + /// Drop place if it is (dynamically) initialized. Only constructed at MIR build, eliminated by drop elaboration + DropIfInit { place: Place<'tcx>, - value: Operand<'tcx>, target: BasicBlock, unwind: Option, + is_replace: bool, + }, + // /// Produced by drop elaboration + DropIf { + place: Place<'tcx>, + target: BasicBlock, + unwind: Option, + test: Operand<'tcx>, + is_replace: bool, }, - /// Roughly speaking, evaluates the `func` operand and the arguments, and starts execution of /// the referred to function. The operand types must match the argument types of the function. /// The return place type must match the return type. The type of the `func` operand must be diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 4ea333cff7d9d..20b6d946ee378 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -160,8 +160,8 @@ impl<'tcx> TerminatorKind<'tcx> { | Call { target: None, cleanup: Some(t), .. } | Call { target: Some(t), cleanup: None, .. } | Yield { resume: t, drop: None, .. } - | DropAndReplace { target: t, unwind: None, .. } - | Drop { target: t, unwind: None, .. } + | DropIfInit { target: t, unwind: None, .. } + | DropIf { target: t, unwind: None, .. } | Assert { target: t, cleanup: None, .. } | FalseUnwind { real_target: t, unwind: None } | InlineAsm { destination: Some(t), cleanup: None, .. } @@ -170,8 +170,8 @@ impl<'tcx> TerminatorKind<'tcx> { } Call { target: Some(t), cleanup: Some(ref u), .. } | Yield { resume: t, drop: Some(ref u), .. } - | DropAndReplace { target: t, unwind: Some(ref u), .. } - | Drop { target: t, unwind: Some(ref u), .. } + | DropIfInit { target: t, unwind: Some(ref u), .. } + | DropIf { target: t, unwind: Some(ref u), .. } | Assert { target: t, cleanup: Some(ref u), .. } | FalseUnwind { real_target: t, unwind: Some(ref u) } | InlineAsm { destination: Some(t), cleanup: Some(ref u), .. } => { @@ -200,8 +200,8 @@ impl<'tcx> TerminatorKind<'tcx> { | Call { target: None, cleanup: Some(ref mut t), .. } | Call { target: Some(ref mut t), cleanup: None, .. } | Yield { resume: ref mut t, drop: None, .. } - | DropAndReplace { target: ref mut t, unwind: None, .. } - | Drop { target: ref mut t, unwind: None, .. } + | DropIfInit { target: ref mut t, unwind: None, .. } + | DropIf { target: ref mut t, unwind: None, .. } | Assert { target: ref mut t, cleanup: None, .. } | FalseUnwind { real_target: ref mut t, unwind: None } | InlineAsm { destination: Some(ref mut t), cleanup: None, .. } @@ -210,8 +210,8 @@ impl<'tcx> TerminatorKind<'tcx> { } Call { target: Some(ref mut t), cleanup: Some(ref mut u), .. } | Yield { resume: ref mut t, drop: Some(ref mut u), .. } - | DropAndReplace { target: ref mut t, unwind: Some(ref mut u), .. } - | Drop { target: ref mut t, unwind: Some(ref mut u), .. } + | DropIfInit { target: ref mut t, unwind: Some(ref mut u), .. } + | DropIf { target: ref mut t, unwind: Some(ref mut u), .. } | Assert { target: ref mut t, cleanup: Some(ref mut u), .. } | FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } | InlineAsm { destination: Some(ref mut t), cleanup: Some(ref mut u), .. } => { @@ -237,8 +237,8 @@ impl<'tcx> TerminatorKind<'tcx> { | TerminatorKind::FalseEdge { .. } => None, TerminatorKind::Call { cleanup: ref unwind, .. } | TerminatorKind::Assert { cleanup: ref unwind, .. } - | TerminatorKind::DropAndReplace { ref unwind, .. } - | TerminatorKind::Drop { ref unwind, .. } + | TerminatorKind::DropIfInit { ref unwind, .. } + | TerminatorKind::DropIf { ref unwind, .. } | TerminatorKind::FalseUnwind { ref unwind, .. } | TerminatorKind::InlineAsm { cleanup: ref unwind, .. } => Some(unwind), } @@ -257,8 +257,8 @@ impl<'tcx> TerminatorKind<'tcx> { | TerminatorKind::FalseEdge { .. } => None, TerminatorKind::Call { cleanup: ref mut unwind, .. } | TerminatorKind::Assert { cleanup: ref mut unwind, .. } - | TerminatorKind::DropAndReplace { ref mut unwind, .. } - | TerminatorKind::Drop { ref mut unwind, .. } + | TerminatorKind::DropIfInit { ref mut unwind, .. } + | TerminatorKind::DropIf { ref mut unwind, .. } | TerminatorKind::FalseUnwind { ref mut unwind, .. } | TerminatorKind::InlineAsm { cleanup: ref mut unwind, .. } => Some(unwind), } @@ -322,10 +322,8 @@ impl<'tcx> TerminatorKind<'tcx> { Abort => write!(fmt, "abort"), Yield { value, resume_arg, .. } => write!(fmt, "{:?} = yield({:?})", resume_arg, value), Unreachable => write!(fmt, "unreachable"), - Drop { place, .. } => write!(fmt, "drop({:?})", place), - DropAndReplace { place, value, .. } => { - write!(fmt, "replace({:?} <- {:?})", place, value) - } + DropIfInit { place, .. } => write!(fmt, "drop_if_init({:?})", place), + DropIf { place, test, .. } => write!(fmt, "drop_if({:?}, {:?})", place, test), Call { func, args, destination, .. } => { write!(fmt, "{:?} = ", destination)?; write!(fmt, "{:?}(", func)?; @@ -426,12 +424,10 @@ impl<'tcx> TerminatorKind<'tcx> { Call { target: None, cleanup: None, .. } => vec![], Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()], Yield { drop: None, .. } => vec!["resume".into()], - DropAndReplace { unwind: None, .. } | Drop { unwind: None, .. } => { - vec!["return".into()] - } - DropAndReplace { unwind: Some(_), .. } | Drop { unwind: Some(_), .. } => { - vec!["return".into(), "unwind".into()] - } + DropIfInit { unwind: None, .. } => vec!["return".into()], + DropIfInit { unwind: Some(_), .. } => vec!["return".into(), "unwind".into()], + DropIf { unwind: None, .. } => vec!["return".into()], + DropIf { unwind: Some(_), .. } => vec!["return".into(), "unwind".into()], Assert { cleanup: None, .. } => vec!["".into()], Assert { .. } => vec!["success".into(), "unwind".into()], FalseEdge { .. } => vec!["real".into(), "imaginary".into()], diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index b21f50ae5eaa9..b12c6d6cda1ed 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -484,10 +484,11 @@ macro_rules! make_mir_visitor { self.visit_ty($(& $mutability)? *switch_ty, TyContext::Location(location)); } - TerminatorKind::Drop { + TerminatorKind::DropIfInit { place, target: _, unwind: _, + is_replace: _, } => { self.visit_place( place, @@ -496,18 +497,22 @@ macro_rules! make_mir_visitor { ); } - TerminatorKind::DropAndReplace { + TerminatorKind::DropIf { place, - value, target: _, unwind: _, + test, + is_replace: _, } => { self.visit_place( place, PlaceContext::MutatingUse(MutatingUseContext::Drop), location ); - self.visit_operand(value, location); + self.visit_operand( + test, + location + ); } TerminatorKind::Call { diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 5c82fb1ddc0d5..bfbb23d8748be 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -625,7 +625,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.cfg.terminate( block, outer_source_info, - TerminatorKind::Drop { place: to_drop, target: success, unwind: None }, + TerminatorKind::DropIfInit { + place: to_drop, + target: success, + unwind: None, + is_replace: false, + }, ); this.diverge_from(block); block = success; diff --git a/compiler/rustc_mir_build/src/build/expr/stmt.rs b/compiler/rustc_mir_build/src/build/expr/stmt.rs index 00dbcaeb0c96f..93848c27617e9 100644 --- a/compiler/rustc_mir_build/src/build/expr/stmt.rs +++ b/compiler/rustc_mir_build/src/build/expr/stmt.rs @@ -41,16 +41,14 @@ 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 lhs = unpack!(block = this.as_place(block, lhs)); - unpack!(block = this.build_drop_and_replace(block, lhs_span, lhs, rhs)); - } else { - let rhs = unpack!(block = this.as_local_rvalue(block, rhs)); - let lhs = unpack!(block = this.as_place(block, lhs)); - this.cfg.push_assign(block, source_info, lhs, rhs); - } + let needs_drop = lhs.ty.needs_drop(this.tcx, this.param_env); + let rhs = unpack!(block = this.as_local_rvalue(block, rhs)); + let lhs = unpack!(block = this.as_place(block, lhs)); + if needs_drop { + unpack!(block = this.build_drop_and_replace(block, lhs_span, lhs, rhs.clone())); + } + this.cfg.push_assign(block, source_info, lhs, rhs); this.block_context.pop(); block.unit() } diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index 3cebd5ebed660..882c41651c9e9 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -365,11 +365,12 @@ impl DropTree { let Some(block) = blocks[drop_idx] else { continue }; match drop_data.0.kind { DropKind::Value => { - let terminator = TerminatorKind::Drop { + let terminator = TerminatorKind::DropIfInit { target: blocks[drop_data.1].unwrap(), // The caller will handle this if needed. unwind: None, place: drop_data.0.local.into(), + is_replace: false, }; cfg.terminate(block, drop_data.0.source_info, terminator); } @@ -1047,8 +1048,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.cfg.block_data(start).terminator().kind, TerminatorKind::Assert { .. } | TerminatorKind::Call { .. } - | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } + | TerminatorKind::DropIfInit { .. } | TerminatorKind::FalseUnwind { .. } | TerminatorKind::InlineAsm { .. } ), @@ -1094,21 +1094,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. + /// Should only be used for DropAndReplace. + /// Note that this does *not* insert the assignement in the MIR, + /// that should be added in the newly returned block by the caller. pub(crate) fn build_drop_and_replace( &mut self, block: BasicBlock, span: Span, place: Place<'tcx>, - value: Operand<'tcx>, + value: Rvalue<'tcx>, ) -> BlockAnd<()> { let source_info = self.source_info(span); let next_target = self.cfg.start_new_block(); + let assign = self.cfg.start_new_cleanup_block(); + self.cfg.push_assign(assign, source_info, place, value.clone()); + self.cfg.terminate(assign, source_info, TerminatorKind::Goto { target: block }); + self.cfg.terminate( block, source_info, - TerminatorKind::DropAndReplace { place, value, target: next_target, unwind: None }, + TerminatorKind::DropIfInit { + place, + target: next_target, + unwind: Some(assign), + is_replace: true, + }, ); + self.diverge_from(block); next_target.unit() @@ -1210,7 +1224,12 @@ fn build_scope_drops<'tcx>( cfg.terminate( block, source_info, - TerminatorKind::Drop { place: local.into(), target: next, unwind: None }, + TerminatorKind::DropIfInit { + place: local.into(), + target: next, + unwind: None, + is_replace: false, + }, ); block = next; } @@ -1389,14 +1408,18 @@ 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::FalseUnwind { unwind, .. } + TerminatorKind::DropIfInit { unwind, .. } => { + if let Some(unwind) = unwind.clone() { + cfg.block_data_mut(unwind).terminator_mut().kind = + TerminatorKind::Goto { target: to }; + } else { + *unwind = Some(to); + } + } + TerminatorKind::FalseUnwind { unwind, .. } | TerminatorKind::Call { cleanup: unwind, .. } | TerminatorKind::Assert { cleanup: unwind, .. } - | TerminatorKind::InlineAsm { cleanup: unwind, .. } => { - *unwind = Some(to); - } + | TerminatorKind::InlineAsm { cleanup: unwind, .. } => *unwind = Some(to), TerminatorKind::Goto { .. } | TerminatorKind::SwitchInt { .. } | TerminatorKind::Resume @@ -1408,6 +1431,12 @@ impl<'tcx> DropTreeBuilder<'tcx> for Unwind { | TerminatorKind::FalseEdge { .. } => { span_bug!(term.source_info.span, "cannot unwind from {:?}", term.kind) } + TerminatorKind::DropIf { .. } => { + span_bug!( + term.source_info.span, + "drop if should only be present after drop elaboration" + ) + } } } } diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs index b21f30efce807..98a620a6e91e6 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -134,8 +134,8 @@ impl<'mir, 'tcx> TriColorVisitor> for Search<'mir, 'tcx> { // These do not. TerminatorKind::Assert { .. } | TerminatorKind::Call { .. } - | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } + | TerminatorKind::DropIfInit { .. } + | TerminatorKind::DropIf { .. } | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } | TerminatorKind::Goto { .. } diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 14d265a402ef8..7fb98da82e3b8 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -164,6 +164,7 @@ where path: D::Path, succ: BasicBlock, unwind: Unwind, + is_replace: bool, } /// "Elaborates" a drop of `place`/`path` and patches `bb`'s terminator to execute it. @@ -182,11 +183,12 @@ pub fn elaborate_drop<'b, 'tcx, D>( succ: BasicBlock, unwind: Unwind, bb: BasicBlock, + is_replace: bool, ) where D: DropElaborator<'b, 'tcx>, 'tcx: 'b, { - DropCtxt { elaborator, source_info, place, path, succ, unwind }.elaborate_drop(bb) + DropCtxt { elaborator, source_info, place, path, succ, unwind, is_replace }.elaborate_drop(bb) } impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> @@ -223,7 +225,7 @@ where pub fn elaborate_drop(&mut self, bb: BasicBlock) { debug!("elaborate_drop({:?}, {:?})", bb, self); let style = self.elaborator.drop_style(self.path, DropFlagMode::Deep); - debug!("elaborate_drop({:?}, {:?}): live - {:?}", bb, self, style); + match style { DropStyle::Dead => { self.elaborator @@ -231,12 +233,15 @@ where .patch_terminator(bb, TerminatorKind::Goto { target: self.succ }); } DropStyle::Static => { + let test = self.constant_bool(true); self.elaborator.patch().patch_terminator( bb, - TerminatorKind::Drop { + TerminatorKind::DropIf { place: self.place, target: self.succ, unwind: self.unwind.into_option(), + test, + is_replace: self.is_replace, }, ); } @@ -298,6 +303,7 @@ where place, succ, unwind, + is_replace: self.is_replace, } .elaborated_drop_block() } else { @@ -312,6 +318,7 @@ where // Using `self.path` here to condition the drop on // our own drop flag. path: self.path, + is_replace: self.is_replace, } .complete_drop(succ, unwind) } @@ -552,9 +559,14 @@ where unwind_blocks.as_mut().unwrap().push(self.goto_block(unwind, Unwind::InCleanup)); } } else { - normal_blocks.push(self.drop_block(succ, unwind)); + let flag = self.constant_bool(true); + normal_blocks.push(self.drop_block(succ, unwind, flag.clone())); if let Unwind::To(unwind) = unwind { - unwind_blocks.as_mut().unwrap().push(self.drop_block(unwind, Unwind::InCleanup)); + unwind_blocks.as_mut().unwrap().push(self.drop_block( + unwind, + Unwind::InCleanup, + flag, + )); } } @@ -606,6 +618,7 @@ where is_cleanup: unwind.is_cleanup(), }; let switch_block = self.elaborator.patch().new_block(switch_block); + // FIXME: this is not very borrock friendly self.drop_flag_test_block(switch_block, succ, unwind) } @@ -721,12 +734,15 @@ where }; let loop_block = self.elaborator.patch().new_block(loop_block); + let test = self.constant_bool(true); self.elaborator.patch().patch_terminator( drop_block, - TerminatorKind::Drop { + TerminatorKind::DropIf { place: tcx.mk_place_deref(ptr), target: loop_block, unwind: unwind.into_option(), + test, + is_replace: self.is_replace, }, ); @@ -898,11 +914,14 @@ where } fn complete_drop(&mut self, succ: BasicBlock, unwind: Unwind) -> BasicBlock { - debug!("complete_drop(succ={:?}, unwind={:?})", succ, unwind); - - let drop_block = self.drop_block(succ, unwind); - - self.drop_flag_test_block(drop_block, succ, unwind) + let style = self.elaborator.drop_style(self.path, DropFlagMode::Shallow); + let flag = match style { + DropStyle::Dead => self.constant_bool(false), + DropStyle::Static => self.constant_bool(true), + _ => self.elaborator.get_drop_flag(self.path).unwrap(), + }; + debug!("complete_drop(succ={:?}, unwind={:?}) {:?}", succ, unwind, flag); + self.drop_block(succ, unwind, flag) } /// Creates a block that resets the drop flag. If `mode` is deep, all children drop flags will @@ -928,7 +947,8 @@ where fn elaborated_drop_block(&mut self) -> BasicBlock { debug!("elaborated_drop_block({:?})", self); - let blk = self.drop_block(self.succ, self.unwind); + // test will be immediately overridden by elaborate_drop() + let blk = self.drop_block(self.succ, self.unwind, self.constant_bool(true)); self.elaborate_drop(blk); blk } @@ -945,6 +965,8 @@ where unwind: Unwind, ) -> BasicBlock { let block = self.unelaborated_free_block(adt, substs, target, unwind); + // we need to keep the additional block here, freeing the backing memory of a `Box` is not + // handled with a drop terminator self.drop_flag_test_block(block, target, unwind) } @@ -988,9 +1010,19 @@ where free_block } - fn drop_block(&mut self, target: BasicBlock, unwind: Unwind) -> BasicBlock { - let block = - TerminatorKind::Drop { place: self.place, target, unwind: unwind.into_option() }; + fn drop_block( + &mut self, + target: BasicBlock, + unwind: Unwind, + test: Operand<'tcx>, + ) -> BasicBlock { + let block = TerminatorKind::DropIf { + place: self.place, + target, + unwind: unwind.into_option(), + test, + is_replace: self.is_replace, + }; self.new_block(unwind, block) } @@ -1047,6 +1079,14 @@ where })) } + fn constant_bool(&self, val: bool) -> Operand<'tcx> { + Operand::Constant(Box::new(Constant { + span: self.source_info.span, + user_ty: None, + literal: ConstantKind::from_bool(self.tcx(), val), + })) + } + fn assign(&self, lhs: Place<'tcx>, rhs: Rvalue<'tcx>) -> Statement<'tcx> { Statement { source_info: self.source_info, diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 5c77f3ea39533..fa0af37021551 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -281,8 +281,7 @@ impl Direction for Backward { // Ignore dead unwinds. mir::TerminatorKind::Call { cleanup: Some(unwind), .. } | mir::TerminatorKind::Assert { cleanup: Some(unwind), .. } - | mir::TerminatorKind::Drop { unwind: Some(unwind), .. } - | mir::TerminatorKind::DropAndReplace { unwind: Some(unwind), .. } + | mir::TerminatorKind::DropIfInit { unwind: Some(unwind), .. } | mir::TerminatorKind::FalseUnwind { unwind: Some(unwind), .. } | mir::TerminatorKind::InlineAsm { cleanup: Some(unwind), .. } if unwind == bb => @@ -498,8 +497,8 @@ impl Direction for Forward { Goto { target } => propagate(target, exit_state), Assert { target, cleanup: unwind, expected: _, msg: _, cond: _ } - | Drop { target, unwind, place: _ } - | DropAndReplace { target, unwind, value: _, place: _ } + | DropIfInit { target, unwind, .. } + | DropIf { target, unwind, .. } | FalseUnwind { real_target: target, unwind } => { if let Some(unwind) = unwind { if dead_unwinds.map_or(true, |dead| !dead.contains(bb)) { diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index 0f8e86d1d6679..eb33efc8f63f2 100644 --- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -111,8 +111,9 @@ where self.super_terminator(terminator, location); match terminator.kind { - mir::TerminatorKind::Drop { place: dropped_place, .. } - | mir::TerminatorKind::DropAndReplace { place: dropped_place, .. } => { + mir::TerminatorKind::DropIfInit { place: dropped_place, .. } + | mir::TerminatorKind::DropIf { place: dropped_place, .. } => { + // | mir::TerminatorKind::DropIf { place: dropped_place, .. } => { // Drop terminators may call custom drop glue (`Drop::drop`), which takes `&mut // self` as a parameter. In the general case, a drop impl could launder that // reference into the surrounding environment through a raw pointer, thus creating @@ -123,7 +124,6 @@ where // [#61069]: https://github.com/rust-lang/rust/pull/61069 self.trans.gen(dropped_place.local); } - TerminatorKind::Abort | TerminatorKind::Assert { .. } | TerminatorKind::Call { .. } diff --git a/compiler/rustc_mir_dataflow/src/impls/mod.rs b/compiler/rustc_mir_dataflow/src/impls/mod.rs index fd1e492779f1b..69ce1609627b2 100644 --- a/compiler/rustc_mir_dataflow/src/impls/mod.rs +++ b/compiler/rustc_mir_dataflow/src/impls/mod.rs @@ -340,6 +340,14 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { Self::update_bits(trans, path, s) }); + if let mir::TerminatorKind::DropIfInit { place, .. } = terminator.kind { + if let LookupResult::Exact(mpi) = self.move_data().rev_lookup.find(place.as_ref()) { + on_all_children_bits(self.tcx, self.body, self.move_data(), mpi, |mpi| { + Self::update_bits(trans, mpi, DropFlagState::Absent) + }) + } + } + if !self.tcx.sess.opts.unstable_opts.precise_enum_drop_elaboration { return; } @@ -460,9 +468,16 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { fn terminator_effect( &self, trans: &mut impl GenKill, - _terminator: &mir::Terminator<'tcx>, + terminator: &mir::Terminator<'tcx>, location: Location, ) { + if let mir::TerminatorKind::DropIfInit { place, .. } = terminator.kind { + if let LookupResult::Exact(mpi) = self.move_data().rev_lookup.find(place.as_ref()) { + on_all_children_bits(self.tcx, self.body, self.move_data(), mpi, |mpi| { + Self::update_bits(trans, mpi, DropFlagState::Absent) + }) + } + } drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { Self::update_bits(trans, path, s) }); @@ -577,9 +592,16 @@ impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> { fn terminator_effect( &self, trans: &mut impl GenKill, - _terminator: &mir::Terminator<'tcx>, + terminator: &mir::Terminator<'tcx>, location: Location, ) { + if let mir::TerminatorKind::DropIfInit { place, .. } = terminator.kind { + if let LookupResult::Exact(mpi) = self.move_data().rev_lookup.find(place.as_ref()) { + on_all_children_bits(self.tcx, self.body, self.move_data(), mpi, |mpi| { + Self::update_bits(trans, mpi, DropFlagState::Absent) + }) + } + } drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { Self::update_bits(trans, path, s) }) diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index 18760b6c6fa54..38047d81f9a46 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -199,8 +199,8 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc // variants are added. TerminatorKind::Abort | TerminatorKind::Assert { .. } - | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } + | TerminatorKind::DropIfInit { .. } + | TerminatorKind::DropIf { .. } | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } | TerminatorKind::GeneratorDrop @@ -237,8 +237,8 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc TerminatorKind::Yield { .. } | TerminatorKind::Abort | TerminatorKind::Assert { .. } - | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } + | TerminatorKind::DropIfInit { .. } + | TerminatorKind::DropIf { .. } | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } | TerminatorKind::GeneratorDrop diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index f46fd118bde5d..10645031b5eb1 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -391,13 +391,8 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { self.gather_init(place.as_ref(), InitKind::Deep); } - TerminatorKind::Drop { place, target: _, unwind: _ } => { - self.gather_move(place); - } - TerminatorKind::DropAndReplace { place, ref value, .. } => { + TerminatorKind::DropIf { place, .. }| TerminatorKind::DropIfInit { place, .. } => { self.create_move_path(place); - self.gather_operand(value); - self.gather_init(place.as_ref(), InitKind::Deep); } TerminatorKind::Call { ref func, diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index db4b0a3deda9d..68146ca27e1f1 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -227,10 +227,10 @@ pub trait ValueAnalysis<'tcx> { TerminatorKind::Call { .. } | TerminatorKind::InlineAsm { .. } => { // Effect is applied by `handle_call_return`. } - TerminatorKind::Drop { .. } => { + TerminatorKind::DropIf { .. } | TerminatorKind::DropIfInit { .. } => { // We don't track dropped places. } - TerminatorKind::DropAndReplace { .. } | TerminatorKind::Yield { .. } => { + TerminatorKind::Yield { .. } => { // They would have an effect, but are not allowed in this phase. bug!("encountered disallowed terminator"); } diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index d8f85d2e37982..11c7ff4929bfc 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -74,7 +74,7 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls { }; layout::fn_can_unwind(tcx, fn_def_id, sig.abi()) } - TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } => { + TerminatorKind::DropIfInit { .. } | TerminatorKind::DropIf { .. } => { tcx.sess.opts.unstable_opts.panic_in_drop == PanicStrategy::Unwind && layout::fn_can_unwind(tcx, None, Abi::Rust) } diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs index ffb5d8c6d95f2..7797fdae6f0a1 100644 --- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs +++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs @@ -60,14 +60,11 @@ fn add_moves_for_packed_drops_patch<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) let terminator = data.terminator(); match terminator.kind { - TerminatorKind::Drop { place, .. } + TerminatorKind::DropIfInit { place, .. } | TerminatorKind::DropIf { place, .. } if util::is_disaligned(tcx, body, param_env, place) => { add_move_for_packed_drop(tcx, body, &mut patch, terminator, loc, data.is_cleanup); } - TerminatorKind::DropAndReplace { .. } => { - span_bug!(terminator.source_info.span, "replace in AddMovesForPackedDrops"); - } _ => {} } } @@ -84,7 +81,7 @@ fn add_move_for_packed_drop<'tcx>( is_cleanup: bool, ) { debug!("add_move_for_packed_drop({:?} @ {:?})", terminator, loc); - let TerminatorKind::Drop { ref place, target, unwind } = terminator.kind else { + let (TerminatorKind::DropIfInit { ref place, target, unwind: _, is_replace: _ } | TerminatorKind::DropIf { ref place, target, .. }) = terminator.kind else { unreachable!(); }; @@ -100,8 +97,25 @@ fn add_move_for_packed_drop<'tcx>( patch.add_statement(loc, StatementKind::StorageLive(temp)); patch.add_assign(loc, Place::from(temp), Rvalue::Use(Operand::Move(*place))); - patch.patch_terminator( - loc.block, - TerminatorKind::Drop { place: Place::from(temp), target: storage_dead_block, unwind }, - ); + let new_terminator = match terminator.kind.clone() { + TerminatorKind::DropIf { place: _, target: _, unwind, test, is_replace } => { + TerminatorKind::DropIf { + place: Place::from(temp), + target: storage_dead_block, + unwind, + test, + is_replace, + } + } + TerminatorKind::DropIfInit { place: _, target: _, unwind, is_replace } => { + TerminatorKind::DropIfInit { + place: Place::from(temp), + target: storage_dead_block, + unwind, + is_replace, + } + } + _ => unreachable!(), + }; + patch.patch_terminator(loc.block, new_terminator); } diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs index 036b5589849a2..e1544afee6683 100644 --- a/compiler/rustc_mir_transform/src/add_retag.rs +++ b/compiler/rustc_mir_transform/src/add_retag.rs @@ -122,7 +122,7 @@ impl<'tcx> MirPass<'tcx> for AddRetag { } // `Drop` is also a call, but it doesn't return anything so we are good. - TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } => None, + TerminatorKind::DropIfInit { .. } => None, // Not a block ending in a Call -> ignore. _ => None, } diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index e783d18913774..722d87d2d5ee5 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -51,10 +51,10 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { match terminator.kind { TerminatorKind::Goto { .. } | TerminatorKind::SwitchInt { .. } - | TerminatorKind::Drop { .. } + | TerminatorKind::DropIfInit { .. } + | TerminatorKind::DropIf { .. } | TerminatorKind::Yield { .. } | TerminatorKind::Assert { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::Resume | TerminatorKind::Abort diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index 9b9f942b491a2..84042e5a72604 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -1108,8 +1108,8 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> { | TerminatorKind::Abort | TerminatorKind::Return | TerminatorKind::Unreachable - | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } + | TerminatorKind::DropIfInit { .. } + | TerminatorKind::DropIf { .. } | TerminatorKind::Yield { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::FalseEdge { .. } diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index 163446c52e4c2..8a0f571e4fde5 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -691,8 +691,8 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { | TerminatorKind::Abort | TerminatorKind::Return | TerminatorKind::Unreachable - | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } + | TerminatorKind::DropIfInit { .. } + | TerminatorKind::DropIf { .. } | TerminatorKind::Yield { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::FalseEdge { .. } diff --git a/compiler/rustc_mir_transform/src/coverage/debug.rs b/compiler/rustc_mir_transform/src/coverage/debug.rs index 0f8679b0bd69d..0c6d1f8ce503a 100644 --- a/compiler/rustc_mir_transform/src/coverage/debug.rs +++ b/compiler/rustc_mir_transform/src/coverage/debug.rs @@ -818,8 +818,8 @@ pub(super) fn term_type(kind: &TerminatorKind<'_>) -> &'static str { TerminatorKind::Abort => "Abort", TerminatorKind::Return => "Return", TerminatorKind::Unreachable => "Unreachable", - TerminatorKind::Drop { .. } => "Drop", - TerminatorKind::DropAndReplace { .. } => "DropAndReplace", + TerminatorKind::DropIfInit { .. } => "DropIfInit", + TerminatorKind::DropIf { .. } => "DropIf", TerminatorKind::Call { .. } => "Call", TerminatorKind::Assert { .. } => "Assert", TerminatorKind::Yield { .. } => "Yield", diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index 782129be088b6..dd7d581517ec8 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -155,8 +155,8 @@ impl CoverageGraph { TerminatorKind::Goto { .. } | TerminatorKind::Resume | TerminatorKind::Unreachable - | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } + | TerminatorKind::DropIfInit { .. } + | TerminatorKind::DropIf { .. } | TerminatorKind::Call { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::Assert { .. } diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 9f842c929dc24..9f245a23a8948 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -847,8 +847,8 @@ pub(super) fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option MockBlocks<'tcx> { match self.blocks[from_block].terminator_mut().kind { TerminatorKind::Assert { ref mut target, .. } | TerminatorKind::Call { target: Some(ref mut target), .. } - | TerminatorKind::Drop { ref mut target, .. } - | TerminatorKind::DropAndReplace { ref mut target, .. } + | TerminatorKind::DropIfInit { ref mut target, .. } | TerminatorKind::FalseEdge { real_target: ref mut target, .. } | TerminatorKind::FalseUnwind { real_target: ref mut target, .. } | TerminatorKind::Goto { ref mut target } @@ -186,8 +185,7 @@ fn debug_basic_blocks<'tcx>(mir_body: &Body<'tcx>) -> String { match kind { TerminatorKind::Assert { target, .. } | TerminatorKind::Call { target: Some(target), .. } - | TerminatorKind::Drop { target, .. } - | TerminatorKind::DropAndReplace { target, .. } + | TerminatorKind::DropIfInit { target, .. } | TerminatorKind::FalseEdge { real_target: target, .. } | TerminatorKind::FalseUnwind { real_target: target, .. } | TerminatorKind::Goto { target } diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index 3f3870cc7bad2..e26edd3214a80 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -44,6 +44,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS if !place.is_indirect() && !borrowed.contains(place.local) { live.seek_before_primary_effect(loc); if !live.get().contains(place.local) { + // error!("killing {:?} {:?} {:?}", place, loc, body); patch.push(loc); } } diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 9bc47613e4c67..c9470ace57b5f 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -544,23 +544,24 @@ impl<'a> Conflicts<'a> { fn record_terminator_conflicts(&mut self, term: &Terminator<'_>) { match &term.kind { - TerminatorKind::DropAndReplace { - place: dropped_place, - value, - target: _, - unwind: _, - } => { - if let Some(place) = value.place() - && !place.is_indirect() - && !dropped_place.is_indirect() - { - self.record_local_conflict( - place.local, - dropped_place.local, - "DropAndReplace operand overlap", - ); - } - } + // FIXME: ?? + // TerminatorKind::DropIfInitAndReplace { + // place: dropped_place, + // value, + // target: _, + // unwind: _, + // } => { + // if let Some(place) = value.place() + // && !place.is_indirect() + // && !dropped_place.is_indirect() + // { + // self.record_local_conflict( + // place.local, + // dropped_place.local, + // "DropAndReplace operand overlap", + // ); + // } + // } TerminatorKind::Yield { value, resume: _, resume_arg, drop: _ } => { if let Some(place) = value.place() { if !place.is_indirect() && !resume_arg.is_indirect() { @@ -697,7 +698,8 @@ impl<'a> Conflicts<'a> { | TerminatorKind::Abort | TerminatorKind::Return | TerminatorKind::Unreachable - | TerminatorKind::Drop { .. } + | TerminatorKind::DropIfInit { .. } + | TerminatorKind::DropIf { .. } | TerminatorKind::Assert { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::FalseEdge { .. } diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 65f4956d23acd..7d017abaaa72e 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -93,8 +93,7 @@ fn find_dead_unwinds<'tcx>( .into_results_cursor(body); for (bb, bb_data) in body.basic_blocks.iter_enumerated() { let place = match bb_data.terminator().kind { - TerminatorKind::Drop { ref place, unwind: Some(_), .. } - | TerminatorKind::DropAndReplace { ref place, unwind: Some(_), .. } => { + TerminatorKind::DropIfInit { ref place, unwind: Some(_), .. } => { und.derefer(place.as_ref(), body).unwrap_or(*place) } _ => continue, @@ -302,8 +301,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { for (bb, data) in self.body.basic_blocks.iter_enumerated() { let terminator = data.terminator(); let place = match terminator.kind { - TerminatorKind::Drop { ref place, .. } - | TerminatorKind::DropAndReplace { ref place, .. } => { + TerminatorKind::DropIfInit { ref place, .. } => { self.un_derefer.derefer(place.as_ref(), self.body).unwrap_or(*place) } _ => continue, @@ -360,7 +358,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { let resume_block = self.patch.resume_block(); match terminator.kind { - TerminatorKind::Drop { mut place, target, unwind } => { + TerminatorKind::DropIfInit { mut place, target, unwind, is_replace } => { if let Some(new_place) = self.un_derefer.derefer(place.as_ref(), self.body) { place = new_place; } @@ -379,112 +377,44 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { Unwind::To(Option::unwrap_or(unwind, resume_block)) }, bb, + is_replace, ), LookupResult::Parent(..) => { - self.tcx.sess.delay_span_bug( - terminator.source_info.span, - &format!("drop of untracked value {:?}", bb), + if !is_replace { + self.tcx.sess.delay_span_bug( + terminator.source_info.span, + &format!("drop of untracked value {:?}", bb), + ); + } + // If we cannot find it, it means it's a drop followed by a replace + // -> unconditional drop + let test = Operand::Constant(Box::new(Constant { + span: terminator.source_info.span, + user_ty: None, + literal: ConstantKind::from_bool(self.tcx, true), + })); + Elaborator { ctxt: self }.patch().patch_terminator( + bb, + TerminatorKind::DropIf { + place, + target, + unwind: if data.is_cleanup { + None + } else { + Some(Option::unwrap_or(unwind, resume_block)) + }, + is_replace, + test, + }, ); } } } - TerminatorKind::DropAndReplace { mut place, ref value, target, unwind } => { - assert!(!data.is_cleanup); - - if let Some(new_place) = self.un_derefer.derefer(place.as_ref(), self.body) { - place = new_place; - } - self.elaborate_replace(loc, place, value, target, unwind); - } _ => continue, } } } - /// Elaborate a MIR `replace` terminator. This instruction - /// is not directly handled by codegen, and therefore - /// must be desugared. - /// - /// The desugaring drops the location if needed, and then writes - /// the value (including setting the drop flag) over it in *both* arms. - /// - /// The `replace` terminator can also be called on places that - /// are not tracked by elaboration (for example, - /// `replace x[i] <- tmp0`). The borrow checker requires that - /// these locations are initialized before the assignment, - /// so we just generate an unconditional drop. - fn elaborate_replace( - &mut self, - loc: Location, - place: Place<'tcx>, - value: &Operand<'tcx>, - target: BasicBlock, - unwind: Option, - ) { - let bb = loc.block; - let data = &self.body[bb]; - let terminator = data.terminator(); - assert!(!data.is_cleanup, "DropAndReplace in unwind path not supported"); - - let assign = Statement { - kind: StatementKind::Assign(Box::new((place, Rvalue::Use(value.clone())))), - source_info: terminator.source_info, - }; - - let unwind = unwind.unwrap_or_else(|| self.patch.resume_block()); - let unwind = self.patch.new_block(BasicBlockData { - statements: vec![assign.clone()], - terminator: Some(Terminator { - kind: TerminatorKind::Goto { target: unwind }, - ..*terminator - }), - is_cleanup: true, - }); - - let target = self.patch.new_block(BasicBlockData { - statements: vec![assign], - terminator: Some(Terminator { kind: TerminatorKind::Goto { target }, ..*terminator }), - is_cleanup: false, - }); - - match self.move_data().rev_lookup.find(place.as_ref()) { - LookupResult::Exact(path) => { - debug!("elaborate_drop_and_replace({:?}) - tracked {:?}", terminator, path); - self.init_data.seek_before(loc); - elaborate_drop( - &mut Elaborator { ctxt: self }, - terminator.source_info, - place, - path, - target, - Unwind::To(unwind), - bb, - ); - on_all_children_bits(self.tcx, self.body, self.move_data(), path, |child| { - self.set_drop_flag( - Location { block: target, statement_index: 0 }, - child, - DropFlagState::Present, - ); - self.set_drop_flag( - Location { block: unwind, statement_index: 0 }, - child, - DropFlagState::Present, - ); - }); - } - LookupResult::Parent(parent) => { - // drop and replace behind a pointer/array/whatever. The location - // must be initialized. - debug!("elaborate_drop_and_replace({:?}) - untracked {:?}", terminator, parent); - self.patch.patch_terminator( - bb, - TerminatorKind::Drop { place, target, unwind: Some(unwind) }, - ); - } - } - } - fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'tcx> { Rvalue::Use(Operand::Constant(Box::new(Constant { span, @@ -547,25 +477,24 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { // clobbered before they are read. for (bb, data) in self.body.basic_blocks.iter_enumerated() { - debug!("drop_flags_for_locs({:?})", data); for i in 0..(data.statements.len() + 1) { - debug!("drop_flag_for_locs: stmt {}", i); - let mut allow_initializations = true; + let allow_initializations = true; if i == data.statements.len() { match data.terminator().kind { - TerminatorKind::Drop { .. } => { + TerminatorKind::DropIfInit { .. } => { // drop elaboration should handle that by itself continue; } - TerminatorKind::DropAndReplace { .. } => { - // this contains the move of the source and - // the initialization of the destination. We - // only want the former - the latter is handled - // by the elaboration code and must be done - // *after* the destination is dropped. - assert!(self.patch.is_patched(bb)); - allow_initializations = false; - } + // FIXME ?? + // TerminatorKind::DropAndReplace { .. } => { + // // this contains the move of the source and + // // the initialization of the destination. We + // // only want the former - the latter is handled + // // by the elaboration code and must be done + // // *after* the destination is dropped. + // assert!(self.patch.is_patched(bb)); + // allow_initializations = false; + // } TerminatorKind::Resume => { // It is possible for `Resume` to be patched // (in particular it can be patched to be replaced with diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index c833de3a8a750..91ec8660b2d38 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -63,11 +63,13 @@ use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt}; use rustc_middle::ty::{GeneratorSubsts, SubstsRef}; +use rustc_mir_dataflow::elaborate_drops::DropElaborator; use rustc_mir_dataflow::impls::{ MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive, }; use rustc_mir_dataflow::storage::always_storage_live_locals; use rustc_mir_dataflow::{self, Analysis}; +use rustc_span::Span; use rustc_target::abi::VariantIdx; use rustc_target::spec::PanicStrategy; use std::{iter, ops}; @@ -886,15 +888,38 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let mut elaborator = DropShimElaborator { body, patch: MirPatch::new(body), tcx, param_env }; for (block, block_data) in body.basic_blocks.iter_enumerated() { - let (target, unwind, source_info) = match block_data.terminator() { - Terminator { source_info, kind: TerminatorKind::Drop { place, target, unwind } } => { + let (target, unwind, source_info, is_replace) = match block_data.terminator() { + Terminator { + source_info, + kind: TerminatorKind::DropIfInit { place, target, unwind, is_replace }, + } => { if let Some(local) = place.as_local() { if local == SELF_ARG { - (target, unwind, source_info) + (target, unwind, source_info, is_replace) } else { + elaborator.patch().patch_terminator( + block, + TerminatorKind::DropIf { + place: *place, + target: *target, + unwind: unwind.clone(), + is_replace: *is_replace, + test: constant_bool(tcx, source_info.span, true), + }, + ); continue; } } else { + elaborator.patch().patch_terminator( + block, + TerminatorKind::DropIf { + place: *place, + target: *target, + unwind: unwind.clone(), + is_replace: *is_replace, + test: constant_bool(tcx, source_info.span, true), + }, + ); continue; } } @@ -905,6 +930,7 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { } else { Unwind::To(unwind.unwrap_or_else(|| elaborator.patch.resume_block())) }; + elaborate_drop( &mut elaborator, *source_info, @@ -913,11 +939,20 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { *target, unwind, block, + *is_replace, ); } elaborator.patch.apply(body); } +fn constant_bool<'tcx>(tcx: TyCtxt<'tcx>, span: Span, val: bool) -> Operand<'tcx> { + Operand::Constant(Box::new(Constant { + span, + user_ty: None, + literal: ConstantKind::from_bool(tcx, val), + })) +} + fn create_generator_drop_shim<'tcx>( tcx: TyCtxt<'tcx>, transform: &TransformVisitor<'tcx>, @@ -1058,8 +1093,8 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool { } // These may unwind. - TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } + TerminatorKind::DropIfInit { .. } + | TerminatorKind::DropIf { .. } | TerminatorKind::Call { .. } | TerminatorKind::InlineAsm { .. } | TerminatorKind::Assert { .. } => return true, @@ -1148,8 +1183,12 @@ fn create_generator_resume_function<'tcx>( fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock { let return_block = insert_term_block(body, TerminatorKind::Return); - let term = - TerminatorKind::Drop { place: Place::from(SELF_ARG), target: return_block, unwind: None }; + let term = TerminatorKind::DropIfInit { + place: Place::from(SELF_ARG), + target: return_block, + unwind: None, + is_replace: false, + }; let source_info = SourceInfo::outermost(body.span); // Create a block to destroy an unresumed generators. This can only destroy upvars. @@ -1238,8 +1277,13 @@ fn create_cases<'tcx>( .collect() } +struct DeelaborateDrops<'tcx> { + tcx: TyCtxt<'tcx>, +} + impl<'tcx> MirPass<'tcx> for StateTransform { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + dump_mir(tcx, None, "generator_start", &0, body, |_, _| Ok(())); let Some(yield_ty) = body.yield_ty() else { // This only applies to generators return; @@ -1323,6 +1367,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform { let (remap, layout, storage_liveness) = compute_layout(liveness_info, body); let can_return = can_return(tcx, body, tcx.param_env(body.source.def_id())); + dump_mir(tcx, None, "generator_pre-transform", &0, body, |_, _| Ok(())); // Run the transformation which converts Places from Local to generator struct // accesses for locals in `remap`. @@ -1341,12 +1386,17 @@ impl<'tcx> MirPass<'tcx> for StateTransform { }; transform.visit_body(body); + // Drops are now not elaborated again by the generator drop elaboration because it only looks for drop-if-init + let mut de_elaborate_drops = DeelaborateDrops { tcx }; + de_elaborate_drops.visit_body(body); + // Update our MIR struct to reflect the changes we've made body.arg_count = 2; // self, resume arg body.spread_arg = None; body.generator.as_mut().unwrap().yield_ty = None; body.generator.as_mut().unwrap().generator_layout = Some(layout); + dump_mir(tcx, None, "generator_insert", &0, body, |_, _| Ok(())); // Insert `drop(generator_struct)` which is used to drop upvars for generators in // the unresumed state. @@ -1491,8 +1541,8 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> { | TerminatorKind::Abort | TerminatorKind::Return | TerminatorKind::Unreachable - | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } + | TerminatorKind::DropIfInit { .. } + | TerminatorKind::DropIf { .. } | TerminatorKind::Assert { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::FalseEdge { .. } @@ -1500,3 +1550,26 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> { } } } + +impl<'tcx> MutVisitor<'tcx> for DeelaborateDrops<'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, _location: Location) { + let (place, target, unwind, is_replace) = if let TerminatorKind::DropIf { + place, + target, + unwind, + test: Operand::Constant(_), + is_replace, + } = &terminator.kind + { + (*place, *target, *unwind, *is_replace) + } else { + return; + }; + + terminator.kind = TerminatorKind::DropIfInit { place, target, unwind, is_replace }; + } +} diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 780b91d9215d5..a50b6fcc88482 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -443,9 +443,7 @@ impl<'tcx> Inliner<'tcx> { checker.visit_basic_block_data(bb, blk); let term = blk.terminator(); - if let TerminatorKind::Drop { ref place, target, unwind } - | TerminatorKind::DropAndReplace { ref place, target, unwind, .. } = term.kind - { + if let TerminatorKind::DropIfInit { ref place, target, unwind, .. } = term.kind { work_list.push(target); // If the place doesn't actually need dropping, treat it like a regular goto. @@ -771,8 +769,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { let tcx = self.tcx; match terminator.kind { - TerminatorKind::Drop { ref place, unwind, .. } - | TerminatorKind::DropAndReplace { ref place, unwind, .. } => { + TerminatorKind::DropIfInit { ref place, unwind, .. } => { // If the place doesn't actually need dropping, treat it like a regular goto. let ty = self.instance.subst_mir(tcx, &place.ty(self.callee_body, tcx).ty); if ty.needs_drop(tcx, self.param_env) { @@ -1097,8 +1094,8 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> { *tgt = self.map_block(*tgt); } } - TerminatorKind::Drop { ref mut target, ref mut unwind, .. } - | TerminatorKind::DropAndReplace { ref mut target, ref mut unwind, .. } => { + TerminatorKind::DropIfInit { ref mut target, ref mut unwind, .. } + | TerminatorKind::DropIf { ref mut target, ref mut unwind, .. } => { *target = self.map_block(*target); *unwind = self.map_unwind(*unwind); } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 5e85d1f0db447..afdabe17b4247 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -481,7 +481,7 @@ fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx> check_consts::post_drop_elaboration::check_live_drops(tcx, &body); // FIXME: make this a MIR lint } - debug!("runtime_mir_lowering({:?})", did); + debug!("runtime_mir_lowering({:?}) {:?}", did, body); run_runtime_lowering_passes(tcx, body); assert!(body.phase == MirPhase::Runtime(RuntimePhase::Initial)); diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index f1bbf2ea7e8ea..fab2d37aba600 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -74,8 +74,8 @@ impl RemoveNoopLandingPads { | TerminatorKind::Unreachable | TerminatorKind::Call { .. } | TerminatorKind::Assert { .. } - | TerminatorKind::DropAndReplace { .. } - | TerminatorKind::Drop { .. } + | TerminatorKind::DropIfInit { .. } + | TerminatorKind::DropIf { .. } | TerminatorKind::InlineAsm { .. } => false, } } diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs index 78b6f714a9b0b..59a8e4ab3d3d2 100644 --- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs @@ -1,5 +1,5 @@ use rustc_index::bit_set::ChunkedBitSet; -use rustc_middle::mir::{Body, Field, Rvalue, Statement, StatementKind, TerminatorKind}; +use rustc_middle::mir::{Body, Field, TerminatorKind}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, VariantDef}; use rustc_mir_dataflow::impls::MaybeInitializedPlaces; @@ -8,6 +8,7 @@ use rustc_mir_dataflow::{self, move_path_children_matching, Analysis, MoveDataPa use crate::MirPass; +// FIXME: can remove this altogether by moving drop elaboration *before* borrowck /// Removes `Drop` and `DropAndReplace` terminators whose target is known to be uninitialized at /// that point. /// @@ -37,7 +38,7 @@ impl<'tcx> MirPass<'tcx> for RemoveUninitDrops { let mut to_remove = vec![]; for (bb, block) in body.basic_blocks.iter_enumerated() { let terminator = block.terminator(); - let (TerminatorKind::Drop { place, .. } | TerminatorKind::DropAndReplace { place, .. }) + let TerminatorKind::DropIfInit { place, .. } = &terminator.kind else { continue }; @@ -64,24 +65,16 @@ impl<'tcx> MirPass<'tcx> for RemoveUninitDrops { for bb in to_remove { let block = &mut body.basic_blocks_mut()[bb]; - let (TerminatorKind::Drop { target, .. } | TerminatorKind::DropAndReplace { target, .. }) + let TerminatorKind::DropIfInit { target, .. } = &block.terminator().kind else { unreachable!() }; // Replace block terminator with `Goto`. let target = *target; - let old_terminator_kind = std::mem::replace( + let _ = std::mem::replace( &mut block.terminator_mut().kind, TerminatorKind::Goto { target }, ); - - // If this is a `DropAndReplace`, we need to emulate the assignment to the return place. - if let TerminatorKind::DropAndReplace { place, value, .. } = old_terminator_kind { - block.statements.push(Statement { - source_info: block.terminator().source_info, - kind: StatementKind::Assign(Box::new((place, Rvalue::Use(value)))), - }); - } } } } diff --git a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs index 84ccf6e1f61d4..a5c72d1f51e65 100644 --- a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs @@ -22,7 +22,7 @@ impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops { for block in body.basic_blocks.as_mut() { let terminator = block.terminator_mut(); - if let TerminatorKind::Drop { place, target, .. } = terminator.kind { + if let TerminatorKind::DropIf { place, target, .. } = terminator.kind { let ty = place.ty(&body.local_decls, tcx); if ty.ty.needs_drop(tcx, param_env) { continue; diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs index 2f116aaa95849..19cef8c4479e1 100644 --- a/compiler/rustc_mir_transform/src/separate_const_switch.rs +++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs @@ -107,8 +107,8 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize { // The following terminators are not allowed TerminatorKind::Resume - | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } + | TerminatorKind::DropIfInit { .. } + | TerminatorKind::DropIf { .. } | TerminatorKind::Call { .. } | TerminatorKind::Assert { .. } | TerminatorKind::FalseUnwind { .. } @@ -170,9 +170,9 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize { | TerminatorKind::Unreachable | TerminatorKind::GeneratorDrop | TerminatorKind::Assert { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::FalseUnwind { .. } - | TerminatorKind::Drop { .. } + | TerminatorKind::DropIfInit { .. } + | TerminatorKind::DropIf { .. } | TerminatorKind::Call { .. } | TerminatorKind::InlineAsm { .. } | TerminatorKind::Yield { .. } => { diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index a0ff7550faeb8..acaba1f40c87a 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -201,6 +201,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) return_block, elaborate_drops::Unwind::To(resume_block), START_BLOCK, + false, ); elaborator.patch }; @@ -497,7 +498,13 @@ impl<'tcx> CloneShimBuilder<'tcx> { self.make_clone_call(dest_field, src_field, ity, next_block, unwind); self.block( vec![], - TerminatorKind::Drop { place: dest_field, target: unwind, unwind: None }, + TerminatorKind::DropIf { + place: dest_field, + target: unwind, + unwind: None, + is_replace: false, + test: constant_bool(self.tcx, self.span, true), + }, true, ); unwind = next_unwind; @@ -751,7 +758,13 @@ fn build_call_shim<'tcx>( block( &mut blocks, vec![], - TerminatorKind::Drop { place: rcvr_place(), target: BasicBlock::new(2), unwind: None }, + TerminatorKind::DropIf { + place: rcvr_place(), + target: BasicBlock::new(2), + unwind: None, + is_replace: false, + test: constant_bool(tcx, span, true), + }, false, ); } @@ -762,7 +775,13 @@ fn build_call_shim<'tcx>( block( &mut blocks, vec![], - TerminatorKind::Drop { place: rcvr_place(), target: BasicBlock::new(4), unwind: None }, + TerminatorKind::DropIf { + place: rcvr_place(), + target: BasicBlock::new(4), + unwind: None, + is_replace: false, + test: constant_bool(tcx, span, true), + }, true, ); @@ -845,3 +864,11 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> { body } + +fn constant_bool<'tcx>(tcx: TyCtxt<'tcx>, span: Span, value: bool) -> Operand<'tcx> { + Operand::Constant(Box::new(Constant { + span, + user_ty: None, + literal: ConstantKind::from_bool(tcx, value), + })) +} diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index 558a372fb1e8a..d8bb544ba5134 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -83,9 +83,7 @@ fn escaping_locals(body: &Body<'_>) -> BitSet { fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { // Drop implicitly calls `drop_in_place`, which takes a `&mut`. // This implies that `Drop` implicitly takes the address of the place. - if let TerminatorKind::Drop { place, .. } - | TerminatorKind::DropAndReplace { place, .. } = terminator.kind - { + if let TerminatorKind::DropIfInit { place, .. } = terminator.kind { if !place.is_indirect() { // Raw pointers may be used to access anything inside the enclosing place. self.set.insert(place.local); diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index e296d4766c18b..4b6a65debfabf 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -812,8 +812,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { let callee_ty = self.monomorphize(callee_ty); visit_fn_use(self.tcx, callee_ty, true, source, &mut self.output) } - mir::TerminatorKind::Drop { ref place, .. } - | mir::TerminatorKind::DropAndReplace { ref place, .. } => { + mir::TerminatorKind::DropIfInit { ref place, .. } + | mir::TerminatorKind::DropIf { ref place, .. } => { let ty = place.ty(self.body, self.tcx).ty; let ty = self.monomorphize(ty); visit_drop_use(self.tcx, ty, true, source, self.output); diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 45b63a4aa5df8..da45b0d267a00 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -291,10 +291,8 @@ fn check_terminator<'a, 'tcx>( | TerminatorKind::Resume | TerminatorKind::Unreachable => Ok(()), - TerminatorKind::Drop { place, .. } => check_place(tcx, *place, span, body), - TerminatorKind::DropAndReplace { place, value, .. } => { - check_place(tcx, *place, span, body)?; - check_operand(tcx, value, span, body) + TerminatorKind::DropIfInit { place, .. } | TerminatorKind::DropIf { place, .. } => { + check_place(tcx, *place, span, body) }, TerminatorKind::SwitchInt {