Refactor call terminator to always hold a destination place
This commit is contained in:
parent
222c5724ec
commit
09b0936db2
67 changed files with 422 additions and 412 deletions
|
@ -50,12 +50,7 @@ impl AddCallGuards {
|
|||
for block in body.basic_blocks_mut() {
|
||||
match block.terminator {
|
||||
Some(Terminator {
|
||||
kind:
|
||||
TerminatorKind::Call {
|
||||
destination: Some((_, ref mut destination)),
|
||||
cleanup,
|
||||
..
|
||||
},
|
||||
kind: TerminatorKind::Call { target: Some(ref mut destination), cleanup, .. },
|
||||
source_info,
|
||||
}) if pred_count[*destination] > 1
|
||||
&& (cleanup.is_some() || self == &AllCallEdges) =>
|
||||
|
|
|
@ -130,11 +130,11 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
|
|||
.iter_mut()
|
||||
.filter_map(|block_data| {
|
||||
match block_data.terminator().kind {
|
||||
TerminatorKind::Call { destination: Some(ref destination), .. }
|
||||
if needs_retag(&destination.0) =>
|
||||
TerminatorKind::Call { target: Some(target), destination, .. }
|
||||
if needs_retag(&destination) =>
|
||||
{
|
||||
// Remember the return destination for later
|
||||
Some((block_data.terminator().source_info, destination.0, destination.1))
|
||||
Some((block_data.terminator().source_info, destination, target))
|
||||
}
|
||||
|
||||
// `Drop` is also a call, but it doesn't return anything so we are good.
|
||||
|
|
|
@ -200,7 +200,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
|
|||
_instance: ty::Instance<'tcx>,
|
||||
_abi: Abi,
|
||||
_args: &[OpTy<'tcx>],
|
||||
_ret: Option<(&PlaceTy<'tcx>, BasicBlock)>,
|
||||
_destination: &PlaceTy<'tcx>,
|
||||
_target: Option<BasicBlock>,
|
||||
_unwind: StackPopUnwind,
|
||||
) -> InterpResult<'tcx, Option<(&'mir Body<'tcx>, ty::Instance<'tcx>)>> {
|
||||
Ok(None)
|
||||
|
@ -210,7 +211,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
|
|||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
_instance: ty::Instance<'tcx>,
|
||||
_args: &[OpTy<'tcx>],
|
||||
_ret: Option<(&PlaceTy<'tcx>, BasicBlock)>,
|
||||
_destination: &PlaceTy<'tcx>,
|
||||
_target: Option<BasicBlock>,
|
||||
_unwind: StackPopUnwind,
|
||||
) -> InterpResult<'tcx> {
|
||||
throw_machine_stop_str!("calling intrinsics isn't supported in ConstProp")
|
||||
|
@ -384,24 +386,22 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
|||
ConstPropMachine::new(only_propagate_inside_block_locals, can_const_prop),
|
||||
);
|
||||
|
||||
let ret = ecx
|
||||
let ret_layout = ecx
|
||||
.layout_of(EarlyBinder(body.return_ty()).subst(tcx, substs))
|
||||
.ok()
|
||||
// Don't bother allocating memory for ZST types which have no values
|
||||
// or for large values.
|
||||
.filter(|ret_layout| {
|
||||
!ret_layout.is_zst() && ret_layout.size < Size::from_bytes(MAX_ALLOC_LIMIT)
|
||||
})
|
||||
.map(|ret_layout| {
|
||||
ecx.allocate(ret_layout, MemoryKind::Stack)
|
||||
.expect("couldn't perform small allocation")
|
||||
.into()
|
||||
});
|
||||
// Don't bother allocating memory for large values.
|
||||
.filter(|ret_layout| ret_layout.size < Size::from_bytes(MAX_ALLOC_LIMIT))
|
||||
.unwrap_or_else(|| ecx.layout_of(tcx.types.unit).unwrap());
|
||||
|
||||
let ret = ecx
|
||||
.allocate(ret_layout, MemoryKind::Stack)
|
||||
.expect("couldn't perform small allocation")
|
||||
.into();
|
||||
|
||||
ecx.push_stack_frame(
|
||||
Instance::new(def_id, substs),
|
||||
dummy_body,
|
||||
ret.as_ref(),
|
||||
&ret,
|
||||
StackPopCleanup::Root { cleanup: false },
|
||||
)
|
||||
.expect("failed to push initial stack frame");
|
||||
|
|
|
@ -192,7 +192,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
|
|||
_instance: ty::Instance<'tcx>,
|
||||
_abi: Abi,
|
||||
_args: &[OpTy<'tcx>],
|
||||
_ret: Option<(&PlaceTy<'tcx>, BasicBlock)>,
|
||||
_destination: &PlaceTy<'tcx>,
|
||||
_target: Option<BasicBlock>,
|
||||
_unwind: StackPopUnwind,
|
||||
) -> InterpResult<'tcx, Option<(&'mir Body<'tcx>, ty::Instance<'tcx>)>> {
|
||||
Ok(None)
|
||||
|
@ -202,7 +203,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
|
|||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
_instance: ty::Instance<'tcx>,
|
||||
_args: &[OpTy<'tcx>],
|
||||
_ret: Option<(&PlaceTy<'tcx>, BasicBlock)>,
|
||||
_destination: &PlaceTy<'tcx>,
|
||||
_target: Option<BasicBlock>,
|
||||
_unwind: StackPopUnwind,
|
||||
) -> InterpResult<'tcx> {
|
||||
throw_machine_stop_str!("calling intrinsics isn't supported in ConstProp")
|
||||
|
@ -377,24 +379,22 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
|||
ConstPropMachine::new(only_propagate_inside_block_locals, can_const_prop),
|
||||
);
|
||||
|
||||
let ret = ecx
|
||||
let ret_layout = ecx
|
||||
.layout_of(EarlyBinder(body.return_ty()).subst(tcx, substs))
|
||||
.ok()
|
||||
// Don't bother allocating memory for ZST types which have no values
|
||||
// or for large values.
|
||||
.filter(|ret_layout| {
|
||||
!ret_layout.is_zst() && ret_layout.size < Size::from_bytes(MAX_ALLOC_LIMIT)
|
||||
})
|
||||
.map(|ret_layout| {
|
||||
ecx.allocate(ret_layout, MemoryKind::Stack)
|
||||
.expect("couldn't perform small allocation")
|
||||
.into()
|
||||
});
|
||||
// Don't bother allocating memory for large values.
|
||||
.filter(|ret_layout| ret_layout.size < Size::from_bytes(MAX_ALLOC_LIMIT))
|
||||
.unwrap_or_else(|| ecx.layout_of(tcx.types.unit).unwrap());
|
||||
|
||||
let ret = ecx
|
||||
.allocate(ret_layout, MemoryKind::Stack)
|
||||
.expect("couldn't perform small allocation")
|
||||
.into();
|
||||
|
||||
ecx.push_stack_frame(
|
||||
Instance::new(def_id, substs),
|
||||
dummy_body,
|
||||
ret.as_ref(),
|
||||
&ret,
|
||||
StackPopCleanup::Root { cleanup: false },
|
||||
)
|
||||
.expect("failed to push initial stack frame");
|
||||
|
|
|
@ -84,7 +84,7 @@ impl<'tcx> MockBlocks<'tcx> {
|
|||
fn link(&mut self, from_block: BasicBlock, to_block: BasicBlock) {
|
||||
match self.blocks[from_block].terminator_mut().kind {
|
||||
TerminatorKind::Assert { ref mut target, .. }
|
||||
| TerminatorKind::Call { destination: Some((_, ref mut target)), .. }
|
||||
| TerminatorKind::Call { target: Some(ref mut target), .. }
|
||||
| TerminatorKind::Drop { ref mut target, .. }
|
||||
| TerminatorKind::DropAndReplace { ref mut target, .. }
|
||||
| TerminatorKind::FalseEdge { real_target: ref mut target, .. }
|
||||
|
@ -139,7 +139,8 @@ impl<'tcx> MockBlocks<'tcx> {
|
|||
TerminatorKind::Call {
|
||||
func: Operand::Copy(self.dummy_place.clone()),
|
||||
args: vec![],
|
||||
destination: Some((self.dummy_place.clone(), TEMP_BLOCK)),
|
||||
destination: self.dummy_place.clone(),
|
||||
target: Some(TEMP_BLOCK),
|
||||
cleanup: None,
|
||||
from_hir_call: false,
|
||||
fn_span: DUMMY_SP,
|
||||
|
@ -182,7 +183,7 @@ fn debug_basic_blocks<'tcx>(mir_body: &Body<'tcx>) -> String {
|
|||
let sp = format!("(span:{},{})", span.lo().to_u32(), span.hi().to_u32());
|
||||
match kind {
|
||||
TerminatorKind::Assert { target, .. }
|
||||
| TerminatorKind::Call { destination: Some((_, target)), .. }
|
||||
| TerminatorKind::Call { target: Some(target), .. }
|
||||
| TerminatorKind::Drop { target, .. }
|
||||
| TerminatorKind::DropAndReplace { target, .. }
|
||||
| TerminatorKind::FalseEdge { real_target: target, .. }
|
||||
|
|
|
@ -575,7 +575,8 @@ impl<'a> Conflicts<'a> {
|
|||
TerminatorKind::Call {
|
||||
func,
|
||||
args,
|
||||
destination: Some((dest_place, _)),
|
||||
destination,
|
||||
target: _,
|
||||
cleanup: _,
|
||||
from_hir_call: _,
|
||||
fn_span: _,
|
||||
|
@ -583,9 +584,9 @@ impl<'a> Conflicts<'a> {
|
|||
// No arguments may overlap with the destination.
|
||||
for arg in args.iter().chain(Some(func)) {
|
||||
if let Some(place) = arg.place() {
|
||||
if !place.is_indirect() && !dest_place.is_indirect() {
|
||||
if !place.is_indirect() && !destination.is_indirect() {
|
||||
self.record_local_conflict(
|
||||
dest_place.local,
|
||||
destination.local,
|
||||
place.local,
|
||||
"call dest/arg overlap",
|
||||
);
|
||||
|
@ -691,7 +692,6 @@ impl<'a> Conflicts<'a> {
|
|||
}
|
||||
|
||||
TerminatorKind::Goto { .. }
|
||||
| TerminatorKind::Call { destination: None, .. }
|
||||
| TerminatorKind::SwitchInt { .. }
|
||||
| TerminatorKind::Resume
|
||||
| TerminatorKind::Abort
|
||||
|
|
|
@ -494,15 +494,13 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
|||
fn drop_flags_for_fn_rets(&mut self) {
|
||||
for (bb, data) in self.body.basic_blocks().iter_enumerated() {
|
||||
if let TerminatorKind::Call {
|
||||
destination: Some((ref place, tgt)),
|
||||
cleanup: Some(_),
|
||||
..
|
||||
destination, target: Some(tgt), cleanup: Some(_), ..
|
||||
} = data.terminator().kind
|
||||
{
|
||||
assert!(!self.patch.is_patched(bb));
|
||||
|
||||
let loc = Location { block: tgt, statement_index: 0 };
|
||||
let path = self.move_data().rev_lookup.find(place.as_ref());
|
||||
let path = self.move_data().rev_lookup.find(destination.as_ref());
|
||||
on_lookup_result_bits(self.tcx, self.body, self.move_data(), path, |child| {
|
||||
self.set_drop_flag(loc, child, DropFlagState::Present)
|
||||
});
|
||||
|
@ -576,14 +574,13 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
|||
// There may be a critical edge after this call,
|
||||
// so mark the return as initialized *before* the
|
||||
// call.
|
||||
if let TerminatorKind::Call {
|
||||
destination: Some((ref place, _)), cleanup: None, ..
|
||||
} = data.terminator().kind
|
||||
if let TerminatorKind::Call { destination, target: Some(_), cleanup: None, .. } =
|
||||
data.terminator().kind
|
||||
{
|
||||
assert!(!self.patch.is_patched(bb));
|
||||
|
||||
let loc = Location { block: bb, statement_index: data.statements.len() };
|
||||
let path = self.move_data().rev_lookup.find(place.as_ref());
|
||||
let path = self.move_data().rev_lookup.find(destination.as_ref());
|
||||
on_lookup_result_bits(self.tcx, self.body, self.move_data(), path, |child| {
|
||||
self.set_drop_flag(loc, child, DropFlagState::Present)
|
||||
});
|
||||
|
|
|
@ -37,6 +37,7 @@ impl<'tcx> Visitor<'tcx> for FunctionItemRefChecker<'_, 'tcx> {
|
|||
func,
|
||||
args,
|
||||
destination: _,
|
||||
target: _,
|
||||
cleanup: _,
|
||||
from_hir_call: _,
|
||||
fn_span: _,
|
||||
|
|
|
@ -1459,12 +1459,13 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
|
|||
TerminatorKind::Call {
|
||||
func,
|
||||
args,
|
||||
destination: Some((dest, _)),
|
||||
destination,
|
||||
target: Some(_),
|
||||
cleanup: _,
|
||||
from_hir_call: _,
|
||||
fn_span: _,
|
||||
} => {
|
||||
self.check_assigned_place(*dest, |this| {
|
||||
self.check_assigned_place(*destination, |this| {
|
||||
this.visit_operand(func, location);
|
||||
for arg in args {
|
||||
this.visit_operand(arg, location);
|
||||
|
|
|
@ -248,7 +248,7 @@ impl<'tcx> Inliner<'tcx> {
|
|||
) -> Option<CallSite<'tcx>> {
|
||||
// Only consider direct calls to functions
|
||||
let terminator = bb_data.terminator();
|
||||
if let TerminatorKind::Call { ref func, ref destination, .. } = terminator.kind {
|
||||
if let TerminatorKind::Call { ref func, target, .. } = terminator.kind {
|
||||
let func_ty = func.ty(caller_body, self.tcx);
|
||||
if let ty::FnDef(def_id, substs) = *func_ty.kind() {
|
||||
// To resolve an instance its substs have to be fully normalized.
|
||||
|
@ -266,7 +266,7 @@ impl<'tcx> Inliner<'tcx> {
|
|||
callee,
|
||||
fn_sig,
|
||||
block: bb,
|
||||
target: destination.map(|(_, target)| target),
|
||||
target,
|
||||
source_info: terminator.source_info,
|
||||
});
|
||||
}
|
||||
|
@ -395,7 +395,7 @@ impl<'tcx> Inliner<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
TerminatorKind::Unreachable | TerminatorKind::Call { destination: None, .. }
|
||||
TerminatorKind::Unreachable | TerminatorKind::Call { target: None, .. }
|
||||
if first_block =>
|
||||
{
|
||||
// If the function always diverges, don't inline
|
||||
|
@ -512,27 +512,22 @@ impl<'tcx> Inliner<'tcx> {
|
|||
false
|
||||
}
|
||||
|
||||
let dest = if let Some((destination_place, _)) = destination {
|
||||
if dest_needs_borrow(destination_place) {
|
||||
trace!("creating temp for return destination");
|
||||
let dest = Rvalue::Ref(
|
||||
self.tcx.lifetimes.re_erased,
|
||||
BorrowKind::Mut { allow_two_phase_borrow: false },
|
||||
destination_place,
|
||||
);
|
||||
let dest_ty = dest.ty(caller_body, self.tcx);
|
||||
let temp = Place::from(self.new_call_temp(caller_body, &callsite, dest_ty));
|
||||
caller_body[callsite.block].statements.push(Statement {
|
||||
source_info: callsite.source_info,
|
||||
kind: StatementKind::Assign(Box::new((temp, dest))),
|
||||
});
|
||||
self.tcx.mk_place_deref(temp)
|
||||
} else {
|
||||
destination_place
|
||||
}
|
||||
let dest = if dest_needs_borrow(destination) {
|
||||
trace!("creating temp for return destination");
|
||||
let dest = Rvalue::Ref(
|
||||
self.tcx.lifetimes.re_erased,
|
||||
BorrowKind::Mut { allow_two_phase_borrow: false },
|
||||
destination,
|
||||
);
|
||||
let dest_ty = dest.ty(caller_body, self.tcx);
|
||||
let temp = Place::from(self.new_call_temp(caller_body, &callsite, dest_ty));
|
||||
caller_body[callsite.block].statements.push(Statement {
|
||||
source_info: callsite.source_info,
|
||||
kind: StatementKind::Assign(Box::new((temp, dest))),
|
||||
});
|
||||
self.tcx.mk_place_deref(temp)
|
||||
} else {
|
||||
trace!("creating temp for return place");
|
||||
Place::from(self.new_call_temp(caller_body, &callsite, callee_body.return_ty()))
|
||||
destination
|
||||
};
|
||||
|
||||
// Copy the arguments if needed.
|
||||
|
@ -914,8 +909,8 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
|
|||
*unwind = self.cleanup_block;
|
||||
}
|
||||
}
|
||||
TerminatorKind::Call { ref mut destination, ref mut cleanup, .. } => {
|
||||
if let Some((_, ref mut tgt)) = *destination {
|
||||
TerminatorKind::Call { ref mut target, ref mut cleanup, .. } => {
|
||||
if let Some(ref mut tgt) = *target {
|
||||
*tgt = self.map_block(*tgt);
|
||||
}
|
||||
if let Some(tgt) = *cleanup {
|
||||
|
|
|
@ -141,7 +141,7 @@ impl<'tcx> InstCombineContext<'tcx, '_> {
|
|||
terminator: &mut Terminator<'tcx>,
|
||||
statements: &mut Vec<Statement<'tcx>>,
|
||||
) {
|
||||
let TerminatorKind::Call { func, args, destination, .. } = &mut terminator.kind
|
||||
let TerminatorKind::Call { func, args, destination, target, .. } = &mut terminator.kind
|
||||
else { return };
|
||||
|
||||
// It's definitely not a clone if there are multiple arguments
|
||||
|
@ -149,7 +149,7 @@ impl<'tcx> InstCombineContext<'tcx, '_> {
|
|||
return;
|
||||
}
|
||||
|
||||
let Some((destination_place, destination_block)) = *destination
|
||||
let Some(destination_block) = *target
|
||||
else { return };
|
||||
|
||||
// Only bother looking more if it's easy to know what we're calling
|
||||
|
@ -193,7 +193,7 @@ impl<'tcx> InstCombineContext<'tcx, '_> {
|
|||
statements.push(Statement {
|
||||
source_info: terminator.source_info,
|
||||
kind: StatementKind::Assign(Box::new((
|
||||
destination_place,
|
||||
*destination,
|
||||
Rvalue::Use(Operand::Copy(
|
||||
arg_place.project_deeper(&[ProjectionElem::Deref], self.tcx),
|
||||
)),
|
||||
|
|
|
@ -14,7 +14,9 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
|
|||
let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
|
||||
for block in basic_blocks {
|
||||
let terminator = block.terminator.as_mut().unwrap();
|
||||
if let TerminatorKind::Call { func, args, destination, .. } = &mut terminator.kind {
|
||||
if let TerminatorKind::Call { func, args, destination, target, .. } =
|
||||
&mut terminator.kind
|
||||
{
|
||||
let func_ty = func.ty(local_decls, tcx);
|
||||
let Some((intrinsic_name, substs)) = resolve_rust_intrinsic(tcx, func_ty) else {
|
||||
continue;
|
||||
|
@ -24,11 +26,11 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
|
|||
terminator.kind = TerminatorKind::Unreachable;
|
||||
}
|
||||
sym::forget => {
|
||||
if let Some((destination, target)) = *destination {
|
||||
if let Some(target) = *target {
|
||||
block.statements.push(Statement {
|
||||
source_info: terminator.source_info,
|
||||
kind: StatementKind::Assign(Box::new((
|
||||
destination,
|
||||
*destination,
|
||||
Rvalue::Use(Operand::Constant(Box::new(Constant {
|
||||
span: terminator.source_info.span,
|
||||
user_ty: None,
|
||||
|
@ -40,7 +42,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
|
|||
}
|
||||
}
|
||||
sym::copy_nonoverlapping => {
|
||||
let target = destination.unwrap().1;
|
||||
let target = target.unwrap();
|
||||
let mut args = args.drain(..);
|
||||
block.statements.push(Statement {
|
||||
source_info: terminator.source_info,
|
||||
|
@ -61,7 +63,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
|
|||
terminator.kind = TerminatorKind::Goto { target };
|
||||
}
|
||||
sym::wrapping_add | sym::wrapping_sub | sym::wrapping_mul => {
|
||||
if let Some((destination, target)) = *destination {
|
||||
if let Some(target) = *target {
|
||||
let lhs;
|
||||
let rhs;
|
||||
{
|
||||
|
@ -78,7 +80,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
|
|||
block.statements.push(Statement {
|
||||
source_info: terminator.source_info,
|
||||
kind: StatementKind::Assign(Box::new((
|
||||
destination,
|
||||
*destination,
|
||||
Rvalue::BinaryOp(bin_op, Box::new((lhs, rhs))),
|
||||
))),
|
||||
});
|
||||
|
@ -91,7 +93,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
|
|||
// during codegen. Issue #35310.
|
||||
}
|
||||
sym::size_of | sym::min_align_of => {
|
||||
if let Some((destination, target)) = *destination {
|
||||
if let Some(target) = *target {
|
||||
let tp_ty = substs.type_at(0);
|
||||
let null_op = match intrinsic_name {
|
||||
sym::size_of => NullOp::SizeOf,
|
||||
|
@ -101,7 +103,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
|
|||
block.statements.push(Statement {
|
||||
source_info: terminator.source_info,
|
||||
kind: StatementKind::Assign(Box::new((
|
||||
destination,
|
||||
*destination,
|
||||
Rvalue::NullaryOp(null_op, tp_ty),
|
||||
))),
|
||||
});
|
||||
|
@ -109,14 +111,12 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
|
|||
}
|
||||
}
|
||||
sym::discriminant_value => {
|
||||
if let (Some((destination, target)), Some(arg)) =
|
||||
(*destination, args[0].place())
|
||||
{
|
||||
if let (Some(target), Some(arg)) = (*target, args[0].place()) {
|
||||
let arg = tcx.mk_place_deref(arg);
|
||||
block.statements.push(Statement {
|
||||
source_info: terminator.source_info,
|
||||
kind: StatementKind::Assign(Box::new((
|
||||
destination,
|
||||
*destination,
|
||||
Rvalue::Discriminant(arg),
|
||||
))),
|
||||
});
|
||||
|
|
|
@ -52,7 +52,8 @@ fn lower_slice_len_call<'tcx>(
|
|||
TerminatorKind::Call {
|
||||
func,
|
||||
args,
|
||||
destination: Some((dest, bb)),
|
||||
destination,
|
||||
target: Some(bb),
|
||||
cleanup: None,
|
||||
from_hir_call: true,
|
||||
..
|
||||
|
@ -73,7 +74,8 @@ fn lower_slice_len_call<'tcx>(
|
|||
// make new RValue for Len
|
||||
let deref_arg = tcx.mk_place_deref(arg);
|
||||
let r_value = Rvalue::Len(deref_arg);
|
||||
let len_statement_kind = StatementKind::Assign(Box::new((*dest, r_value)));
|
||||
let len_statement_kind =
|
||||
StatementKind::Assign(Box::new((*destination, r_value)));
|
||||
let add_statement =
|
||||
Statement { kind: len_statement_kind, source_info: terminator.source_info };
|
||||
|
||||
|
|
|
@ -450,7 +450,8 @@ impl<'tcx> CloneShimBuilder<'tcx> {
|
|||
TerminatorKind::Call {
|
||||
func,
|
||||
args: vec![Operand::Move(ref_loc)],
|
||||
destination: Some((dest, next)),
|
||||
destination: dest,
|
||||
target: Some(next),
|
||||
cleanup: Some(cleanup),
|
||||
from_hir_call: true,
|
||||
fn_span: self.span,
|
||||
|
@ -676,7 +677,8 @@ fn build_call_shim<'tcx>(
|
|||
TerminatorKind::Call {
|
||||
func: callee,
|
||||
args,
|
||||
destination: Some((Place::return_place(), BasicBlock::new(1))),
|
||||
destination: Place::return_place(),
|
||||
target: Some(BasicBlock::new(1)),
|
||||
cleanup: if let Some(Adjustment::RefMut) = rcvr_adjustment {
|
||||
Some(BasicBlock::new(3))
|
||||
} else {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue