Remove DropAndReplace terminator

PR 107844 made DropAndReplace unused, let's remove it completely
from the codebase.
This commit is contained in:
Giacomo Pasini 2023-03-05 21:02:14 +01:00
parent 14c54b637b
commit c5d4e4d907
No known key found for this signature in database
GPG Key ID: A03851B78A6C9A46
48 changed files with 33 additions and 341 deletions

View File

@ -118,15 +118,6 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
LocalMutationIsAllowed::Yes, LocalMutationIsAllowed::Yes,
); );
} }
TerminatorKind::DropAndReplace {
place: drop_place,
value: new_value,
target: _,
unwind: _,
} => {
self.mutate_place(location, *drop_place, Deep);
self.consume_operand(location, new_value);
}
TerminatorKind::Call { TerminatorKind::Call {
func, func,
args, args,

View File

@ -744,15 +744,6 @@ fn visit_terminator_before_primary_effect(
flow_state, flow_state,
); );
} }
TerminatorKind::DropAndReplace {
place: drop_place,
value: new_value,
target: _,
unwind: _,
} => {
self.mutate_place(loc, (*drop_place, span), Deep, flow_state);
self.consume_operand(loc, (new_value, span), flow_state);
}
TerminatorKind::Call { TerminatorKind::Call {
func, func,
args, args,
@ -867,7 +858,6 @@ fn visit_terminator_after_primary_effect(
| TerminatorKind::Assert { .. } | TerminatorKind::Assert { .. }
| TerminatorKind::Call { .. } | TerminatorKind::Call { .. }
| TerminatorKind::Drop { .. } | TerminatorKind::Drop { .. }
| TerminatorKind::DropAndReplace { .. }
| TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ } | TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ }
| TerminatorKind::FalseUnwind { real_target: _, unwind: _ } | TerminatorKind::FalseUnwind { real_target: _, unwind: _ }
| TerminatorKind::Goto { .. } | TerminatorKind::Goto { .. }

View File

@ -435,8 +435,7 @@ fn compute_drop_live_points_for_block(&mut self, mpi: MovePathIndex, term_point:
// //
// What we *actually* generate is a store to a temporary // What we *actually* generate is a store to a temporary
// for the call (`TMP = call()...`) and then a // for the call (`TMP = call()...`) and then a
// `DropAndReplace` to swap that with `X` // `Drop(X)` followed by `X = TMP` to swap that with `X`.
// (`DropAndReplace` has very particular semantics).
} }
} }

View File

