Merge if-let and match.

This commit is contained in:
Camille GILLOT 2023-02-08 20:32:28 +00:00
parent 4a75995fbd
commit d0934f14c7

View file

@ -917,84 +917,80 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
trace!("visit_statement: {:?}", statement); trace!("visit_statement: {:?}", statement);
let source_info = statement.source_info; let source_info = statement.source_info;
self.source_info = Some(source_info); self.source_info = Some(source_info);
if let StatementKind::Assign(box (place, ref mut rval)) = statement.kind { match statement.kind {
let can_const_prop = self.ecx.machine.can_const_prop[place.local]; StatementKind::Assign(box (place, ref mut rval)) => {
if let Some(()) = self.const_prop(rval, place) { let can_const_prop = self.ecx.machine.can_const_prop[place.local];
// This will return None if the above `const_prop` invocation only "wrote" a if let Some(()) = self.const_prop(rval, place) {
// type whose creation requires no write. E.g. a generator whose initial state // This will return None if the above `const_prop` invocation only "wrote" a
// consists solely of uninitialized memory (so it doesn't capture any locals). // type whose creation requires no write. E.g. a generator whose initial state
if let Some(ref value) = self.get_const(place) && self.should_const_prop(value) { // consists solely of uninitialized memory (so it doesn't capture any locals).
trace!("replacing {:?} with {:?}", rval, value); if let Some(ref value) = self.get_const(place) && self.should_const_prop(value) {
self.replace_with_const(rval, value, source_info); trace!("replacing {:?} with {:?}", rval, value);
if can_const_prop == ConstPropMode::FullConstProp self.replace_with_const(rval, value, source_info);
|| can_const_prop == ConstPropMode::OnlyInsideOwnBlock if can_const_prop == ConstPropMode::FullConstProp
{ || can_const_prop == ConstPropMode::OnlyInsideOwnBlock
trace!("propagated into {:?}", place); {
} trace!("propagated into {:?}", place);
}
match can_const_prop {
ConstPropMode::OnlyInsideOwnBlock => {
trace!(
"found local restricted to its block. \
Will remove it from const-prop after block is finished. Local: {:?}",
place.local
);
}
ConstPropMode::OnlyPropagateInto | ConstPropMode::NoPropagation => {
trace!("can't propagate into {:?}", place);
if place.local != RETURN_PLACE {
Self::remove_const(&mut self.ecx, place.local);
} }
} }
ConstPropMode::FullConstProp => {} match can_const_prop {
} ConstPropMode::OnlyInsideOwnBlock => {
} else { trace!(
// Const prop failed, so erase the destination, ensuring that whatever happens "found local restricted to its block. \
// from here on, does not know about the previous value. Will remove it from const-prop after block is finished. Local: {:?}",
// This is important in case we have place.local
// ```rust );
// let mut x = 42; }
// x = SOME_MUTABLE_STATIC; ConstPropMode::OnlyPropagateInto | ConstPropMode::NoPropagation => {
// // x must now be uninit trace!("can't propagate into {:?}", place);
// ``` if place.local != RETURN_PLACE {
// FIXME: we overzealously erase the entire local, because that's easier to
// implement.
trace!(
"propagation into {:?} failed.
Nuking the entire site from orbit, it's the only way to be sure",
place,
);
Self::remove_const(&mut self.ecx, place.local);
}
} else {
match statement.kind {
StatementKind::SetDiscriminant { ref place, .. } => {
match self.ecx.machine.can_const_prop[place.local] {
ConstPropMode::FullConstProp | ConstPropMode::OnlyInsideOwnBlock => {
if self.use_ecx(|this| this.ecx.statement(statement)).is_some() {
trace!("propped discriminant into {:?}", place);
} else {
Self::remove_const(&mut self.ecx, place.local); Self::remove_const(&mut self.ecx, place.local);
} }
} }
ConstPropMode::OnlyPropagateInto | ConstPropMode::NoPropagation => { ConstPropMode::FullConstProp => {}
}
} else {
// Const prop failed, so erase the destination, ensuring that whatever happens
// from here on, does not know about the previous value.
// This is important in case we have
// ```rust
// let mut x = 42;
// x = SOME_MUTABLE_STATIC;
// // x must now be uninit
// ```
// FIXME: we overzealously erase the entire local, because that's easier to
// implement.
trace!(
"propagation into {:?} failed.
Nuking the entire site from orbit, it's the only way to be sure",
place,
);
Self::remove_const(&mut self.ecx, place.local);
}
}
StatementKind::SetDiscriminant { ref place, .. } => {
match self.ecx.machine.can_const_prop[place.local] {
ConstPropMode::FullConstProp | ConstPropMode::OnlyInsideOwnBlock => {
if self.use_ecx(|this| this.ecx.statement(statement)).is_some() {
trace!("propped discriminant into {:?}", place);
} else {
Self::remove_const(&mut self.ecx, place.local); Self::remove_const(&mut self.ecx, place.local);
} }
} }
ConstPropMode::OnlyPropagateInto | ConstPropMode::NoPropagation => {
Self::remove_const(&mut self.ecx, place.local);
}
} }
StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => {
let frame = self.ecx.frame_mut();
frame.locals[local].value =
if let StatementKind::StorageLive(_) = statement.kind {
LocalValue::Live(interpret::Operand::Immediate(
interpret::Immediate::Uninit,
))
} else {
LocalValue::Dead
};
}
_ => {}
} }
StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => {
let frame = self.ecx.frame_mut();
frame.locals[local].value = if let StatementKind::StorageLive(_) = statement.kind {
LocalValue::Live(interpret::Operand::Immediate(interpret::Immediate::Uninit))
} else {
LocalValue::Dead
};
}
_ => {}
} }
self.super_statement(statement, location); self.super_statement(statement, location);