Auto merge of #43174 - RalfJung:refactor-ty, r=nikomatsakis

Refactor: {Lvalue,Rvalue,Operand}::ty only need the locals' types, not the full &Mir

I am writing code that needs to call these `ty` methods while mutating MIR -- which is impossible with the current API.

Even with the refactoring the situation is not great: I am cloning the `local_decls` and then passing the clone to the `ty` methods. I have to clone because `Mir::basic_blocks_mut` borrows the entire `Mir` including the `local_decls`. But even that is better than not being able to get these types at all...

Cc @nikomatsakis
This commit is contained in:
bors 2017-07-14 23:29:51 +00:00
commit 23ecebd6bd
5 changed files with 45 additions and 21 deletions

View File

@ -66,6 +66,25 @@ macro_rules! newtype_index {
)
}
/// Types for locals
type LocalDecls<'tcx> = IndexVec<Local, LocalDecl<'tcx>>;
pub trait HasLocalDecls<'tcx> {
fn local_decls(&self) -> &LocalDecls<'tcx>;
}
impl<'tcx> HasLocalDecls<'tcx> for LocalDecls<'tcx> {
fn local_decls(&self) -> &LocalDecls<'tcx> {
self
}
}
impl<'tcx> HasLocalDecls<'tcx> for Mir<'tcx> {
fn local_decls(&self) -> &LocalDecls<'tcx> {
&self.local_decls
}
}
/// Lowered representation of a single function.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Mir<'tcx> {
@ -90,7 +109,7 @@ pub struct Mir<'tcx> {
/// The first local is the return value pointer, followed by `arg_count`
/// locals for the function arguments, followed by any user-declared
/// variables and temporaries.
pub local_decls: IndexVec<Local, LocalDecl<'tcx>>,
pub local_decls: LocalDecls<'tcx>,
/// Number of arguments this function takes.
///

View File

