Skip to content

Commit af669c2

Browse files
committed
Auto merge of rust-lang#106850 - cjgillot:issue-106141, r=oli-obk
Make the inlining destination a Local. Fixes rust-lang#106141
2 parents a5bfc25 + 389d52c commit af669c2

File tree

4 files changed

+118
-31
lines changed

4 files changed

+118
-31
lines changed

compiler/rustc_mir_transform/src/inline.rs

+28-24
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,21 @@ impl<'tcx> Inliner<'tcx> {
542542
destination
543543
};
544544

545+
// Always create a local to hold the destination, as `RETURN_PLACE` may appear
546+
// where a full `Place` is not allowed.
547+
let (remap_destination, destination_local) = if let Some(d) = dest.as_local() {
548+
(false, d)
549+
} else {
550+
(
551+
true,
552+
self.new_call_temp(
553+
caller_body,
554+
&callsite,
555+
destination.ty(caller_body, self.tcx).ty,
556+
),
557+
)
558+
};
559+
545560
// Copy the arguments if needed.
546561
let args: Vec<_> = self.make_call_args(args, &callsite, caller_body, &callee_body);
547562

@@ -560,7 +575,7 @@ impl<'tcx> Inliner<'tcx> {
560575
new_locals: Local::new(caller_body.local_decls.len())..,
561576
new_scopes: SourceScope::new(caller_body.source_scopes.len())..,
562577
new_blocks: BasicBlock::new(caller_body.basic_blocks.len())..,
563-
destination: dest,
578+
destination: destination_local,
564579
callsite_scope: caller_body.source_scopes[callsite.source_info.scope].clone(),
565580
callsite,
566581
cleanup_block: cleanup,
@@ -591,6 +606,16 @@ impl<'tcx> Inliner<'tcx> {
591606
// To avoid repeated O(n) insert, push any new statements to the end and rotate
592607
// the slice once.
593608
let mut n = 0;
609+
if remap_destination {
610+
caller_body[block].statements.push(Statement {
611+
source_info: callsite.source_info,
612+
kind: StatementKind::Assign(Box::new((
613+
dest,
614+
Rvalue::Use(Operand::Move(destination_local.into())),
615+
))),
616+
});
617+
n += 1;
618+
}
594619
for local in callee_body.vars_and_temps_iter().rev() {
595620
if !callee_body.local_decls[local].internal
596621
&& integrator.always_live_locals.contains(local)
@@ -959,7 +984,7 @@ struct Integrator<'a, 'tcx> {
959984
new_locals: RangeFrom<Local>,
960985
new_scopes: RangeFrom<SourceScope>,
961986
new_blocks: RangeFrom<BasicBlock>,
962-
destination: Place<'tcx>,
987+
destination: Local,
963988
callsite_scope: SourceScopeData<'tcx>,
964989
callsite: &'a CallSite<'tcx>,
965990
cleanup_block: Option<BasicBlock>,
@@ -972,7 +997,7 @@ struct Integrator<'a, 'tcx> {
972997
impl Integrator<'_, '_> {
973998
fn map_local(&self, local: Local) -> Local {
974999
let new = if local == RETURN_PLACE {
975-
self.destination.local
1000+
self.destination
9761001
} else {
9771002
let idx = local.index() - 1;
9781003
if idx < self.args.len() {
@@ -1053,27 +1078,6 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
10531078
*span = span.fresh_expansion(self.expn_data);
10541079
}
10551080

1056-
fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
1057-
for elem in place.projection {
1058-
// FIXME: Make sure that return place is not used in an indexing projection, since it
1059-
// won't be rebased as it is supposed to be.
1060-
assert_ne!(ProjectionElem::Index(RETURN_PLACE), elem);
1061-
}
1062-
1063-
// If this is the `RETURN_PLACE`, we need to rebase any projections onto it.
1064-
let dest_proj_len = self.destination.projection.len();
1065-
if place.local == RETURN_PLACE && dest_proj_len > 0 {
1066-
let mut projs = Vec::with_capacity(dest_proj_len + place.projection.len());
1067-
projs.extend(self.destination.projection);
1068-
projs.extend(place.projection);
1069-
1070-
place.projection = self.tcx.intern_place_elems(&*projs);
1071-
}
1072-
// Handles integrating any locals that occur in the base
1073-
// or projections
1074-
self.super_place(place, context, location)
1075-
}
1076-
10771081
fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) {
10781082
self.in_cleanup_block = data.is_cleanup;
10791083
self.super_basic_block_data(block, data);

tests/mir-opt/inline/inline_into_box_place.main.Inline.diff

+11-7
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@
1111
let mut _6: (); // in scope 0 at $DIR/inline_into_box_place.rs:+1:42: +1:43
1212
let mut _7: *const std::vec::Vec<u32>; // in scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:43
1313
+ let mut _8: &mut std::vec::Vec<u32>; // in scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43
14+
+ let mut _9: std::vec::Vec<u32>; // in scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43
1415
scope 1 {
1516
debug _x => _1; // in scope 1 at $DIR/inline_into_box_place.rs:+1:9: +1:11
1617
}
1718
scope 2 {
1819
}
1920
+ scope 3 (inlined Vec::<u32>::new) { // at $DIR/inline_into_box_place.rs:8:33: 8:43
20-
+ let mut _9: alloc::raw_vec::RawVec<u32>; // in scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
21+
+ let mut _10: alloc::raw_vec::RawVec<u32>; // in scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
2122
+ }
2223

2324
bb0: {
@@ -37,8 +38,9 @@
3738
- (*_7) = Vec::<u32>::new() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43
3839
+ StorageLive(_8); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43
3940
+ _8 = &mut (*_7); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43
40-
+ StorageLive(_9); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
41-
+ _9 = const _; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
41+
+ StorageLive(_9); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43
42+
+ StorageLive(_10); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
43+
+ _10 = const _; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
4244
// mir::Constant
4345
- // + span: $DIR/inline_into_box_place.rs:8:33: 8:41
4446
- // + user_ty: UserType(1)
@@ -49,10 +51,12 @@
4951
+ // + span: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
5052
+ // + user_ty: UserType(0)
5153
+ // + literal: Const { ty: alloc::raw_vec::RawVec<u32>, val: Unevaluated(alloc::raw_vec::RawVec::<T>::NEW, [u32], None) }
52-
+ Deinit((*_8)); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
53-
+ ((*_8).0: alloc::raw_vec::RawVec<u32>) = move _9; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
54-
+ ((*_8).1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
55-
+ StorageDead(_9); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
54+
+ Deinit(_9); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
55+
+ (_9.0: alloc::raw_vec::RawVec<u32>) = move _10; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
56+
+ (_9.1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
57+
+ StorageDead(_10); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
58+
+ (*_8) = move _9; // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43
59+
+ StorageDead(_9); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43
5660
+ StorageDead(_8); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43
5761
_1 = move _5; // scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:43
5862
StorageDead(_5); // scope 0 at $DIR/inline_into_box_place.rs:+1:42: +1:43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
- // MIR for `outer` before Inline
2+
+ // MIR for `outer` after Inline
3+
4+
fn outer() -> usize {
5+
let mut _0: usize; // return place in scope 0 at $DIR/issue_106141.rs:+0:19: +0:24
6+
+ scope 1 (inlined inner) { // at $DIR/issue_106141.rs:2:5: 2:12
7+
+ let mut _1: bool; // in scope 1 at $DIR/issue_106141.rs:13:8: 13:21
8+
+ let mut _2: bool; // in scope 1 at $DIR/issue_106141.rs:13:8: 13:21
9+
+ let mut _3: &[bool; 1]; // in scope 1 at $DIR/issue_106141.rs:11:18: 11:25
10+
+ scope 2 {
11+
+ debug buffer => _3; // in scope 2 at $DIR/issue_106141.rs:11:9: 11:15
12+
+ scope 3 {
13+
+ debug index => _0; // in scope 3 at $DIR/issue_106141.rs:12:9: 12:14
14+
+ }
15+
+ }
16+
+ }
17+
18+
bb0: {
19+
- _0 = inner() -> bb1; // scope 0 at $DIR/issue_106141.rs:+1:5: +1:12
20+
+ StorageLive(_3); // scope 0 at $DIR/issue_106141.rs:+1:5: +1:12
21+
+ _3 = const _; // scope 1 at $DIR/issue_106141.rs:11:18: 11:25
22+
// mir::Constant
23+
- // + span: $DIR/issue_106141.rs:2:5: 2:10
24+
- // + literal: Const { ty: fn() -> usize {inner}, val: Value(<ZST>) }
25+
+ // + span: $DIR/issue_106141.rs:11:18: 11:25
26+
+ // + literal: Const { ty: &[bool; 1], val: Unevaluated(inner, [], Some(promoted[0])) }
27+
+ _0 = index() -> bb1; // scope 2 at $DIR/issue_106141.rs:12:17: 12:24
28+
+ // mir::Constant
29+
+ // + span: $DIR/issue_106141.rs:12:17: 12:22
30+
+ // + literal: Const { ty: fn() -> usize {index}, val: Value(<ZST>) }
31+
}
32+
33+
bb1: {
34+
+ StorageLive(_1); // scope 3 at $DIR/issue_106141.rs:13:8: 13:21
35+
+ _2 = Lt(_0, const 1_usize); // scope 3 at $DIR/issue_106141.rs:13:8: 13:21
36+
+ assert(move _2, "index out of bounds: the length is {} but the index is {}", const 1_usize, _0) -> bb2; // scope 3 at $DIR/issue_106141.rs:13:8: 13:21
37+
+ }
38+
+
39+
+ bb2: {
40+
+ _1 = (*_3)[_0]; // scope 3 at $DIR/issue_106141.rs:13:8: 13:21
41+
+ switchInt(move _1) -> [0: bb3, otherwise: bb4]; // scope 3 at $DIR/issue_106141.rs:13:8: 13:21
42+
+ }
43+
+
44+
+ bb3: {
45+
+ _0 = const 0_usize; // scope 3 at $DIR/issue_106141.rs:16:9: 16:10
46+
+ goto -> bb4; // scope 3 at $DIR/issue_106141.rs:13:5: 17:6
47+
+ }
48+
+
49+
+ bb4: {
50+
+ StorageDead(_1); // scope 3 at $DIR/issue_106141.rs:17:5: 17:6
51+
+ StorageDead(_3); // scope 0 at $DIR/issue_106141.rs:+1:5: +1:12
52+
return; // scope 0 at $DIR/issue_106141.rs:+2:2: +2:2
53+
}
54+
}
55+

tests/mir-opt/inline/issue_106141.rs

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
pub fn outer() -> usize {
2+
inner()
3+
}
4+
5+
fn index() -> usize {
6+
loop {}
7+
}
8+
9+
#[inline]
10+
fn inner() -> usize {
11+
let buffer = &[true];
12+
let index = index();
13+
if buffer[index] {
14+
index
15+
} else {
16+
0
17+
}
18+
}
19+
20+
fn main() {
21+
outer();
22+
}
23+
24+
// EMIT_MIR issue_106141.outer.Inline.diff

0 commit comments

Comments
 (0)