Skip to content

Commit daf48b8

Browse files
committed
inliner: use caller param_env
1 parent efbaa41 commit daf48b8

File tree

2 files changed

+53
-17
lines changed

2 files changed

+53
-17
lines changed

compiler/rustc_mir/src/transform/inline.rs

+15-17
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,20 @@ impl<'tcx> MirPass<'tcx> for Inline {
4545
// based function.
4646
debug!("function inlining is disabled when compiling with `instrument_coverage`");
4747
} else {
48-
Inliner { tcx, codegen_fn_attrs: tcx.codegen_fn_attrs(body.source.def_id()) }
49-
.run_pass(body);
48+
Inliner {
49+
tcx,
50+
param_env: tcx.param_env_reveal_all_normalized(body.source.def_id()),
51+
codegen_fn_attrs: tcx.codegen_fn_attrs(body.source.def_id()),
52+
}
53+
.run_pass(body);
5054
}
5155
}
5256
}
5357
}
5458

5559
struct Inliner<'tcx> {
5660
tcx: TyCtxt<'tcx>,
61+
param_env: ParamEnv<'tcx>,
5762
codegen_fn_attrs: &'tcx CodegenFnAttrs,
5863
}
5964

@@ -75,17 +80,13 @@ impl Inliner<'tcx> {
7580

7681
let def_id = caller_body.source.def_id();
7782

78-
let param_env = self.tcx.param_env_reveal_all_normalized(def_id);
79-
8083
// Only do inlining into fn bodies.
8184
let self_hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
8285
if self.tcx.hir().body_owner_kind(self_hir_id).is_fn_or_closure()
8386
&& caller_body.source.promoted.is_none()
8487
{
8588
for (bb, bb_data) in caller_body.basic_blocks().iter_enumerated() {
86-
if let Some(callsite) =
87-
self.get_valid_function_call(bb, bb_data, caller_body, param_env)
88-
{
89+
if let Some(callsite) = self.get_valid_function_call(bb, bb_data, caller_body) {
8990
callsites.push_back(callsite);
9091
}
9192
}
@@ -131,7 +132,7 @@ impl Inliner<'tcx> {
131132
let callee_body = if self.consider_optimizing(callsite, callee_body) {
132133
self.tcx.subst_and_normalize_erasing_regions(
133134
&callsite.substs,
134-
param_env,
135+
self.param_env,
135136
callee_body,
136137
)
137138
} else {
@@ -159,7 +160,7 @@ impl Inliner<'tcx> {
159160
// Add callsites from inlined function
160161
for (bb, bb_data) in caller_body.basic_blocks().iter_enumerated().skip(start) {
161162
if let Some(new_callsite) =
162-
self.get_valid_function_call(bb, bb_data, caller_body, param_env)
163+
self.get_valid_function_call(bb, bb_data, caller_body)
163164
{
164165
// Don't inline the same function multiple times.
165166
if callsite.callee != new_callsite.callee {
@@ -190,7 +191,6 @@ impl Inliner<'tcx> {
190191
bb: BasicBlock,
191192
bb_data: &BasicBlockData<'tcx>,
192193
caller_body: &Body<'tcx>,
193-
param_env: ParamEnv<'tcx>,
194194
) -> Option<CallSite<'tcx>> {
195195
// Don't inline calls that are in cleanup blocks.
196196
if bb_data.is_cleanup {
@@ -201,8 +201,9 @@ impl Inliner<'tcx> {
201201
let terminator = bb_data.terminator();
202202
if let TerminatorKind::Call { func: ref op, .. } = terminator.kind {
203203
if let ty::FnDef(callee_def_id, substs) = *op.ty(caller_body, self.tcx).kind() {
204-
let instance =
205-
Instance::resolve(self.tcx, param_env, callee_def_id, substs).ok().flatten()?;
204+
let instance = Instance::resolve(self.tcx, self.param_env, callee_def_id, substs)
205+
.ok()
206+
.flatten()?;
206207

207208
if let InstanceDef::Virtual(..) = instance.def {
208209
return None;
@@ -300,9 +301,6 @@ impl Inliner<'tcx> {
300301
debug!(" final inline threshold = {}", threshold);
301302

302303
// FIXME: Give a bonus to functions with only a single caller
303-
304-
let param_env = tcx.param_env(callee_body.source.def_id());
305-
306304
let mut first_block = true;
307305
let mut cost = 0;
308306

@@ -335,7 +333,7 @@ impl Inliner<'tcx> {
335333
// If the place doesn't actually need dropping, treat it like
336334
// a regular goto.
337335
let ty = place.ty(callee_body, tcx).subst(tcx, callsite.substs).ty;
338-
if ty.needs_drop(tcx, param_env) {
336+
if ty.needs_drop(tcx, self.param_env) {
339337
cost += CALL_PENALTY;
340338
if let Some(unwind) = unwind {
341339
cost += LANDINGPAD_PENALTY;
@@ -400,7 +398,7 @@ impl Inliner<'tcx> {
400398
let ty = v.ty.subst(tcx, callsite.substs);
401399
// Cost of the var is the size in machine-words, if we know
402400
// it.
403-
if let Some(size) = type_size_of(tcx, param_env, ty) {
401+
if let Some(size) = type_size_of(tcx, self.param_env, ty) {
404402
cost += (size / ptr_size) as usize;
405403
} else {
406404
cost += UNKNOWN_SIZE_COST;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// run-pass
2+
// compile-flags:-Zmir-opt-level=2
3+
4+
use std::mem::MaybeUninit;
5+
const N: usize = 2;
6+
7+
trait CollectArray<A>: Iterator<Item = A> {
8+
fn inner_array(&mut self) -> [A; N];
9+
fn collect_array(&mut self) -> [A; N] {
10+
let result = self.inner_array();
11+
assert!(self.next().is_none());
12+
result
13+
}
14+
}
15+
16+
impl<A, I: ?Sized> CollectArray<A> for I
17+
where
18+
I: Iterator<Item = A>,
19+
{
20+
fn inner_array(&mut self) -> [A; N] {
21+
let mut result: [MaybeUninit<A>; N] = unsafe { MaybeUninit::uninit().assume_init() };
22+
for (dest, item) in result.iter_mut().zip(self) {
23+
*dest = MaybeUninit::new(item);
24+
}
25+
let temp_ptr: *const [MaybeUninit<A>; N] = &result;
26+
unsafe { std::ptr::read(temp_ptr as *const [A; N]) }
27+
}
28+
}
29+
30+
fn main() {
31+
assert_eq!(
32+
[[1, 2], [3, 4]]
33+
.iter()
34+
.map(|row| row.iter().collect_array())
35+
.collect_array(),
36+
[[&1, &2], [&3, &4]]
37+
);
38+
}

0 commit comments

Comments
 (0)