@ -1312,24 +1312,6 @@ fn check_terminator(
// no checks needed for these // no checks needed for these
} }
TerminatorKind::DropAndReplace { place, 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 { discr, .. } => { TerminatorKind::SwitchInt { discr, .. } => {
self.check_operand(discr, term_location); self.check_operand(discr, term_location);
@ -1629,7 +1611,6 @@ fn check_iscleanup(&mut self, body: &Body<'tcx>, block_data: &BasicBlockData<'tc
} }
TerminatorKind::Unreachable => {} TerminatorKind::Unreachable => {}
TerminatorKind::Drop { target, unwind, .. } TerminatorKind::Drop { target, unwind, .. }
| TerminatorKind::DropAndReplace { target, unwind, .. }
| TerminatorKind::Assert { target, cleanup: unwind, .. } => { | TerminatorKind::Assert { target, cleanup: unwind, .. } => {
self.assert_iscleanup(body, block_data, target, is_cleanup); self.assert_iscleanup(body, block_data, target, is_cleanup);
if let Some(unwind) = unwind { if let Some(unwind) = unwind {

View File

@ -71,9 +71,6 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
TerminatorKind::Call { destination, .. } => { TerminatorKind::Call { destination, .. } => {
self.remove_never_initialized_mut_locals(*destination); self.remove_never_initialized_mut_locals(*destination);
} }
TerminatorKind::DropAndReplace { place, .. } => {
self.remove_never_initialized_mut_locals(*place);
}
_ => {} _ => {}
} }

View File

@ -499,7 +499,6 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
TerminatorKind::Yield { .. } TerminatorKind::Yield { .. }
| TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseEdge { .. }
| TerminatorKind::FalseUnwind { .. } | TerminatorKind::FalseUnwind { .. }
| TerminatorKind::DropAndReplace { .. }
| TerminatorKind::GeneratorDrop => { | TerminatorKind::GeneratorDrop => {
bug!("shouldn't exist at codegen {:?}", bb_data.terminator()); bug!("shouldn't exist at codegen {:?}", bb_data.terminator());
} }

View File

@ -543,8 +543,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::Drop { .. } | TerminatorKind::Drop { .. }
| TerminatorKind::Assert { .. } => {} | TerminatorKind::Assert { .. } => {}
TerminatorKind::DropAndReplace { .. } TerminatorKind::Yield { .. }
| TerminatorKind::Yield { .. }
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
| TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseEdge { .. }
| TerminatorKind::FalseUnwind { .. } => unreachable!(), | TerminatorKind::FalseUnwind { .. } => unreachable!(),

View File

@ -295,7 +295,6 @@ fn discover_masters<'tcx>(
TerminatorKind::Call { cleanup: unwind, .. } TerminatorKind::Call { cleanup: unwind, .. }
| TerminatorKind::InlineAsm { cleanup: unwind, .. } | TerminatorKind::InlineAsm { cleanup: unwind, .. }
| TerminatorKind::Assert { cleanup: unwind, .. } | TerminatorKind::Assert { cleanup: unwind, .. }
| TerminatorKind::DropAndReplace { unwind, .. }
| TerminatorKind::Drop { unwind, .. } => { | TerminatorKind::Drop { unwind, .. } => {
if let Some(unwind) = unwind { if let Some(unwind) = unwind {
debug!( debug!(

View File

@ -1305,10 +1305,6 @@ fn codegen_terminator(
mergeable_succ(), mergeable_succ(),
), ),
mir::TerminatorKind::DropAndReplace { .. } => {
bug!("undesugared DropAndReplace in codegen: {:?}", terminator);
}
mir::TerminatorKind::Call { mir::TerminatorKind::Call {
ref func, ref func,
ref args, ref args,

View File

@ -171,11 +171,7 @@ pub(super) fn eval_terminator(
Unreachable => throw_ub!(Unreachable), Unreachable => throw_ub!(Unreachable),
// These should never occur for MIR we actually run. // These should never occur for MIR we actually run.
DropAndReplace { .. } FalseEdge { .. } | FalseUnwind { .. } | Yield { .. } | GeneratorDrop => span_bug!(
| FalseEdge { .. }
| FalseUnwind { .. }
| Yield { .. }
| GeneratorDrop => span_bug!(
terminator.source_info.span, terminator.source_info.span,
"{:#?} should have been eliminated by MIR pass", "{:#?} should have been eliminated by MIR pass",
terminator.kind terminator.kind

View File

@ -977,8 +977,7 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
// Forbid all `Drop` terminators unless the place being dropped is a local with no // Forbid all `Drop` terminators unless the place being dropped is a local with no
// projections that cannot be `NeedsNonConstDrop`. // projections that cannot be `NeedsNonConstDrop`.
TerminatorKind::Drop { place: dropped_place, .. } TerminatorKind::Drop { place: dropped_place, .. } => {
| TerminatorKind::DropAndReplace { place: dropped_place, .. } => {
// If we are checking live drops after drop-elaboration, don't emit duplicate // If we are checking live drops after drop-elaboration, don't emit duplicate
// errors here. // errors here.
if super::post_drop_elaboration::checking_enabled(self.ccx) { if super::post_drop_elaboration::checking_enabled(self.ccx) {

View File

@ -80,8 +80,7 @@ fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Loc
trace!("visit_terminator: terminator={:?} location={:?}", terminator, location); trace!("visit_terminator: terminator={:?} location={:?}", terminator, location);
match &terminator.kind { match &terminator.kind {
mir::TerminatorKind::Drop { place: dropped_place, .. } mir::TerminatorKind::Drop { place: dropped_place, .. } => {
| mir::TerminatorKind::DropAndReplace { place: dropped_place, .. } => {
let dropped_ty = dropped_place.ty(self.body, self.tcx).ty; let dropped_ty = dropped_place.ty(self.body, self.tcx).ty;
if !NeedsNonConstDrop::in_any_value_of_ty(self.ccx, dropped_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 // Instead of throwing a bug, we just return here. This is because we have to

View File

@ -222,18 +222,6 @@ fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Loc
// The effect of assignment to the return place in `TerminatorKind::Call` is not applied // The effect of assignment to the return place in `TerminatorKind::Call` is not applied
// here; that occurs in `apply_call_return_effect`. // here; that occurs in `apply_call_return_effect`.
if let mir::TerminatorKind::DropAndReplace { value, place, .. } = &terminator.kind {
let qualif = qualifs::in_operand::<Q, _>(
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. // 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. // FIXME: Reconsider if accounting for borrows in drops is necessary for const drop.

View File

@ -835,18 +835,6 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
self.check_edge(location, *unwind, EdgeKind::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",
);
}
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, .. } => { TerminatorKind::Call { func, args, destination, target, cleanup, .. } => {
let func_ty = func.ty(&self.body.local_decls, self.tcx); let func_ty = func.ty(&self.body.local_decls, self.tcx);
match func_ty.kind() { match func_ty.kind() {

View File

@ -265,7 +265,6 @@ pub fn terminator_kind_name(term: &Terminator<'_>) -> &'static str {
Return => "Return", Return => "Return",
Unreachable => "Unreachable", Unreachable => "Unreachable",
Drop { .. } => "Drop", Drop { .. } => "Drop",
DropAndReplace { .. } => "DropAndReplace",
Call { .. } => "Call", Call { .. } => "Call",
Assert { .. } => "Assert", Assert { .. } => "Assert",
Yield { .. } => "Yield", Yield { .. } => "Yield",

View File

@ -133,7 +133,6 @@ pub enum AnalysisPhase {
pub enum RuntimePhase { pub enum RuntimePhase {
/// In addition to the semantic changes, beginning with this phase, the following variants are /// In addition to the semantic changes, beginning with this phase, the following variants are
/// disallowed: /// disallowed:
/// * [`TerminatorKind::DropAndReplace`]
/// * [`TerminatorKind::Yield`] /// * [`TerminatorKind::Yield`]
/// * [`TerminatorKind::GeneratorDrop`] /// * [`TerminatorKind::GeneratorDrop`]
/// * [`Rvalue::Aggregate`] for any `AggregateKind` except `Array` /// * [`Rvalue::Aggregate`] for any `AggregateKind` except `Array`
@ -596,43 +595,6 @@ pub enum TerminatorKind<'tcx> {
/// > consider indirect assignments. /// > consider indirect assignments.
Drop { place: Place<'tcx>, target: BasicBlock, unwind: Option<BasicBlock> }, Drop { place: Place<'tcx>, target: BasicBlock, unwind: Option<BasicBlock> },
/// 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 {
place: Place<'tcx>,
value: Operand<'tcx>,
target: BasicBlock,
unwind: Option<BasicBlock>,
},
/// Roughly speaking, evaluates the `func` operand and the arguments, and starts execution of /// 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 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 /// The return place type must match the return type. The type of the `func` operand must be

View File

@ -148,7 +148,6 @@ pub fn successors(&self) -> Successors<'_> {
| Call { target: None, cleanup: Some(t), .. } | Call { target: None, cleanup: Some(t), .. }
| Call { target: Some(t), cleanup: None, .. } | Call { target: Some(t), cleanup: None, .. }
| Yield { resume: t, drop: None, .. } | Yield { resume: t, drop: None, .. }
| DropAndReplace { target: t, unwind: None, .. }
| Drop { target: t, unwind: None, .. } | Drop { target: t, unwind: None, .. }
| Assert { target: t, cleanup: None, .. } | Assert { target: t, cleanup: None, .. }
| FalseUnwind { real_target: t, unwind: None } | FalseUnwind { real_target: t, unwind: None }
@ -158,7 +157,6 @@ pub fn successors(&self) -> Successors<'_> {
} }
Call { target: Some(t), cleanup: Some(ref u), .. } Call { target: Some(t), cleanup: Some(ref u), .. }
| Yield { resume: t, drop: Some(ref u), .. } | Yield { resume: t, drop: Some(ref u), .. }
| DropAndReplace { target: t, unwind: Some(ref u), .. }
| Drop { target: t, unwind: Some(ref u), .. } | Drop { target: t, unwind: Some(ref u), .. }
| Assert { target: t, cleanup: Some(ref u), .. } | Assert { target: t, cleanup: Some(ref u), .. }
| FalseUnwind { real_target: t, unwind: Some(ref u) } | FalseUnwind { real_target: t, unwind: Some(ref u) }
@ -188,7 +186,6 @@ pub fn successors_mut(&mut self) -> SuccessorsMut<'_> {
| Call { target: None, cleanup: Some(ref mut t), .. } | Call { target: None, cleanup: Some(ref mut t), .. }
| Call { target: Some(ref mut t), cleanup: None, .. } | Call { target: Some(ref mut t), cleanup: None, .. }
| Yield { resume: ref mut t, drop: None, .. } | Yield { resume: ref mut t, drop: None, .. }
| DropAndReplace { target: ref mut t, unwind: None, .. }
| Drop { target: ref mut t, unwind: None, .. } | Drop { target: ref mut t, unwind: None, .. }
| Assert { target: ref mut t, cleanup: None, .. } | Assert { target: ref mut t, cleanup: None, .. }
| FalseUnwind { real_target: ref mut t, unwind: None } | FalseUnwind { real_target: ref mut t, unwind: None }
@ -198,7 +195,6 @@ pub fn successors_mut(&mut self) -> SuccessorsMut<'_> {
} }
Call { target: Some(ref mut t), cleanup: Some(ref mut u), .. } Call { target: Some(ref mut t), cleanup: Some(ref mut u), .. }
| Yield { resume: ref mut t, drop: 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), .. } | Drop { target: ref mut t, unwind: Some(ref mut u), .. }
| Assert { target: ref mut t, cleanup: 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) } | FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) }
@ -225,7 +221,6 @@ pub fn unwind(&self) -> Option<&Option<BasicBlock>> {
| TerminatorKind::FalseEdge { .. } => None, | TerminatorKind::FalseEdge { .. } => None,
TerminatorKind::Call { cleanup: ref unwind, .. } TerminatorKind::Call { cleanup: ref unwind, .. }
| TerminatorKind::Assert { cleanup: ref unwind, .. } | TerminatorKind::Assert { cleanup: ref unwind, .. }
| TerminatorKind::DropAndReplace { ref unwind, .. }
| TerminatorKind::Drop { ref unwind, .. } | TerminatorKind::Drop { ref unwind, .. }
| TerminatorKind::FalseUnwind { ref unwind, .. } | TerminatorKind::FalseUnwind { ref unwind, .. }
| TerminatorKind::InlineAsm { cleanup: ref unwind, .. } => Some(unwind), | TerminatorKind::InlineAsm { cleanup: ref unwind, .. } => Some(unwind),
@ -245,7 +240,6 @@ pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
| TerminatorKind::FalseEdge { .. } => None, | TerminatorKind::FalseEdge { .. } => None,
TerminatorKind::Call { cleanup: ref mut unwind, .. } TerminatorKind::Call { cleanup: ref mut unwind, .. }
| TerminatorKind::Assert { cleanup: ref mut unwind, .. } | TerminatorKind::Assert { cleanup: ref mut unwind, .. }
| TerminatorKind::DropAndReplace { ref mut unwind, .. }
| TerminatorKind::Drop { ref mut unwind, .. } | TerminatorKind::Drop { ref mut unwind, .. }
| TerminatorKind::FalseUnwind { ref mut unwind, .. } | TerminatorKind::FalseUnwind { ref mut unwind, .. }
| TerminatorKind::InlineAsm { cleanup: ref mut unwind, .. } => Some(unwind), | TerminatorKind::InlineAsm { cleanup: ref mut unwind, .. } => Some(unwind),
@ -309,9 +303,6 @@ pub fn fmt_head<W: Write>(&self, fmt: &mut W) -> fmt::Result {
Yield { value, resume_arg, .. } => write!(fmt, "{:?} = yield({:?})", resume_arg, value), Yield { value, resume_arg, .. } => write!(fmt, "{:?} = yield({:?})", resume_arg, value),
Unreachable => write!(fmt, "unreachable"), Unreachable => write!(fmt, "unreachable"),
Drop { place, .. } => write!(fmt, "drop({:?})", place), Drop { place, .. } => write!(fmt, "drop({:?})", place),
DropAndReplace { place, value, .. } => {
write!(fmt, "replace({:?} <- {:?})", place, value)
}
Call { func, args, destination, .. } => { Call { func, args, destination, .. } => {
write!(fmt, "{:?} = ", destination)?; write!(fmt, "{:?} = ", destination)?;
write!(fmt, "{:?}(", func)?; write!(fmt, "{:?}(", func)?;
@ -403,10 +394,10 @@ pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
Call { target: None, cleanup: None, .. } => vec![], Call { target: None, cleanup: None, .. } => vec![],
Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()], Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()],
Yield { drop: None, .. } => vec!["resume".into()], Yield { drop: None, .. } => vec!["resume".into()],
DropAndReplace { unwind: None, .. } | Drop { unwind: None, .. } => { Drop { unwind: None, .. } => {
vec!["return".into()] vec!["return".into()]
} }
DropAndReplace { unwind: Some(_), .. } | Drop { unwind: Some(_), .. } => { Drop { unwind: Some(_), .. } => {
vec!["return".into(), "unwind".into()] vec!["return".into(), "unwind".into()]
} }
Assert { cleanup: None, .. } => vec!["".into()], Assert { cleanup: None, .. } => vec!["".into()],

View File

@ -495,20 +495,6 @@ fn super_terminator(&mut self,
); );
} }
TerminatorKind::DropAndReplace {
place,
value,
target: _,
unwind: _,
} => {
self.visit_place(
place,
PlaceContext::MutatingUse(MutatingUseContext::Drop),
location
);
self.visit_operand(value, location);
}
TerminatorKind::Call { TerminatorKind::Call {
func, func,
args, args,

View File

@ -58,14 +58,6 @@ pub fn parse_terminator(&self, expr_id: ExprId) -> PResult<TerminatorKind<'tcx>>
unwind: None, unwind: None,
}) })
}, },
@call("mir_drop_and_replace", args) => {
Ok(TerminatorKind::DropAndReplace {
place: self.parse_place(args[0])?,
value: self.parse_operand(args[1])?,
target: self.parse_block(args[2])?,
unwind: None,
})
},
@call("mir_call", args) => { @call("mir_call", args) => {
let destination = self.parse_place(args[0])?; let destination = self.parse_place(args[0])?;
let target = self.parse_block(args[1])?; let target = self.parse_block(args[1])?;

View File

@ -1072,7 +1072,6 @@ pub(crate) fn diverge_from(&mut self, start: BasicBlock) {
TerminatorKind::Assert { .. } TerminatorKind::Assert { .. }
| TerminatorKind::Call { .. } | TerminatorKind::Call { .. }
| TerminatorKind::Drop { .. } | TerminatorKind::Drop { .. }
| TerminatorKind::DropAndReplace { .. }
| TerminatorKind::FalseUnwind { .. } | TerminatorKind::FalseUnwind { .. }
| TerminatorKind::InlineAsm { .. } | TerminatorKind::InlineAsm { .. }
), ),
@ -1432,8 +1431,7 @@ fn add_entry(cfg: &mut CFG<'tcx>, from: BasicBlock, to: BasicBlock) {
*unwind = Some(to); *unwind = Some(to);
} }
} }
TerminatorKind::DropAndReplace { unwind, .. } TerminatorKind::FalseUnwind { unwind, .. }
| TerminatorKind::FalseUnwind { unwind, .. }
| TerminatorKind::Call { cleanup: unwind, .. } | TerminatorKind::Call { cleanup: unwind, .. }
| TerminatorKind::Assert { cleanup: unwind, .. } | TerminatorKind::Assert { cleanup: unwind, .. }
| TerminatorKind::InlineAsm { cleanup: unwind, .. } => { | TerminatorKind::InlineAsm { cleanup: unwind, .. } => {

View File

@ -128,7 +128,6 @@ fn node_examined(
TerminatorKind::Assert { .. } TerminatorKind::Assert { .. }
| TerminatorKind::Call { .. } | TerminatorKind::Call { .. }
| TerminatorKind::Drop { .. } | TerminatorKind::Drop { .. }
| TerminatorKind::DropAndReplace { .. }
| TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseEdge { .. }
| TerminatorKind::FalseUnwind { .. } | TerminatorKind::FalseUnwind { .. }
| TerminatorKind::Goto { .. } | TerminatorKind::Goto { .. }

View File

@ -480,7 +480,6 @@ fn join_state_into_successors_of<'tcx, A>(
Assert { target, cleanup: unwind, expected: _, msg: _, cond: _ } Assert { target, cleanup: unwind, expected: _, msg: _, cond: _ }
| Drop { target, unwind, place: _ } | Drop { target, unwind, place: _ }
| DropAndReplace { target, unwind, value: _, place: _ }
| FalseUnwind { real_target: target, unwind } => { | FalseUnwind { real_target: target, unwind } => {
if let Some(unwind) = unwind { if let Some(unwind) = unwind {
propagate(unwind, exit_state); propagate(unwind, exit_state);

View File

@ -111,8 +111,7 @@ fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Loc
self.super_terminator(terminator, location); self.super_terminator(terminator, location);
match terminator.kind { match terminator.kind {
mir::TerminatorKind::Drop { place: dropped_place, .. } mir::TerminatorKind::Drop { place: dropped_place, .. } => {
| mir::TerminatorKind::DropAndReplace { place: dropped_place, .. } => {
// Drop terminators may call custom drop glue (`Drop::drop`), which takes `&mut // 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 // 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 // reference into the surrounding environment through a raw pointer, thus creating

View File

@ -202,7 +202,6 @@ fn before_terminator_effect(
TerminatorKind::Abort TerminatorKind::Abort
| TerminatorKind::Assert { .. } | TerminatorKind::Assert { .. }
| TerminatorKind::Drop { .. } | TerminatorKind::Drop { .. }
| TerminatorKind::DropAndReplace { .. }
| TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseEdge { .. }
| TerminatorKind::FalseUnwind { .. } | TerminatorKind::FalseUnwind { .. }
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
@ -240,7 +239,6 @@ fn terminator_effect(
| TerminatorKind::Abort | TerminatorKind::Abort
| TerminatorKind::Assert { .. } | TerminatorKind::Assert { .. }
| TerminatorKind::Drop { .. } | TerminatorKind::Drop { .. }
| TerminatorKind::DropAndReplace { .. }
| TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseEdge { .. }
| TerminatorKind::FalseUnwind { .. } | TerminatorKind::FalseUnwind { .. }
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop

View File

@ -392,11 +392,6 @@ fn gather_terminator(&mut self, term: &Terminator<'tcx>) {
self.create_move_path(place); self.create_move_path(place);
self.gather_init(place.as_ref(), InitKind::Deep); self.gather_init(place.as_ref(), InitKind::Deep);
} }
TerminatorKind::DropAndReplace { place, ref value, .. } => {
self.create_move_path(place);
self.gather_operand(value);
self.gather_init(place.as_ref(), InitKind::Deep);
}
TerminatorKind::Call { TerminatorKind::Call {
ref func, ref func,
ref args, ref args,

View File

@ -230,7 +230,7 @@ fn super_terminator(&self, terminator: &Terminator<'tcx>, state: &mut State<Self
TerminatorKind::Drop { place, .. } => { TerminatorKind::Drop { place, .. } => {
state.flood_with(place.as_ref(), self.map(), Self::Value::bottom()); state.flood_with(place.as_ref(), self.map(), Self::Value::bottom());
} }
TerminatorKind::DropAndReplace { .. } | TerminatorKind::Yield { .. } => { TerminatorKind::Yield { .. } => {
// They would have an effect, but are not allowed in this phase. // They would have an effect, but are not allowed in this phase.
bug!("encountered disallowed terminator"); bug!("encountered disallowed terminator");
} }

View File

@ -74,7 +74,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
}; };
layout::fn_can_unwind(tcx, fn_def_id, sig.abi()) layout::fn_can_unwind(tcx, fn_def_id, sig.abi())
} }
TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } => { TerminatorKind::Drop { .. } => {
tcx.sess.opts.unstable_opts.panic_in_drop == PanicStrategy::Unwind tcx.sess.opts.unstable_opts.panic_in_drop == PanicStrategy::Unwind
&& layout::fn_can_unwind(tcx, None, Abi::Rust) && layout::fn_can_unwind(tcx, None, Abi::Rust)
} }

View File

@ -64,9 +64,6 @@ fn add_moves_for_packed_drops_patch<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>)
{ {
add_move_for_packed_drop(tcx, body, &mut patch, terminator, loc, data.is_cleanup); 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");
}
_ => {} _ => {}
} }
} }

View File

@ -100,7 +100,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
} }
// `Drop` is also a call, but it doesn't return anything so we are good. // `Drop` is also a call, but it doesn't return anything so we are good.
TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } => None, TerminatorKind::Drop { .. } => None,
// Not a block ending in a Call -> ignore. // Not a block ending in a Call -> ignore.
_ => None, _ => None,
} }

View File

@ -55,7 +55,6 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
| TerminatorKind::Drop { .. } | TerminatorKind::Drop { .. }
| TerminatorKind::Yield { .. } | TerminatorKind::Yield { .. }
| TerminatorKind::Assert { .. } | TerminatorKind::Assert { .. }
| TerminatorKind::DropAndReplace { .. }
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
| TerminatorKind::Resume | TerminatorKind::Resume
| TerminatorKind::Abort | TerminatorKind::Abort

View File

@ -1007,7 +1007,6 @@ fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, location: Loca
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::Drop { .. } | TerminatorKind::Drop { .. }
| TerminatorKind::DropAndReplace { .. }
| TerminatorKind::Yield { .. } | TerminatorKind::Yield { .. }
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
| TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseEdge { .. }

View File

@ -686,7 +686,6 @@ fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::Drop { .. } | TerminatorKind::Drop { .. }
| TerminatorKind::DropAndReplace { .. }
| TerminatorKind::Yield { .. } | TerminatorKind::Yield { .. }
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
| TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseEdge { .. }

View File

@ -822,7 +822,6 @@ pub(super) fn term_type(kind: &TerminatorKind<'_>) -> &'static str {
TerminatorKind::Return => "Return", TerminatorKind::Return => "Return",
TerminatorKind::Unreachable => "Unreachable", TerminatorKind::Unreachable => "Unreachable",
TerminatorKind::Drop { .. } => "Drop", TerminatorKind::Drop { .. } => "Drop",
TerminatorKind::DropAndReplace { .. } => "DropAndReplace",
TerminatorKind::Call { .. } => "Call", TerminatorKind::Call { .. } => "Call",
TerminatorKind::Assert { .. } => "Assert", TerminatorKind::Assert { .. } => "Assert",
TerminatorKind::Yield { .. } => "Yield", TerminatorKind::Yield { .. } => "Yield",

View File

@ -156,7 +156,6 @@ fn compute_basic_coverage_blocks(
| TerminatorKind::Resume | TerminatorKind::Resume
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::Drop { .. } | TerminatorKind::Drop { .. }
| TerminatorKind::DropAndReplace { .. }
| TerminatorKind::Call { .. } | TerminatorKind::Call { .. }
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
| TerminatorKind::Assert { .. } | TerminatorKind::Assert { .. }

View File

@ -850,7 +850,6 @@ pub(super) fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Sp
TerminatorKind::Unreachable // Unreachable blocks are not connected to the MIR CFG TerminatorKind::Unreachable // Unreachable blocks are not connected to the MIR CFG
| TerminatorKind::Assert { .. } | TerminatorKind::Assert { .. }
| TerminatorKind::Drop { .. } | TerminatorKind::Drop { .. }
| TerminatorKind::DropAndReplace { .. }
| TerminatorKind::SwitchInt { .. } | TerminatorKind::SwitchInt { .. }
// For `FalseEdge`, only the `real` branch is taken, so it is similar to a `Goto`. // For `FalseEdge`, only the `real` branch is taken, so it is similar to a `Goto`.
| TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseEdge { .. }

View File

@ -86,7 +86,6 @@ fn link(&mut self, from_block: BasicBlock, to_block: BasicBlock) {
TerminatorKind::Assert { ref mut target, .. } TerminatorKind::Assert { ref mut target, .. }
| TerminatorKind::Call { target: Some(ref mut target), .. } | TerminatorKind::Call { target: Some(ref mut target), .. }
| TerminatorKind::Drop { ref mut target, .. } | TerminatorKind::Drop { ref mut target, .. }
| TerminatorKind::DropAndReplace { ref mut target, .. }
| TerminatorKind::FalseEdge { real_target: ref mut target, .. } | TerminatorKind::FalseEdge { real_target: ref mut target, .. }
| TerminatorKind::FalseUnwind { real_target: ref mut target, .. } | TerminatorKind::FalseUnwind { real_target: ref mut target, .. }
| TerminatorKind::Goto { ref mut target } | TerminatorKind::Goto { ref mut target }
@ -184,7 +183,6 @@ fn debug_basic_blocks(mir_body: &Body<'_>) -> String {
TerminatorKind::Assert { target, .. } TerminatorKind::Assert { target, .. }
| TerminatorKind::Call { target: Some(target), .. } | TerminatorKind::Call { target: Some(target), .. }
| TerminatorKind::Drop { target, .. } | TerminatorKind::Drop { target, .. }
| TerminatorKind::DropAndReplace { target, .. }
| TerminatorKind::FalseEdge { real_target: target, .. } | TerminatorKind::FalseEdge { real_target: target, .. }
| TerminatorKind::FalseUnwind { real_target: target, .. } | TerminatorKind::FalseUnwind { real_target: target, .. }
| TerminatorKind::Goto { target } | TerminatorKind::Goto { target }

View File

@ -650,8 +650,7 @@ fn for_terminator<'tcx>(&mut self, terminator: &TerminatorKind<'tcx>) {
TerminatorKind::Drop { .. } => { TerminatorKind::Drop { .. } => {
// `Drop`s create a `&mut` and so are not considered // `Drop`s create a `&mut` and so are not considered
} }
TerminatorKind::DropAndReplace { .. } TerminatorKind::Yield { .. }
| TerminatorKind::Yield { .. }
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
| TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseEdge { .. }
| TerminatorKind::FalseUnwind { .. } => { | TerminatorKind::FalseUnwind { .. } => {

View File

@ -18,15 +18,14 @@
use rustc_target::abi::VariantIdx; use rustc_target::abi::VariantIdx;
use std::fmt; use std::fmt;
/// During MIR building, Drop and DropAndReplace terminators are inserted in every place where a drop may occur. /// During MIR building, Drop terminators are inserted in every place where a drop may occur.
/// However, in this phase, the presence of these terminators does not guarantee that a destructor will run, /// However, in this phase, the presence of these terminators does not guarantee that a destructor will run,
/// as the target of the drop may be uninitialized. /// as the target of the drop may be uninitialized.
/// In general, the compiler cannot determine at compile time whether a destructor will run or not. /// In general, the compiler cannot determine at compile time whether a destructor will run or not.
/// ///
/// At a high level, this pass refines Drop and DropAndReplace to only run the destructor if the /// At a high level, this pass refines Drop to only run the destructor if the
/// target is initialized. The way this is achievied is by inserting drop flags for every variable /// target is initialized. The way this is achievied is by inserting drop flags for every variable
/// that may be dropped, and then using those flags to determine whether a destructor should run. /// that may be dropped, and then using those flags to determine whether a destructor should run.
/// This pass also removes DropAndReplace, replacing it with a Drop paired with an assign statement.
/// Once this is complete, Drop terminators in the MIR correspond to a call to the "drop glue" or /// Once this is complete, Drop terminators in the MIR correspond to a call to the "drop glue" or
/// "drop shim" for the type of the dropped place. /// "drop shim" for the type of the dropped place.
/// ///
@ -121,8 +120,7 @@ fn remove_dead_unwinds<'tcx>(
.into_results_cursor(body); .into_results_cursor(body);
for (bb, bb_data) in body.basic_blocks.iter_enumerated() { for (bb, bb_data) in body.basic_blocks.iter_enumerated() {
let place = match bb_data.terminator().kind { let place = match bb_data.terminator().kind {
TerminatorKind::Drop { ref place, unwind: Some(_), .. } TerminatorKind::Drop { ref place, unwind: Some(_), .. } => {
| TerminatorKind::DropAndReplace { ref place, unwind: Some(_), .. } => {
und.derefer(place.as_ref(), body).unwrap_or(*place) und.derefer(place.as_ref(), body).unwrap_or(*place)
} }
_ => continue, _ => continue,
@ -343,8 +341,7 @@ fn collect_drop_flags(&mut self) {
} }
let terminator = data.terminator(); let terminator = data.terminator();
let place = match terminator.kind { let place = match terminator.kind {
TerminatorKind::Drop { ref place, .. } TerminatorKind::Drop { ref place, .. } => {
| TerminatorKind::DropAndReplace { ref place, .. } => {
self.un_derefer.derefer(place.as_ref(), self.body).unwrap_or(*place) self.un_derefer.derefer(place.as_ref(), self.body).unwrap_or(*place)
} }
_ => continue, _ => continue,
@ -441,103 +438,11 @@ fn elaborate_drops(&mut self) {
} }
} }
} }
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, _ => 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<BasicBlock>,
) {
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> { fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'tcx> {
Rvalue::Use(Operand::Constant(Box::new(Constant { Rvalue::Use(Operand::Constant(Box::new(Constant {
span, span,
@ -609,22 +514,12 @@ fn drop_flags_for_locs(&mut self) {
debug!("drop_flags_for_locs({:?})", data); debug!("drop_flags_for_locs({:?})", data);
for i in 0..(data.statements.len() + 1) { for i in 0..(data.statements.len() + 1) {
debug!("drop_flag_for_locs: stmt {}", i); debug!("drop_flag_for_locs: stmt {}", i);
let mut allow_initializations = true;
if i == data.statements.len() { if i == data.statements.len() {
match data.terminator().kind { match data.terminator().kind {
TerminatorKind::Drop { .. } => { TerminatorKind::Drop { .. } => {
// drop elaboration should handle that by itself // drop elaboration should handle that by itself
continue; 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;
}
TerminatorKind::Resume => { TerminatorKind::Resume => {
// It is possible for `Resume` to be patched // It is possible for `Resume` to be patched
// (in particular it can be patched to be replaced with // (in particular it can be patched to be replaced with
@ -641,11 +536,7 @@ fn drop_flags_for_locs(&mut self) {
self.body, self.body,
self.env, self.env,
loc, loc,
|path, ds| { |path, ds| self.set_drop_flag(loc, path, ds),
if ds == DropFlagState::Absent || allow_initializations {
self.set_drop_flag(loc, path, ds)
}
},
) )
} }

View File

@ -1199,7 +1199,6 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
// These may unwind. // These may unwind.
TerminatorKind::Drop { .. } TerminatorKind::Drop { .. }
| TerminatorKind::DropAndReplace { .. }
| TerminatorKind::Call { .. } | TerminatorKind::Call { .. }
| TerminatorKind::InlineAsm { .. } | TerminatorKind::InlineAsm { .. }
| TerminatorKind::Assert { .. } => return true, | TerminatorKind::Assert { .. } => return true,
@ -1691,7 +1690,6 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::Drop { .. } | TerminatorKind::Drop { .. }
| TerminatorKind::DropAndReplace { .. }
| TerminatorKind::Assert { .. } | TerminatorKind::Assert { .. }
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
| TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseEdge { .. }

View File

@ -453,9 +453,7 @@ fn check_mir_body(
checker.visit_basic_block_data(bb, blk); checker.visit_basic_block_data(bb, blk);
let term = blk.terminator(); let term = blk.terminator();
if let TerminatorKind::Drop { ref place, target, unwind } if let TerminatorKind::Drop { ref place, target, unwind } = term.kind {
| TerminatorKind::DropAndReplace { ref place, target, unwind, .. } = term.kind
{
work_list.push(target); work_list.push(target);
// If the place doesn't actually need dropping, treat it like a regular goto. // If the place doesn't actually need dropping, treat it like a regular goto.
@ -815,8 +813,7 @@ fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
let tcx = self.tcx; let tcx = self.tcx;
match terminator.kind { match terminator.kind {
TerminatorKind::Drop { ref place, unwind, .. } TerminatorKind::Drop { ref place, unwind, .. } => {
| TerminatorKind::DropAndReplace { ref place, unwind, .. } => {
// If the place doesn't actually need dropping, treat it like a regular goto. // 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); let ty = self.instance.subst_mir(tcx, &place.ty(self.callee_body, tcx).ty);
if ty.needs_drop(tcx, self.param_env) { if ty.needs_drop(tcx, self.param_env) {
@ -1120,8 +1117,7 @@ fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, loc: Location)
*tgt = self.map_block(*tgt); *tgt = self.map_block(*tgt);
} }
} }
TerminatorKind::Drop { ref mut target, ref mut unwind, .. } TerminatorKind::Drop { ref mut target, ref mut unwind, .. } => {
| TerminatorKind::DropAndReplace { ref mut target, ref mut unwind, .. } => {
*target = self.map_block(*target); *target = self.map_block(*target);
*unwind = self.map_unwind(*unwind); *unwind = self.map_unwind(*unwind);
} }

View File

@ -75,7 +75,6 @@ fn is_nop_landing_pad(
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::Call { .. } | TerminatorKind::Call { .. }
| TerminatorKind::Assert { .. } | TerminatorKind::Assert { .. }
| TerminatorKind::DropAndReplace { .. }
| TerminatorKind::Drop { .. } | TerminatorKind::Drop { .. }
| TerminatorKind::InlineAsm { .. } => false, | TerminatorKind::InlineAsm { .. } => false,
} }

View File

@ -1,5 +1,5 @@
use rustc_index::bit_set::ChunkedBitSet; 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::subst::SubstsRef;
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, VariantDef}; use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, VariantDef};
use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
@ -8,7 +8,7 @@
use crate::MirPass; use crate::MirPass;
/// Removes `Drop` and `DropAndReplace` terminators whose target is known to be uninitialized at /// Removes `Drop` terminators whose target is known to be uninitialized at
/// that point. /// that point.
/// ///
/// This is redundant with drop elaboration, but we need to do it prior to const-checking, and /// This is redundant with drop elaboration, but we need to do it prior to const-checking, and
@ -37,8 +37,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let mut to_remove = vec![]; let mut to_remove = vec![];
for (bb, block) in body.basic_blocks.iter_enumerated() { for (bb, block) in body.basic_blocks.iter_enumerated() {
let terminator = block.terminator(); let terminator = block.terminator();
let (TerminatorKind::Drop { place, .. } | TerminatorKind::DropAndReplace { place, .. }) let TerminatorKind::Drop { place, .. } = &terminator.kind
= &terminator.kind
else { continue }; else { continue };
maybe_inits.seek_before_primary_effect(body.terminator_loc(bb)); maybe_inits.seek_before_primary_effect(body.terminator_loc(bb));
@ -64,24 +63,12 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
for bb in to_remove { for bb in to_remove {
let block = &mut body.basic_blocks_mut()[bb]; let block = &mut body.basic_blocks_mut()[bb];
let (TerminatorKind::Drop { target, .. } | TerminatorKind::DropAndReplace { target, .. }) let TerminatorKind::Drop { target, .. }
= &block.terminator().kind = &block.terminator().kind
else { unreachable!() }; else { unreachable!() };
// Replace block terminator with `Goto`. // Replace block terminator with `Goto`.
let target = *target; block.terminator_mut().kind = TerminatorKind::Goto { target: *target };
let old_terminator_kind = 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)))),
});
}
} }
} }
} }

View File

@ -108,7 +108,6 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize {
// The following terminators are not allowed // The following terminators are not allowed
TerminatorKind::Resume TerminatorKind::Resume
| TerminatorKind::Drop { .. } | TerminatorKind::Drop { .. }
| TerminatorKind::DropAndReplace { .. }
| TerminatorKind::Call { .. } | TerminatorKind::Call { .. }
| TerminatorKind::Assert { .. } | TerminatorKind::Assert { .. }
| TerminatorKind::FalseUnwind { .. } | TerminatorKind::FalseUnwind { .. }
@ -170,7 +169,6 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize {
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop
| TerminatorKind::Assert { .. } | TerminatorKind::Assert { .. }
| TerminatorKind::DropAndReplace { .. }
| TerminatorKind::FalseUnwind { .. } | TerminatorKind::FalseUnwind { .. }
| TerminatorKind::Drop { .. } | TerminatorKind::Drop { .. }
| TerminatorKind::Call { .. } | TerminatorKind::Call { .. }

View File

@ -808,8 +808,7 @@ fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Loc
let callee_ty = self.monomorphize(callee_ty); let callee_ty = self.monomorphize(callee_ty);
visit_fn_use(self.tcx, callee_ty, true, source, &mut self.output) visit_fn_use(self.tcx, callee_ty, true, source, &mut self.output)
} }
mir::TerminatorKind::Drop { ref place, .. } mir::TerminatorKind::Drop { ref place, .. } => {
| mir::TerminatorKind::DropAndReplace { ref place, .. } => {
let ty = place.ty(self.body, self.tcx).ty; let ty = place.ty(self.body, self.tcx).ty;
let ty = self.monomorphize(ty); let ty = self.monomorphize(ty);
visit_drop_use(self.tcx, ty, true, source, self.output); visit_drop_use(self.tcx, ty, true, source, self.output);

View File

@ -227,7 +227,7 @@
//! are no resume and abort terminators, and terminators that might unwind do not have any way to //! are no resume and abort terminators, and terminators that might unwind do not have any way to
//! indicate the unwind block. //! indicate the unwind block.
//! //!
//! - [`Goto`], [`Return`], [`Unreachable`], [`Drop`](Drop()), and [`DropAndReplace`] have associated functions. //! - [`Goto`], [`Return`], [`Unreachable`] and [`Drop`](Drop()) have associated functions.
//! - `match some_int_operand` becomes a `SwitchInt`. Each arm should be `literal => basic_block` //! - `match some_int_operand` becomes a `SwitchInt`. Each arm should be `literal => basic_block`
//! - The exception is the last arm, which must be `_ => basic_block` and corresponds to the //! - The exception is the last arm, which must be `_ => basic_block` and corresponds to the
//! otherwise branch. //! otherwise branch.
@ -259,7 +259,6 @@ pub fn $($sig)* { panic!() }
define!("mir_goto", fn Goto(destination: BasicBlock) -> BasicBlock); define!("mir_goto", fn Goto(destination: BasicBlock) -> BasicBlock);
define!("mir_unreachable", fn Unreachable() -> BasicBlock); define!("mir_unreachable", fn Unreachable() -> BasicBlock);
define!("mir_drop", fn Drop<T>(place: T, goto: BasicBlock)); define!("mir_drop", fn Drop<T>(place: T, goto: BasicBlock));
define!("mir_drop_and_replace", fn DropAndReplace<T>(place: T, value: T, goto: BasicBlock));
define!("mir_call", fn Call<T>(place: T, goto: BasicBlock, call: T)); define!("mir_call", fn Call<T>(place: T, goto: BasicBlock, call: T));
define!("mir_storage_live", fn StorageLive<T>(local: T)); define!("mir_storage_live", fn StorageLive<T>(local: T));
define!("mir_storage_dead", fn StorageDead<T>(local: T)); define!("mir_storage_dead", fn StorageDead<T>(local: T));

View File

@ -299,10 +299,6 @@ fn check_terminator<'tcx>(
| TerminatorKind::Unreachable => Ok(()), | TerminatorKind::Unreachable => Ok(()),
TerminatorKind::Drop { place, .. } => check_place(tcx, *place, span, body), 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::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body), TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body),

View File

@ -4,10 +4,11 @@ fn drop_first(_1: WriteOnDrop<'_>, _2: WriteOnDrop<'_>) -> () {
let mut _0: (); // return place in scope 0 at $DIR/terminators.rs:+0:59: +0:59 let mut _0: (); // return place in scope 0 at $DIR/terminators.rs:+0:59: +0:59
bb0: { bb0: {
replace(_1 <- move _2) -> bb1; // scope 0 at $DIR/terminators.rs:+3:13: +3:49 drop(_1) -> bb1; // scope 0 at $DIR/terminators.rs:+3:13: +3:30
} }
bb1: { bb1: {
return; // scope 0 at $DIR/terminators.rs:+7:13: +7:21 _1 = move _2; // scope 0 at $DIR/terminators.rs:+7:13: +7:24
return; // scope 0 at $DIR/terminators.rs:+8:13: +8:21
} }
} }

View File

@ -48,10 +48,11 @@ fn drop(&mut self) {
fn drop_first<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) { fn drop_first<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) {
mir!( mir!(
{ {
DropAndReplace(a, Move(b), retblock) Drop(a, retblock)
} }
retblock = { retblock = {
a = Move(b);
Return() Return()
} }
) )