Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure enum cast moves #103016

Merged
merged 4 commits into from
Oct 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,13 +197,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// create all the steps directly in MIR with operations all backends need to support anyway.
let (source, ty) = if let ty::Adt(adt_def, ..) = source.ty.kind() && adt_def.is_enum() {
let discr_ty = adt_def.repr().discr_type().to_ty(this.tcx);
let place = unpack!(block = this.as_place(block, source));
let temp = unpack!(block = this.as_temp(block, scope, source, Mutability::Not));
let discr = this.temp(discr_ty, source.span);
this.cfg.push_assign(
block,
source_info,
discr,
Rvalue::Discriminant(place),
Rvalue::Discriminant(temp.into()),
);

(Operand::Move(discr), discr_ty)
Expand Down
10 changes: 7 additions & 3 deletions src/test/mir-opt/enum_cast.bar.mir_map.0.mir
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@
fn bar(_1: Bar) -> usize {
debug bar => _1; // in scope 0 at $DIR/enum_cast.rs:+0:8: +0:11
let mut _0: usize; // return place in scope 0 at $DIR/enum_cast.rs:+0:21: +0:26
let mut _2: isize; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
let _2: Bar; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
let mut _3: isize; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8

bb0: {
_2 = discriminant(_1); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
_0 = move _2 as usize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
StorageLive(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
_2 = move _1; // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
_3 = discriminant(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
_0 = move _3 as usize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
StorageDead(_2); // scope 0 at $DIR/enum_cast.rs:+1:16: +1:17
return; // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
}
}
10 changes: 7 additions & 3 deletions src/test/mir-opt/enum_cast.boo.mir_map.0.mir
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@
fn boo(_1: Boo) -> usize {
debug boo => _1; // in scope 0 at $DIR/enum_cast.rs:+0:8: +0:11
let mut _0: usize; // return place in scope 0 at $DIR/enum_cast.rs:+0:21: +0:26
let mut _2: u8; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
let _2: Boo; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
let mut _3: u8; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8

bb0: {
_2 = discriminant(_1); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
_0 = move _2 as usize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
StorageLive(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
_2 = move _1; // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
_3 = discriminant(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
_0 = move _3 as usize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
StorageDead(_2); // scope 0 at $DIR/enum_cast.rs:+1:16: +1:17
return; // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
}
}
40 changes: 26 additions & 14 deletions src/test/mir-opt/enum_cast.droppy.mir_map.0.mir
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ fn droppy() -> () {
let mut _0: (); // return place in scope 0 at $DIR/enum_cast.rs:+0:13: +0:13
let _1: (); // in scope 0 at $DIR/enum_cast.rs:+1:5: +6:6
let _2: Droppy; // in scope 0 at $DIR/enum_cast.rs:+2:13: +2:14
let mut _4: isize; // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:18
let _5: Droppy; // in scope 0 at $DIR/enum_cast.rs:+7:9: +7:10
let _4: Droppy; // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:18
let mut _5: isize; // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:18
let _6: Droppy; // in scope 0 at $DIR/enum_cast.rs:+7:9: +7:10
scope 1 {
debug x => _2; // in scope 1 at $DIR/enum_cast.rs:+2:13: +2:14
scope 2 {
Expand All @@ -16,7 +17,7 @@ fn droppy() -> () {
}
}
scope 4 {
debug z => _5; // in scope 4 at $DIR/enum_cast.rs:+7:9: +7:10
debug z => _6; // in scope 4 at $DIR/enum_cast.rs:+7:9: +7:10
}

bb0: {
Expand All @@ -25,30 +26,41 @@ fn droppy() -> () {
_2 = Droppy::C; // scope 0 at $DIR/enum_cast.rs:+2:17: +2:26
FakeRead(ForLet(None), _2); // scope 0 at $DIR/enum_cast.rs:+2:13: +2:14
StorageLive(_3); // scope 3 at $DIR/enum_cast.rs:+5:13: +5:14
_4 = discriminant(_2); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
_3 = move _4 as usize (IntToInt); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
StorageLive(_4); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:18
_4 = move _2; // scope 3 at $DIR/enum_cast.rs:+5:17: +5:18
_5 = discriminant(_4); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
_3 = move _5 as usize (IntToInt); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
drop(_4) -> [return: bb1, unwind: bb4]; // scope 3 at $DIR/enum_cast.rs:+5:26: +5:27
}

bb1: {
StorageDead(_4); // scope 3 at $DIR/enum_cast.rs:+5:26: +5:27
FakeRead(ForLet(None), _3); // scope 3 at $DIR/enum_cast.rs:+5:13: +5:14
_1 = const (); // scope 0 at $DIR/enum_cast.rs:+1:5: +6:6
StorageDead(_3); // scope 1 at $DIR/enum_cast.rs:+6:5: +6:6
drop(_2) -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/enum_cast.rs:+6:5: +6:6
drop(_2) -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/enum_cast.rs:+6:5: +6:6
}

bb1: {
bb2: {
StorageDead(_2); // scope 0 at $DIR/enum_cast.rs:+6:5: +6:6
StorageDead(_1); // scope 0 at $DIR/enum_cast.rs:+6:5: +6:6
StorageLive(_5); // scope 0 at $DIR/enum_cast.rs:+7:9: +7:10
_5 = Droppy::B; // scope 0 at $DIR/enum_cast.rs:+7:13: +7:22
FakeRead(ForLet(None), _5); // scope 0 at $DIR/enum_cast.rs:+7:9: +7:10
StorageLive(_6); // scope 0 at $DIR/enum_cast.rs:+7:9: +7:10
_6 = Droppy::B; // scope 0 at $DIR/enum_cast.rs:+7:13: +7:22
FakeRead(ForLet(None), _6); // scope 0 at $DIR/enum_cast.rs:+7:9: +7:10
_0 = const (); // scope 0 at $DIR/enum_cast.rs:+0:13: +8:2
drop(_5) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/enum_cast.rs:+8:1: +8:2
drop(_6) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/enum_cast.rs:+8:1: +8:2
}

bb2: {
StorageDead(_5); // scope 0 at $DIR/enum_cast.rs:+8:1: +8:2
bb3: {
StorageDead(_6); // scope 0 at $DIR/enum_cast.rs:+8:1: +8:2
return; // scope 0 at $DIR/enum_cast.rs:+8:2: +8:2
}

bb3 (cleanup): {
bb4 (cleanup): {
drop(_2) -> bb5; // scope 0 at $DIR/enum_cast.rs:+6:5: +6:6
}

bb5 (cleanup): {
resume; // scope 0 at $DIR/enum_cast.rs:+0:1: +8:2
}
}
10 changes: 7 additions & 3 deletions src/test/mir-opt/enum_cast.foo.mir_map.0.mir
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@
fn foo(_1: Foo) -> usize {
debug foo => _1; // in scope 0 at $DIR/enum_cast.rs:+0:8: +0:11
let mut _0: usize; // return place in scope 0 at $DIR/enum_cast.rs:+0:21: +0:26
let mut _2: isize; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
let _2: Foo; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
let mut _3: isize; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8

bb0: {
_2 = discriminant(_1); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
_0 = move _2 as usize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
StorageLive(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
_2 = move _1; // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
_3 = discriminant(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
_0 = move _3 as usize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
StorageDead(_2); // scope 0 at $DIR/enum_cast.rs:+1:16: +1:17
return; // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
}
}
2 changes: 1 addition & 1 deletion src/test/run-pass-valgrind/cast-enum-with-dtor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fn main() {
{
let e = E::C;
assert_eq!(e as u32, 2);
assert_eq!(FLAG.load(Ordering::SeqCst), 0);
assert_eq!(FLAG.load(Ordering::SeqCst), 1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when I first read this PR, I was concerned that this change to this test does not represent a pure revert of the change in behavior injected by #96862 (see specifically https://github.com/rust-lang/rust/pull/96862/files#diff-7e1f76bb00c9a4c88616e00451baa4b95f56d066d893b0bd781f17dadfcf1338 , which changed a different line in this test).

However, @nbdd0121 has pointed out to me that we never intended to specify how drop interacts with casting of C enums, and in fact #97652 made the pre-existing lint against such casts into a future-incompat error. So I am no longer concerned about the change in behavior to this test.

}
assert_eq!(FLAG.load(Ordering::SeqCst), 1);
}
8 changes: 8 additions & 0 deletions src/test/ui/mir/issue-102389.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
enum Enum { A, B, C }

fn func(inbounds: &Enum, array: &[i16; 3]) -> i16 {
array[*inbounds as usize]
//~^ ERROR [E0507]
}

fn main() {}
9 changes: 9 additions & 0 deletions src/test/ui/mir/issue-102389.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0507]: cannot move out of `*inbounds` which is behind a shared reference
--> $DIR/issue-102389.rs:4:11
|
LL | array[*inbounds as usize]
| ^^^^^^^^^ move occurs because `*inbounds` has type `Enum`, which does not implement the `Copy` trait

error: aborting due to previous error

For more information about this error, try `rustc --explain E0507`.