Auto merge of #45909 - sinkuu:issue-45885, r=arielb1

Normalize inlined function in MIR inliner

Fixes #45885

r? @arielb1
This commit is contained in:
bors 2017-11-14 02:05:37 +00:00
commit 9b53f0a662
2 changed files with 71 additions and 5 deletions

View File

@ -18,7 +18,7 @@ use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use rustc::mir::*;
use rustc::mir::transform::{MirPass, MirSource};
use rustc::mir::visit::*;
use rustc::ty::{self, Ty, TyCtxt, Instance};
use rustc::ty::{self, Instance, Ty, TyCtxt, TypeFoldable};
use rustc::ty::subst::{Subst,Substs};
use std::collections::VecDeque;
@ -77,8 +77,13 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
let mut callsites = VecDeque::new();
let param_env;
// Only do inlining into fn bodies.
if let MirSource::Fn(caller_id) = self.source {
let caller_def_id = self.tcx.hir.local_def_id(caller_id);
param_env = self.tcx.param_env(caller_def_id);
for (bb, bb_data) in caller_mir.basic_blocks().iter_enumerated() {
// Don't inline calls that are in cleanup blocks.
if bb_data.is_cleanup { continue; }
@ -88,9 +93,6 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
if let TerminatorKind::Call {
func: Operand::Constant(ref f), .. } = terminator.kind {
if let ty::TyFnDef(callee_def_id, substs) = f.ty.sty {
let caller_def_id = self.tcx.hir.local_def_id(caller_id);
let param_env = self.tcx.param_env(caller_def_id);
if let Some(instance) = Instance::resolve(self.tcx,
param_env,
callee_def_id,
@ -105,6 +107,8 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
}
}
}
} else {
return;
}
let mut local_change;
@ -123,7 +127,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
callsite.location.span,
callsite.callee) {
Ok(ref callee_mir) if self.should_inline(callsite, callee_mir) => {
callee_mir.subst(self.tcx, callsite.substs)
subst_and_normalize(callee_mir, self.tcx, &callsite.substs, param_env)
}
Ok(_) => continue,
@ -587,6 +591,30 @@ fn type_size_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
})
}
fn subst_and_normalize<'a, 'tcx: 'a>(
mir: &Mir<'tcx>,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
substs: &'tcx ty::subst::Substs<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> Mir<'tcx> {
struct Folder<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
substs: &'tcx ty::subst::Substs<'tcx>,
}
impl<'a, 'tcx: 'a> ty::fold::TypeFolder<'tcx, 'tcx> for Folder<'a, 'tcx> {
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
self.tcx
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
self.tcx.trans_apply_param_substs_env(&self.substs, self.param_env, &t)
}
}
let mut f = Folder { tcx, param_env, substs };
mir.fold_with(&mut f)
}
/**
* Integrator.
*

View File

@ -0,0 +1,38 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-flags:-Zmir-opt-level=2
pub enum Enum {
A,
B,
}
trait SliceIndex {
type Output;
fn get(&self) -> &Self::Output;
}
impl SliceIndex for usize {
type Output = Enum;
#[inline(never)]
fn get(&self) -> &Enum {
&Enum::A
}
}
#[inline(always)]
fn index<T: SliceIndex>(t: &T) -> &T::Output {
t.get()
}
fn main() {
match *index(&0) { Enum::A => true, _ => false };
}