@ -121,31 +121,34 @@ impl<'tcx> TypeFoldable<'tcx> for LvalueTy<'tcx> {
}
impl<'tcx> Lvalue<'tcx> {
pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> LvalueTy<'tcx> {
pub fn ty<'a, 'gcx, D>(&self, local_decls: &D, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> LvalueTy<'tcx>
where D: HasLocalDecls<'tcx>
{
match *self {
Lvalue::Local(index) =>
LvalueTy::Ty { ty: mir.local_decls[index].ty },
LvalueTy::Ty { ty: local_decls.local_decls()[index].ty },
Lvalue::Static(ref data) =>
LvalueTy::Ty { ty: data.ty },
Lvalue::Projection(ref proj) =>
proj.base.ty(mir, tcx).projection_ty(tcx, &proj.elem),
proj.base.ty(local_decls, tcx).projection_ty(tcx, &proj.elem),
}
}
}
impl<'tcx> Rvalue<'tcx> {
pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx>
pub fn ty<'a, 'gcx, D>(&self, local_decls: &D, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx>
where D: HasLocalDecls<'tcx>
{
match *self {
Rvalue::Use(ref operand) => operand.ty(mir, tcx),
Rvalue::Use(ref operand) => operand.ty(local_decls, tcx),
Rvalue::Repeat(ref operand, ref count) => {
let op_ty = operand.ty(mir, tcx);
let op_ty = operand.ty(local_decls, tcx);
let count = count.as_u64(tcx.sess.target.uint_type);
assert_eq!(count as usize as u64, count);
tcx.mk_array(op_ty, count as usize)
}
Rvalue::Ref(reg, bk, ref lv) => {
let lv_ty = lv.ty(mir, tcx).to_ty(tcx);
let lv_ty = lv.ty(local_decls, tcx).to_ty(tcx);
tcx.mk_ref(reg,
ty::TypeAndMut {
ty: lv_ty,
@ -156,22 +159,22 @@ impl<'tcx> Rvalue<'tcx> {
Rvalue::Len(..) => tcx.types.usize,
Rvalue::Cast(.., ty) => ty,
Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
let lhs_ty = lhs.ty(mir, tcx);
let rhs_ty = rhs.ty(mir, tcx);
let lhs_ty = lhs.ty(local_decls, tcx);
let rhs_ty = rhs.ty(local_decls, tcx);
op.ty(tcx, lhs_ty, rhs_ty)
}
Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) => {
let lhs_ty = lhs.ty(mir, tcx);
let rhs_ty = rhs.ty(mir, tcx);
let lhs_ty = lhs.ty(local_decls, tcx);
let rhs_ty = rhs.ty(local_decls, tcx);
let ty = op.ty(tcx, lhs_ty, rhs_ty);
tcx.intern_tup(&[ty, tcx.types.bool], false)
}
Rvalue::UnaryOp(UnOp::Not, ref operand) |
Rvalue::UnaryOp(UnOp::Neg, ref operand) => {
operand.ty(mir, tcx)
operand.ty(local_decls, tcx)
}
Rvalue::Discriminant(ref lval) => {
let ty = lval.ty(mir, tcx).to_ty(tcx);
let ty = lval.ty(local_decls, tcx).to_ty(tcx);
if let ty::TyAdt(adt_def, _) = ty.sty {
adt_def.repr.discr_type().to_ty(tcx)
} else {
@ -189,7 +192,7 @@ impl<'tcx> Rvalue<'tcx> {
}
AggregateKind::Tuple => {
tcx.mk_tup(
ops.iter().map(|op| op.ty(mir, tcx)),
ops.iter().map(|op| op.ty(local_decls, tcx)),
false
)
}
@ -206,9 +209,11 @@ impl<'tcx> Rvalue<'tcx> {
}
impl<'tcx> Operand<'tcx> {
pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
pub fn ty<'a, 'gcx, D>(&self, local_decls: &D, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx>
where D: HasLocalDecls<'tcx>
{
match self {
&Operand::Consume(ref l) => l.ty(mir, tcx).to_ty(tcx),
&Operand::Consume(ref l) => l.ty(local_decls, tcx).to_ty(tcx),
&Operand::Constant(ref c) => c.ty,
}
}

View File

@ -250,7 +250,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
work_list.push(target);
// If the location doesn't actually need dropping, treat it like
// a regular goto.
let ty = location.ty(&callee_mir, tcx).subst(tcx, callsite.substs);
let ty = location.ty(callee_mir, tcx).subst(tcx, callsite.substs);
let ty = ty.to_ty(tcx);
if ty.needs_drop(tcx, param_env) {
cost += CALL_PENALTY;

View File

@ -263,7 +263,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
}
mir::TerminatorKind::Drop { ref location, target, unwind } => {
let ty = location.ty(&self.mir, bcx.tcx()).to_ty(bcx.tcx());
let ty = location.ty(self.mir, bcx.tcx()).to_ty(bcx.tcx());
let ty = self.monomorphize(&ty);
let drop_fn = monomorphize::resolve_drop_in_place(bcx.ccx.shared(), ty);
@ -438,7 +438,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
let extra_args = &args[sig.inputs().len()..];
let extra_args = extra_args.iter().map(|op_arg| {
let op_ty = op_arg.ty(&self.mir, bcx.tcx());
let op_ty = op_arg.ty(self.mir, bcx.tcx());
self.monomorphize(&op_ty)
}).collect::<Vec<_>>();

View File

@ -408,7 +408,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
pub fn monomorphized_lvalue_ty(&self, lvalue: &mir::Lvalue<'tcx>) -> Ty<'tcx> {
let tcx = self.ccx.tcx();
let lvalue_ty = lvalue.ty(&self.mir, tcx);
let lvalue_ty = lvalue.ty(self.mir, tcx);
self.monomorphize(&lvalue_ty.to_ty(tcx))
}
}