Skip to content

Commit 720b865

Browse files
committed
[mir-opt] Fix Inline pass to handle inlining into box expressions
1 parent 6f82984 commit 720b865

File tree

2 files changed

+90
-10
lines changed

2 files changed

+90
-10
lines changed

src/librustc_mir/transform/inline.rs

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -663,9 +663,9 @@ impl<'a, 'tcx> Integrator<'a, 'tcx> {
663663

664664
fn make_integrate_local(&self, local: &Local) -> Local {
665665
if *local == RETURN_PLACE {
666-
match self.destination.as_local() {
667-
Some(l) => return l,
668-
ref place => bug!("Return place is {:?}, not local", place),
666+
match self.destination.base {
667+
PlaceBase::Local(l) => return l,
668+
PlaceBase::Static(ref s) => bug!("Return place is {:?}, not local", s),
669669
}
670670
}
671671

@@ -695,14 +695,24 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
695695
fn visit_place(
696696
&mut self,
697697
place: &mut Place<'tcx>,
698-
context: PlaceContext,
699-
location: Location,
698+
_context: PlaceContext,
699+
_location: Location,
700700
) {
701-
if let Some(RETURN_PLACE) = place.as_local() {
702-
// Return pointer; update the place itself
703-
*place = self.destination.clone();
704-
} else {
705-
self.super_place(place, context, location);
701+
match &mut place.base {
702+
PlaceBase::Static(_) => {},
703+
PlaceBase::Local(l) => {
704+
// If this is the `RETURN_PLACE`, we need to rebase any projections onto it.
705+
let dest_proj_len = self.destination.projection.len();
706+
if *l == RETURN_PLACE && dest_proj_len > 0 {
707+
let mut projs = Vec::with_capacity(dest_proj_len + place.projection.len());
708+
projs.extend(self.destination.projection);
709+
projs.extend(place.projection);
710+
711+
place.projection = self.tcx.intern_place_elems(&*projs);
712+
}
713+
714+
*l = self.make_integrate_local(l);
715+
}
706716
}
707717
}
708718

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// ignore-tidy-linelength
2+
#![feature(box_syntax)]
3+
4+
fn main() {
5+
let _x: Box<Vec<u32>> = box Vec::new();
6+
}
7+
8+
// END RUST SOURCE
9+
// START rustc.main.Inline.before.mir
10+
// let mut _0: ();
11+
// let _1: std::boxed::Box<std::vec::Vec<u32>> as UserTypeProjection { base: UserType(0), projs: [] };
12+
// let mut _2: std::boxed::Box<std::vec::Vec<u32>>;
13+
// let mut _3: ();
14+
// scope 1 {
15+
// debug _x => _1;
16+
// }
17+
// bb0: {
18+
// StorageLive(_1);
19+
// StorageLive(_2);
20+
// _2 = Box(std::vec::Vec<u32>);
21+
// (*_2) = const std::vec::Vec::<u32>::new() -> [return: bb2, unwind: bb4];
22+
// }
23+
// bb1 (cleanup): {
24+
// resume;
25+
// }
26+
// bb2: {
27+
// _1 = move _2;
28+
// StorageDead(_2);
29+
// _0 = ();
30+
// drop(_1) -> [return: bb3, unwind: bb1];
31+
// }
32+
// bb3: {
33+
// StorageDead(_1);
34+
// return;
35+
// }
36+
// bb4 (cleanup): {
37+
// _3 = const alloc::alloc::box_free::<std::vec::Vec<u32>>(move (_2.0: std::ptr::Unique<std::vec::Vec<u32>>)) -> bb1;
38+
// }
39+
// END rustc.main.Inline.before.mir
40+
// START rustc.main.Inline.after.mir
41+
// let mut _0: ();
42+
// let _1: std::boxed::Box<std::vec::Vec<u32>> as UserTypeProjection { base: UserType(0), projs: [] };
43+
// let mut _2: std::boxed::Box<std::vec::Vec<u32>>;
44+
// let mut _3: ();
45+
// let mut _4: &mut std::vec::Vec<u32>;
46+
// scope 1 {
47+
// debug _x => _1;
48+
// }
49+
// scope 2 {
50+
// }
51+
// bb0: {
52+
// StorageLive(_1);
53+
// StorageLive(_2);
54+
// _2 = Box(std::vec::Vec<u32>);
55+
// _4 = &mut (*_2);
56+
// ((*_4).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32>::NEW;
57+
// ((*_4).1: usize) = const 0usize;
58+
// _1 = move _2;
59+
// StorageDead(_2);
60+
// _0 = ();
61+
// drop(_1) -> [return: bb2, unwind: bb1];
62+
// }
63+
// bb1 (cleanup): {
64+
// resume;
65+
// }
66+
// bb2: {
67+
// StorageDead(_1);
68+
// return;
69+
// }
70+
// END rustc.main.Inline.after.mir

0 commit comments

Comments
 (0)