1
Fork 0

Visit move out of _0 when visiting return

This commit is contained in:
Jonas Schievink 2020-05-09 16:08:04 +02:00
parent 7c59a81a5f
commit e22cc993fb
4 changed files with 38 additions and 3 deletions

View file

@ -427,13 +427,29 @@ macro_rules! make_mir_visitor {
TerminatorKind::Goto { .. } | TerminatorKind::Goto { .. } |
TerminatorKind::Resume | TerminatorKind::Resume |
TerminatorKind::Abort | TerminatorKind::Abort |
TerminatorKind::Return |
TerminatorKind::GeneratorDrop | TerminatorKind::GeneratorDrop |
TerminatorKind::Unreachable | TerminatorKind::Unreachable |
TerminatorKind::FalseEdges { .. } | TerminatorKind::FalseEdges { .. } |
TerminatorKind::FalseUnwind { .. } => { TerminatorKind::FalseUnwind { .. } => {
} }
TerminatorKind::Return => {
// `return` logically moves from the return place `_0`. Note that the place
// cannot be changed by any visitor, though.
let $($mutability)? local = RETURN_PLACE;
self.visit_local(
& $($mutability)? local,
PlaceContext::NonMutatingUse(NonMutatingUseContext::Move),
source_location,
);
assert_eq!(
local,
RETURN_PLACE,
"`MutVisitor` tried to mutate return place of `return` terminator"
);
}
TerminatorKind::SwitchInt { TerminatorKind::SwitchInt {
discr, discr,
switch_ty, switch_ty,

View file

@ -73,7 +73,12 @@ impl<'tcx> MirPass<'tcx> for CopyPropagation {
} }
// Conservatively gives up if the dest is an argument, // Conservatively gives up if the dest is an argument,
// because there may be uses of the original argument value. // because there may be uses of the original argument value.
if body.local_kind(dest_local) == LocalKind::Arg { // Also gives up on the return place, as we cannot propagate into its implicit
// use by `return`.
if matches!(
body.local_kind(dest_local),
LocalKind::Arg | LocalKind::ReturnPointer
) {
debug!(" Can't copy-propagate local: dest {:?} (argument)", dest_local); debug!(" Can't copy-propagate local: dest {:?} (argument)", dest_local);
continue; continue;
} }

View file

@ -91,6 +91,16 @@ impl<'tcx> MutVisitor<'tcx> for RenameLocalVisitor<'tcx> {
*local = self.to; *local = self.to;
} }
} }
fn visit_terminator_kind(&mut self, kind: &mut TerminatorKind<'tcx>, location: Location) {
match kind {
TerminatorKind::Return => {
// Do not replace the implicit `_0` access here, as that's not possible. The
// transform already handles `return` correctly.
}
_ => self.super_terminator_kind(kind, location),
}
}
} }
struct DerefArgVisitor<'tcx> { struct DerefArgVisitor<'tcx> {

View file

@ -732,7 +732,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
} }
fn visit_terminator_kind(&mut self, kind: &mut TerminatorKind<'tcx>, loc: Location) { fn visit_terminator_kind(&mut self, kind: &mut TerminatorKind<'tcx>, loc: Location) {
self.super_terminator_kind(kind, loc); // Don't try to modify the implicit `_0` access on return (`return` terminators are
// replaced down below anyways).
if !matches!(kind, TerminatorKind::Return) {
self.super_terminator_kind(kind, loc);
}
match *kind { match *kind {
TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => bug!(), TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => bug!(),