fn visit_operand(&mut self, operand: &mut Operand<'tcx>, loc: Location) {
if let Operand::Move(place) = *operand
- && let Some(local) = place.as_local()
- && !self.fully_moved.contains(local)
+ && !place.has_deref()
+ && !self.fully_moved.contains(place.local)
{
*operand = Operand::Copy(place);
}
--- /dev/null
+- // MIR for `f` before CopyProp
++ // MIR for `f` after CopyProp
+
+ fn f(_1: Foo) -> bool {
+ let mut _0: bool; // return place in scope 0 at $DIR/move_projection.rs:+0:17: +0:21
+ let mut _2: Foo; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+ let mut _3: u8; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+
+ bb0: {
+- _2 = _1; // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+- _3 = move (_2.0: u8); // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+- _0 = opaque::<Foo>(move _1) -> bb1; // scope 0 at $DIR/move_projection.rs:+6:13: +6:44
++ _3 = (_1.0: u8); // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
++ _0 = opaque::<Foo>(_1) -> bb1; // scope 0 at $DIR/move_projection.rs:+6:13: +6:44
+ // mir::Constant
+ // + span: $DIR/move_projection.rs:19:28: 19:34
+ // + literal: Const { ty: fn(Foo) -> bool {opaque::<Foo>}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+ _0 = opaque::<u8>(move _3) -> bb2; // scope 0 at $DIR/move_projection.rs:+9:13: +9:44
+ // mir::Constant
+ // + span: $DIR/move_projection.rs:22:28: 22:34
+ // + literal: Const { ty: fn(u8) -> bool {opaque::<u8>}, val: Value(<ZST>) }
+ }
+
+ bb2: {
+ return; // scope 0 at $DIR/move_projection.rs:+12:13: +12:21
+ }
+ }
+
--- /dev/null
+// unit-test: CopyProp
+
+#![feature(custom_mir, core_intrinsics)]
+#![allow(unused_assignments)]
+extern crate core;
+use core::intrinsics::mir::*;
+
+fn opaque(_: impl Sized) -> bool { true }
+
+struct Foo(u8);
+
+#[custom_mir(dialect = "analysis", phase = "post-cleanup")]
+fn f(a: Foo) -> bool {
+ mir!(
+ {
+ let b = a;
+ // This is a move out of a copy, so must become a copy of `a.0`.
+ let c = Move(b.0);
+ Call(RET, bb1, opaque(Move(a)))
+ }
+ bb1 = {
+ Call(RET, ret, opaque(Move(c)))
+ }
+ ret = {
+ Return()
+ }
+ )
+}
+
+fn main() {
+ assert!(f(Foo(0)));
+}
+
+// EMIT_MIR move_projection.f.CopyProp.diff
}
bb3: {
- _4 = move ((_1 as Some).0: i32); // scope 1 at $DIR/simple_option_map_e2e.rs:7:14: 7:15
+ _4 = ((_1 as Some).0: i32); // scope 1 at $DIR/simple_option_map_e2e.rs:7:14: 7:15
StorageLive(_5); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29
StorageLive(_6); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29
_6 = (move _4,); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29