Skip to content

Commit 4b54a90

Browse files
authored
Rollup merge of #95857 - ouz-a:mir-opt, r=oli-obk
Allow multiple derefs to be splitted in deref_separator Previously in #95649 only a single deref within projection was supported and multiple derefs caused a bunch of issues, this PR fixes those issues. ``@oli-obk`` helped a ton again ❤️
2 parents 4f6df46 + 80afd9d commit 4b54a90

File tree

3 files changed

+117
-8
lines changed

3 files changed

+117
-8
lines changed

compiler/rustc_mir_transform/src/deref_separator.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ pub fn deref_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
1111
for (i, stmt) in data.statements.iter_mut().enumerate() {
1212
match stmt.kind {
1313
StatementKind::Assign(box (og_place, Rvalue::Ref(region, borrow_knd, place))) => {
14+
let mut place_local = place.local;
15+
let mut last_len = 0;
1416
for (idx, (p_ref, p_elem)) in place.iter_projections().enumerate() {
1517
if p_elem == ProjectionElem::Deref && !p_ref.projection.is_empty() {
1618
// The type that we are derefing.
@@ -23,15 +25,18 @@ pub fn deref_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
2325
patch.add_statement(loc, StatementKind::StorageLive(temp));
2426

2527
// We are adding current p_ref's projections to our
26-
// temp value.
27-
let deref_place =
28-
Place::from(p_ref.local).project_deeper(p_ref.projection, tcx);
28+
// temp value, excluding projections we already covered.
29+
let deref_place = Place::from(place_local)
30+
.project_deeper(&p_ref.projection[last_len..], tcx);
2931
patch.add_assign(
3032
loc,
3133
Place::from(temp),
3234
Rvalue::Use(Operand::Move(deref_place)),
3335
);
3436

37+
place_local = temp;
38+
last_len = p_ref.projection.len();
39+
3540
// We are creating a place by using our temp value's location
3641
// and copying derefed values which we need to create new statement.
3742
let temp_place =
@@ -50,11 +55,6 @@ pub fn deref_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
5055
// Since our job with the temp is done it should be gone
5156
let loc = Location { block: block, statement_index: i + 1 };
5257
patch.add_statement(loc, StatementKind::StorageDead(temp));
53-
54-
// As all projections are off the base projection, if there are
55-
// multiple derefs in the middle of projection, it might cause
56-
// unsoundness, to not let that happen we break the loop.
57-
break;
5858
}
5959
}
6060
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
- // MIR for `main` before Derefer
2+
+ // MIR for `main` after Derefer
3+
4+
fn main() -> () {
5+
let mut _0: (); // return place in scope 0 at $DIR/derefer_test_multiple.rs:2:12: 2:12
6+
let mut _1: (i32, i32); // in scope 0 at $DIR/derefer_test_multiple.rs:3:9: 3:14
7+
let mut _3: &mut (i32, i32); // in scope 0 at $DIR/derefer_test_multiple.rs:4:22: 4:28
8+
let mut _5: &mut (i32, &mut (i32, i32)); // in scope 0 at $DIR/derefer_test_multiple.rs:5:22: 5:28
9+
let mut _7: &mut (i32, &mut (i32, &mut (i32, i32))); // in scope 0 at $DIR/derefer_test_multiple.rs:6:22: 6:28
10+
+ let mut _10: &mut (i32, &mut (i32, &mut (i32, i32))); // in scope 0 at $DIR/derefer_test_multiple.rs:7:13: 7:30
11+
+ let mut _11: &mut (i32, &mut (i32, i32)); // in scope 0 at $DIR/derefer_test_multiple.rs:7:13: 7:30
12+
+ let mut _12: &mut (i32, i32); // in scope 0 at $DIR/derefer_test_multiple.rs:7:13: 7:30
13+
+ let mut _13: &mut (i32, &mut (i32, &mut (i32, i32))); // in scope 0 at $DIR/derefer_test_multiple.rs:8:13: 8:30
14+
+ let mut _14: &mut (i32, &mut (i32, i32)); // in scope 0 at $DIR/derefer_test_multiple.rs:8:13: 8:30
15+
+ let mut _15: &mut (i32, i32); // in scope 0 at $DIR/derefer_test_multiple.rs:8:13: 8:30
16+
scope 1 {
17+
debug a => _1; // in scope 1 at $DIR/derefer_test_multiple.rs:3:9: 3:14
18+
let mut _2: (i32, &mut (i32, i32)); // in scope 1 at $DIR/derefer_test_multiple.rs:4:9: 4:14
19+
scope 2 {
20+
debug b => _2; // in scope 2 at $DIR/derefer_test_multiple.rs:4:9: 4:14
21+
let mut _4: (i32, &mut (i32, &mut (i32, i32))); // in scope 2 at $DIR/derefer_test_multiple.rs:5:9: 5:14
22+
scope 3 {
23+
debug c => _4; // in scope 3 at $DIR/derefer_test_multiple.rs:5:9: 5:14
24+
let mut _6: (i32, &mut (i32, &mut (i32, &mut (i32, i32)))); // in scope 3 at $DIR/derefer_test_multiple.rs:6:9: 6:14
25+
scope 4 {
26+
debug d => _6; // in scope 4 at $DIR/derefer_test_multiple.rs:6:9: 6:14
27+
let _8: &mut i32; // in scope 4 at $DIR/derefer_test_multiple.rs:7:9: 7:10
28+
scope 5 {
29+
debug x => _8; // in scope 5 at $DIR/derefer_test_multiple.rs:7:9: 7:10
30+
let _9: &mut i32; // in scope 5 at $DIR/derefer_test_multiple.rs:8:9: 8:10
31+
scope 6 {
32+
debug y => _9; // in scope 6 at $DIR/derefer_test_multiple.rs:8:9: 8:10
33+
}
34+
}
35+
}
36+
}
37+
}
38+
}
39+
40+
bb0: {
41+
StorageLive(_1); // scope 0 at $DIR/derefer_test_multiple.rs:3:9: 3:14
42+
(_1.0: i32) = const 42_i32; // scope 0 at $DIR/derefer_test_multiple.rs:3:17: 3:25
43+
(_1.1: i32) = const 43_i32; // scope 0 at $DIR/derefer_test_multiple.rs:3:17: 3:25
44+
StorageLive(_2); // scope 1 at $DIR/derefer_test_multiple.rs:4:9: 4:14
45+
StorageLive(_3); // scope 1 at $DIR/derefer_test_multiple.rs:4:22: 4:28
46+
_3 = &mut _1; // scope 1 at $DIR/derefer_test_multiple.rs:4:22: 4:28
47+
(_2.0: i32) = const 99_i32; // scope 1 at $DIR/derefer_test_multiple.rs:4:17: 4:29
48+
(_2.1: &mut (i32, i32)) = move _3; // scope 1 at $DIR/derefer_test_multiple.rs:4:17: 4:29
49+
StorageDead(_3); // scope 1 at $DIR/derefer_test_multiple.rs:4:28: 4:29
50+
StorageLive(_4); // scope 2 at $DIR/derefer_test_multiple.rs:5:9: 5:14
51+
StorageLive(_5); // scope 2 at $DIR/derefer_test_multiple.rs:5:22: 5:28
52+
_5 = &mut _2; // scope 2 at $DIR/derefer_test_multiple.rs:5:22: 5:28
53+
(_4.0: i32) = const 11_i32; // scope 2 at $DIR/derefer_test_multiple.rs:5:17: 5:29
54+
(_4.1: &mut (i32, &mut (i32, i32))) = move _5; // scope 2 at $DIR/derefer_test_multiple.rs:5:17: 5:29
55+
StorageDead(_5); // scope 2 at $DIR/derefer_test_multiple.rs:5:28: 5:29
56+
StorageLive(_6); // scope 3 at $DIR/derefer_test_multiple.rs:6:9: 6:14
57+
StorageLive(_7); // scope 3 at $DIR/derefer_test_multiple.rs:6:22: 6:28
58+
_7 = &mut _4; // scope 3 at $DIR/derefer_test_multiple.rs:6:22: 6:28
59+
(_6.0: i32) = const 13_i32; // scope 3 at $DIR/derefer_test_multiple.rs:6:17: 6:29
60+
(_6.1: &mut (i32, &mut (i32, &mut (i32, i32)))) = move _7; // scope 3 at $DIR/derefer_test_multiple.rs:6:17: 6:29
61+
StorageDead(_7); // scope 3 at $DIR/derefer_test_multiple.rs:6:28: 6:29
62+
StorageLive(_8); // scope 4 at $DIR/derefer_test_multiple.rs:7:9: 7:10
63+
- _8 = &mut ((*((*((*(_6.1: &mut (i32, &mut (i32, &mut (i32, i32))))).1: &mut (i32, &mut (i32, i32)))).1: &mut (i32, i32))).1: i32); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30
64+
+ StorageLive(_10); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30
65+
+ _10 = move (_6.1: &mut (i32, &mut (i32, &mut (i32, i32)))); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30
66+
+ StorageLive(_11); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30
67+
+ _11 = move ((*_10).1: &mut (i32, &mut (i32, i32))); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30
68+
+ StorageLive(_12); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30
69+
+ _12 = move ((*_11).1: &mut (i32, i32)); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30
70+
+ _8 = &mut ((*_12).1: i32); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30
71+
+ StorageDead(_10); // scope 5 at $DIR/derefer_test_multiple.rs:8:9: 8:10
72+
+ StorageDead(_11); // scope 5 at $DIR/derefer_test_multiple.rs:8:9: 8:10
73+
+ StorageDead(_12); // scope 5 at $DIR/derefer_test_multiple.rs:8:9: 8:10
74+
StorageLive(_9); // scope 5 at $DIR/derefer_test_multiple.rs:8:9: 8:10
75+
- _9 = &mut ((*((*((*(_6.1: &mut (i32, &mut (i32, &mut (i32, i32))))).1: &mut (i32, &mut (i32, i32)))).1: &mut (i32, i32))).1: i32); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30
76+
+ StorageLive(_13); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30
77+
+ _13 = move (_6.1: &mut (i32, &mut (i32, &mut (i32, i32)))); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30
78+
+ StorageLive(_14); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30
79+
+ _14 = move ((*_13).1: &mut (i32, &mut (i32, i32))); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30
80+
+ StorageLive(_15); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30
81+
+ _15 = move ((*_14).1: &mut (i32, i32)); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30
82+
+ _9 = &mut ((*_15).1: i32); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30
83+
+ StorageDead(_13); // scope 0 at $DIR/derefer_test_multiple.rs:2:12: 9:2
84+
+ StorageDead(_14); // scope 0 at $DIR/derefer_test_multiple.rs:2:12: 9:2
85+
+ StorageDead(_15); // scope 0 at $DIR/derefer_test_multiple.rs:2:12: 9:2
86+
_0 = const (); // scope 0 at $DIR/derefer_test_multiple.rs:2:12: 9:2
87+
StorageDead(_9); // scope 5 at $DIR/derefer_test_multiple.rs:9:1: 9:2
88+
StorageDead(_8); // scope 4 at $DIR/derefer_test_multiple.rs:9:1: 9:2
89+
StorageDead(_6); // scope 3 at $DIR/derefer_test_multiple.rs:9:1: 9:2
90+
StorageDead(_4); // scope 2 at $DIR/derefer_test_multiple.rs:9:1: 9:2
91+
StorageDead(_2); // scope 1 at $DIR/derefer_test_multiple.rs:9:1: 9:2
92+
StorageDead(_1); // scope 0 at $DIR/derefer_test_multiple.rs:9:1: 9:2
93+
return; // scope 0 at $DIR/derefer_test_multiple.rs:9:2: 9:2
94+
+ }
95+
+
96+
+ bb1 (cleanup): {
97+
+ resume; // scope 0 at $DIR/derefer_test_multiple.rs:2:1: 9:2
98+
}
99+
}
100+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// EMIT_MIR derefer_test_multiple.main.Derefer.diff
2+
fn main () {
3+
let mut a = (42, 43);
4+
let mut b = (99, &mut a);
5+
let mut c = (11, &mut b);
6+
let mut d = (13, &mut c);
7+
let x = &mut (*d.1).1.1.1;
8+
let y = &mut (*d.1).1.1.1;
9+
}

0 commit comments

Comments
 (0)