Visit move out of _0
when visiting return
This commit is contained in:
parent
7c59a81a5f
commit
e22cc993fb
4 changed files with 38 additions and 3 deletions
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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!(),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue