]> git.lizzy.rs Git - rust.git/commitdiff
Visit move out of `_0` when visiting `return`
authorJonas Schievink <jonasschievink@gmail.com>
Sat, 9 May 2020 14:08:04 +0000 (16:08 +0200)
committerJonas Schievink <jonasschievink@gmail.com>
Sat, 9 May 2020 14:08:04 +0000 (16:08 +0200)
src/librustc_middle/mir/visit.rs
src/librustc_mir/transform/copy_prop.rs
src/librustc_mir/transform/generator.rs
src/librustc_mir/transform/inline.rs

index 2f3d89dc02980c6c17acdf9598c9bb9efd1ad2a0..1f097f24942decf27a19892b858a94c04c623e5d 100644 (file)
@@ -427,13 +427,29 @@ fn super_terminator_kind(&mut self,
                     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,
index b9eb58f800e5c0d388af07cec6e054e0df8e3015..ba406c72df8488225a10da8425e45b66752fdf8f 100644 (file)
@@ -73,7 +73,12 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<
                     }
                     // 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;
                     }
index d334006d7b528fc3d80a640afe1422754bcf9cb3..bfc872be653a596ca25db421d3f6a00d58b40089 100644 (file)
@@ -91,6 +91,16 @@ fn visit_local(&mut self, local: &mut Local, _: PlaceContext, _: Location) {
             *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> {
index a8e949ecb3144cc9ebc4d1af058e23ac0b7db32c..632408fde749f225ef864c88f92faaecf48917cd 100644 (file)
@@ -732,7 +732,11 @@ fn visit_retag(&mut self, kind: &mut RetagKind, place: &mut Place<'tcx>, loc: Lo
     }
 
     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!(),