Skip to content

Commit 45c4e11

Browse files
tmiaskoCentril
andcommitted
SimplifyArmIdentity only for locals with the same type
Co-Authored-By: Mazdak Farrokhzad <twingoow@gmail.com>
1 parent c4375c9 commit 45c4e11

File tree

3 files changed

+102
-1
lines changed

3 files changed

+102
-1
lines changed

src/librustc_mir/transform/simplify_try.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ pub struct SimplifyArmIdentity;
3434

3535
impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity {
3636
fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) {
37-
for bb in body.basic_blocks_mut() {
37+
let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
38+
for bb in basic_blocks {
3839
// Need 3 statements:
3940
let (s0, s1, s2) = match &mut *bb.statements {
4041
[s0, s1, s2] => (s0, s1, s2),
@@ -51,7 +52,12 @@ impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity {
5152
Some(x) => x,
5253
};
5354
if local_tmp_s0 != local_tmp_s1
55+
// The field-and-variant information match up.
5456
|| vf_s0 != vf_s1
57+
// Source and target locals have the same type.
58+
// FIXME(Centril | oli-obk): possibly relax to same layout?
59+
|| local_decls[local_0].ty != local_decls[local_1].ty
60+
// We're setting the discriminant of `local_0` to this variant.
5561
|| Some((local_0, vf_s0.var_idx)) != match_set_discr(s2)
5662
{
5763
continue;
+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// Checks that `SimplifyArmIdentity` is not applied if enums have incompatible layouts.
2+
// Regression test for issue #66856.
3+
//
4+
// compile-flags: -Zmir-opt-level=2
5+
6+
enum Src {
7+
Foo(u8),
8+
Bar,
9+
}
10+
11+
enum Dst {
12+
Foo(u8),
13+
}
14+
15+
fn main() {
16+
let e: Src = Src::Foo(0);
17+
let _: Dst = match e {
18+
Src::Foo(x) => Dst::Foo(x),
19+
Src::Bar => Dst::Foo(0),
20+
};
21+
}
22+
23+
// END RUST SOURCE
24+
// START rustc.main.SimplifyArmIdentity.before.mir
25+
// fn main() -> () {
26+
// ...
27+
// bb0: {
28+
// StorageLive(_1);
29+
// ((_1 as Foo).0: u8) = const 0u8;
30+
// discriminant(_1) = 0;
31+
// StorageLive(_2);
32+
// _3 = discriminant(_1);
33+
// switchInt(move _3) -> [0isize: bb3, 1isize: bb1, otherwise: bb2];
34+
// }
35+
// bb1: {
36+
// ((_2 as Foo).0: u8) = const 0u8;
37+
// discriminant(_2) = 0;
38+
// goto -> bb4;
39+
// }
40+
// ...
41+
// bb3: {
42+
// _4 = ((_1 as Foo).0: u8);
43+
// ((_2 as Foo).0: u8) = move _4;
44+
// discriminant(_2) = 0;
45+
// goto -> bb4;
46+
// }
47+
// ...
48+
// }
49+
// END rustc.main.SimplifyArmIdentity.before.mir
50+
// START rustc.main.SimplifyArmIdentity.after.mir
51+
// fn main() -> () {
52+
// ...
53+
// bb0: {
54+
// StorageLive(_1);
55+
// ((_1 as Foo).0: u8) = const 0u8;
56+
// discriminant(_1) = 0;
57+
// StorageLive(_2);
58+
// _3 = discriminant(_1);
59+
// switchInt(move _3) -> [0isize: bb3, 1isize: bb1, otherwise: bb2];
60+
// }
61+
// bb1: {
62+
// ((_2 as Foo).0: u8) = const 0u8;
63+
// discriminant(_2) = 0;
64+
// goto -> bb4;
65+
// }
66+
// ...
67+
// bb3: {
68+
// _4 = ((_1 as Foo).0: u8);
69+
// ((_2 as Foo).0: u8) = move _4;
70+
// discriminant(_2) = 0;
71+
// goto -> bb4;
72+
// }
73+
// ...
74+
// }
75+
// END rustc.main.SimplifyArmIdentity.after.mir

src/test/ui/issues/issue-66851.rs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// This used to mis-compile because the mir-opt `SimplifyArmIdentity`
2+
// did not check that the types matched up in the `Ok(r)` branch.
3+
//
4+
// run-pass
5+
// compile-flags: -Zmir-opt-level=2
6+
7+
#[derive(Debug, PartialEq, Eq)]
8+
enum SpecialsRes { Res(u64) }
9+
10+
fn e103() -> SpecialsRes {
11+
if let Ok(r) = "1".parse() {
12+
SpecialsRes::Res(r)
13+
} else {
14+
SpecialsRes::Res(42)
15+
}
16+
}
17+
18+
fn main() {
19+
assert_eq!(e103(), SpecialsRes::Res(1));
20+
}

0 commit comments

Comments
 (0)