Use let else to reduce indentation
This commit is contained in:
parent
d19980e1ce
commit
525a64fa81
@ -541,142 +541,141 @@ fn inline_call(
|
||||
mut callee_body: Body<'tcx>,
|
||||
) {
|
||||
let terminator = caller_body[callsite.block].terminator.take().unwrap();
|
||||
match terminator.kind {
|
||||
TerminatorKind::Call { args, destination, unwind, .. } => {
|
||||
// If the call is something like `a[*i] = f(i)`, where
|
||||
// `i : &mut usize`, then just duplicating the `a[*i]`
|
||||
// Place could result in two different locations if `f`
|
||||
// writes to `i`. To prevent this we need to create a temporary
|
||||
// borrow of the place and pass the destination as `*temp` instead.
|
||||
fn dest_needs_borrow(place: Place<'_>) -> bool {
|
||||
for elem in place.projection.iter() {
|
||||
match elem {
|
||||
ProjectionElem::Deref | ProjectionElem::Index(_) => return true,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
let TerminatorKind::Call { args, destination, unwind, .. } = terminator.kind else {
|
||||
bug!("unexpected terminator kind {:?}", terminator.kind);
|
||||
};
|
||||
|
||||
false
|
||||
// If the call is something like `a[*i] = f(i)`, where
|
||||
// `i : &mut usize`, then just duplicating the `a[*i]`
|
||||
// Place could result in two different locations if `f`
|
||||
// writes to `i`. To prevent this we need to create a temporary
|
||||
// borrow of the place and pass the destination as `*temp` instead.
|
||||
fn dest_needs_borrow(place: Place<'_>) -> bool {
|
||||
for elem in place.projection.iter() {
|
||||
match elem {
|
||||
ProjectionElem::Deref | ProjectionElem::Index(_) => return true,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let dest = if dest_needs_borrow(destination) {
|
||||
trace!("creating temp for return destination");
|
||||
let dest = Rvalue::Ref(
|
||||
self.tcx.lifetimes.re_erased,
|
||||
BorrowKind::Mut { kind: MutBorrowKind::Default },
|
||||
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 {
|
||||
destination
|
||||
};
|
||||
|
||||
// Always create a local to hold the destination, as `RETURN_PLACE` may appear
|
||||
// where a full `Place` is not allowed.
|
||||
let (remap_destination, destination_local) = if let Some(d) = dest.as_local() {
|
||||
(false, d)
|
||||
} else {
|
||||
(
|
||||
true,
|
||||
self.new_call_temp(
|
||||
caller_body,
|
||||
&callsite,
|
||||
destination.ty(caller_body, self.tcx).ty,
|
||||
),
|
||||
)
|
||||
};
|
||||
|
||||
// Copy the arguments if needed.
|
||||
let args: Vec<_> = self.make_call_args(args, &callsite, caller_body, &callee_body);
|
||||
|
||||
let mut integrator = Integrator {
|
||||
args: &args,
|
||||
new_locals: Local::new(caller_body.local_decls.len())..,
|
||||
new_scopes: SourceScope::new(caller_body.source_scopes.len())..,
|
||||
new_blocks: BasicBlock::new(caller_body.basic_blocks.len())..,
|
||||
destination: destination_local,
|
||||
callsite_scope: caller_body.source_scopes[callsite.source_info.scope].clone(),
|
||||
callsite,
|
||||
cleanup_block: unwind,
|
||||
in_cleanup_block: false,
|
||||
tcx: self.tcx,
|
||||
always_live_locals: BitSet::new_filled(callee_body.local_decls.len()),
|
||||
};
|
||||
|
||||
// Map all `Local`s, `SourceScope`s and `BasicBlock`s to new ones
|
||||
// (or existing ones, in a few special cases) in the caller.
|
||||
integrator.visit_body(&mut callee_body);
|
||||
|
||||
// If there are any locals without storage markers, give them storage only for the
|
||||
// duration of the call.
|
||||
for local in callee_body.vars_and_temps_iter() {
|
||||
if integrator.always_live_locals.contains(local) {
|
||||
let new_local = integrator.map_local(local);
|
||||
caller_body[callsite.block].statements.push(Statement {
|
||||
source_info: callsite.source_info,
|
||||
kind: StatementKind::StorageLive(new_local),
|
||||
});
|
||||
}
|
||||
}
|
||||
if let Some(block) = callsite.target {
|
||||
// To avoid repeated O(n) insert, push any new statements to the end and rotate
|
||||
// the slice once.
|
||||
let mut n = 0;
|
||||
if remap_destination {
|
||||
caller_body[block].statements.push(Statement {
|
||||
source_info: callsite.source_info,
|
||||
kind: StatementKind::Assign(Box::new((
|
||||
dest,
|
||||
Rvalue::Use(Operand::Move(destination_local.into())),
|
||||
))),
|
||||
});
|
||||
n += 1;
|
||||
}
|
||||
for local in callee_body.vars_and_temps_iter().rev() {
|
||||
if integrator.always_live_locals.contains(local) {
|
||||
let new_local = integrator.map_local(local);
|
||||
caller_body[block].statements.push(Statement {
|
||||
source_info: callsite.source_info,
|
||||
kind: StatementKind::StorageDead(new_local),
|
||||
});
|
||||
n += 1;
|
||||
}
|
||||
}
|
||||
caller_body[block].statements.rotate_right(n);
|
||||
}
|
||||
|
||||
// Insert all of the (mapped) parts of the callee body into the caller.
|
||||
caller_body.local_decls.extend(callee_body.drain_vars_and_temps());
|
||||
caller_body.source_scopes.extend(&mut callee_body.source_scopes.drain(..));
|
||||
caller_body.var_debug_info.append(&mut callee_body.var_debug_info);
|
||||
caller_body.basic_blocks_mut().extend(callee_body.basic_blocks_mut().drain(..));
|
||||
|
||||
caller_body[callsite.block].terminator = Some(Terminator {
|
||||
source_info: callsite.source_info,
|
||||
kind: TerminatorKind::Goto { target: integrator.map_block(START_BLOCK) },
|
||||
});
|
||||
|
||||
// Copy only unevaluated constants from the callee_body into the caller_body.
|
||||
// Although we are only pushing `ConstKind::Unevaluated` consts to
|
||||
// `required_consts`, here we may not only have `ConstKind::Unevaluated`
|
||||
// because we are calling `instantiate_and_normalize_erasing_regions`.
|
||||
caller_body.required_consts.extend(
|
||||
callee_body.required_consts.iter().copied().filter(|&ct| match ct.const_ {
|
||||
Const::Ty(_) => {
|
||||
bug!("should never encounter ty::UnevaluatedConst in `required_consts`")
|
||||
}
|
||||
Const::Val(..) | Const::Unevaluated(..) => true,
|
||||
}),
|
||||
);
|
||||
}
|
||||
kind => bug!("unexpected terminator kind {:?}", kind),
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
let dest = if dest_needs_borrow(destination) {
|
||||
trace!("creating temp for return destination");
|
||||
let dest = Rvalue::Ref(
|
||||
self.tcx.lifetimes.re_erased,
|
||||
BorrowKind::Mut { kind: MutBorrowKind::Default },
|
||||
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 {
|
||||
destination
|
||||
};
|
||||
|
||||
// Always create a local to hold the destination, as `RETURN_PLACE` may appear
|
||||
// where a full `Place` is not allowed.
|
||||
let (remap_destination, destination_local) = if let Some(d) = dest.as_local() {
|
||||
(false, d)
|
||||
} else {
|
||||
(
|
||||
true,
|
||||
self.new_call_temp(
|
||||
caller_body,
|
||||
&callsite,
|
||||
destination.ty(caller_body, self.tcx).ty,
|
||||
),
|
||||
)
|
||||
};
|
||||
|
||||
// Copy the arguments if needed.
|
||||
let args: Vec<_> = self.make_call_args(args, &callsite, caller_body, &callee_body);
|
||||
|
||||
let mut integrator = Integrator {
|
||||
args: &args,
|
||||
new_locals: Local::new(caller_body.local_decls.len())..,
|
||||
new_scopes: SourceScope::new(caller_body.source_scopes.len())..,
|
||||
new_blocks: BasicBlock::new(caller_body.basic_blocks.len())..,
|
||||
destination: destination_local,
|
||||
callsite_scope: caller_body.source_scopes[callsite.source_info.scope].clone(),
|
||||
callsite,
|
||||
cleanup_block: unwind,
|
||||
in_cleanup_block: false,
|
||||
tcx: self.tcx,
|
||||
always_live_locals: BitSet::new_filled(callee_body.local_decls.len()),
|
||||
};
|
||||
|
||||
// Map all `Local`s, `SourceScope`s and `BasicBlock`s to new ones
|
||||
// (or existing ones, in a few special cases) in the caller.
|
||||
integrator.visit_body(&mut callee_body);
|
||||
|
||||
// If there are any locals without storage markers, give them storage only for the
|
||||
// duration of the call.
|
||||
for local in callee_body.vars_and_temps_iter() {
|
||||
if integrator.always_live_locals.contains(local) {
|
||||
let new_local = integrator.map_local(local);
|
||||
caller_body[callsite.block].statements.push(Statement {
|
||||
source_info: callsite.source_info,
|
||||
kind: StatementKind::StorageLive(new_local),
|
||||
});
|
||||
}
|
||||
}
|
||||
if let Some(block) = callsite.target {
|
||||
// To avoid repeated O(n) insert, push any new statements to the end and rotate
|
||||
// the slice once.
|
||||
let mut n = 0;
|
||||
if remap_destination {
|
||||
caller_body[block].statements.push(Statement {
|
||||
source_info: callsite.source_info,
|
||||
kind: StatementKind::Assign(Box::new((
|
||||
dest,
|
||||
Rvalue::Use(Operand::Move(destination_local.into())),
|
||||
))),
|
||||
});
|
||||
n += 1;
|
||||
}
|
||||
for local in callee_body.vars_and_temps_iter().rev() {
|
||||
if integrator.always_live_locals.contains(local) {
|
||||
let new_local = integrator.map_local(local);
|
||||
caller_body[block].statements.push(Statement {
|
||||
source_info: callsite.source_info,
|
||||
kind: StatementKind::StorageDead(new_local),
|
||||
});
|
||||
n += 1;
|
||||
}
|
||||
}
|
||||
caller_body[block].statements.rotate_right(n);
|
||||
}
|
||||
|
||||
// Insert all of the (mapped) parts of the callee body into the caller.
|
||||
caller_body.local_decls.extend(callee_body.drain_vars_and_temps());
|
||||
caller_body.source_scopes.extend(&mut callee_body.source_scopes.drain(..));
|
||||
caller_body.var_debug_info.append(&mut callee_body.var_debug_info);
|
||||
caller_body.basic_blocks_mut().extend(callee_body.basic_blocks_mut().drain(..));
|
||||
|
||||
caller_body[callsite.block].terminator = Some(Terminator {
|
||||
source_info: callsite.source_info,
|
||||
kind: TerminatorKind::Goto { target: integrator.map_block(START_BLOCK) },
|
||||
});
|
||||
|
||||
// Copy only unevaluated constants from the callee_body into the caller_body.
|
||||
// Although we are only pushing `ConstKind::Unevaluated` consts to
|
||||
// `required_consts`, here we may not only have `ConstKind::Unevaluated`
|
||||
// because we are calling `instantiate_and_normalize_erasing_regions`.
|
||||
caller_body.required_consts.extend(callee_body.required_consts.iter().copied().filter(
|
||||
|&ct| match ct.const_ {
|
||||
Const::Ty(_) => {
|
||||
bug!("should never encounter ty::UnevaluatedConst in `required_consts`")
|
||||
}
|
||||
Const::Val(..) | Const::Unevaluated(..) => true,
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
fn make_call_args(
|
||||
|
Loading…
Reference in New Issue
Block a user