Rollup merge of #107524 - cjgillot:both-storage, r=RalfJung

Remove both StorageLive and StorageDead in CopyProp.

Fixes https://github.com/rust-lang/rust/issues/107511

https://github.com/rust-lang/rust/pull/106908 removed StorageDead without the accompanying StorageLive. In loops, execution would see repeated StorageLive, without any StorageDead, which is UB.

So when removing storage statements, we have to remove both StorageLive and StorageDead.

~I also added a MIR validation pass for StorageLive. It may be a bit overzealous.~
This commit is contained in:
Matthias Krüger 2023-02-02 17:14:06 +01:00 committed by GitHub
commit 6917040cf0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 176 additions and 48 deletions

View file

@ -162,17 +162,20 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> {
}
fn visit_statement(&mut self, stmt: &mut Statement<'tcx>, loc: Location) {
if let StatementKind::StorageDead(l) = stmt.kind
&& self.storage_to_remove.contains(l)
{
stmt.make_nop();
} else if let StatementKind::Assign(box (ref place, ref mut rvalue)) = stmt.kind
&& place.as_local().is_some()
{
// Do not replace assignments.
self.visit_rvalue(rvalue, loc)
} else {
self.super_statement(stmt, loc);
match stmt.kind {
// When removing storage statements, we need to remove both (#107511).
StatementKind::StorageLive(l) | StatementKind::StorageDead(l)
if self.storage_to_remove.contains(l) =>
{
stmt.make_nop()
}
StatementKind::Assign(box (ref place, ref mut rvalue))
if place.as_local().is_some() =>
{
// Do not replace assignments.
self.visit_rvalue(rvalue, loc)
}
_ => self.super_statement(stmt, loc),
}
}
}