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,
}
// 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;
}
*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> {
}
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 {
TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => bug!(),