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::Resume |
|
||||
TerminatorKind::Abort |
|
||||
TerminatorKind::Return |
|
||||
TerminatorKind::GeneratorDrop |
|
||||
TerminatorKind::Unreachable |
|
||||
TerminatorKind::FalseEdges { .. } |
|
||||
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 {
|
||||
discr,
|
||||
switch_ty,
|
||||
|
|
|
@ -73,7 +73,12 @@ impl<'tcx> MirPass<'tcx> for CopyPropagation {
|
|||
}
|
||||
// Conservatively gives up if the dest is an argument,
|
||||
// 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);
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -91,6 +91,16 @@ impl<'tcx> MutVisitor<'tcx> for RenameLocalVisitor<'tcx> {
|
|||
*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> {
|
||||
|
|
|
@ -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) {
|
||||
// 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 {
|
||||
TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => bug!(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue