use syntax_pos::Span;
use super::cache::Cache;
+use super::super::ty::TyCtxt;
+use super::tcx::LvalueTy;
macro_rules! newtype_index {
($name:ident, $debug_name:expr) => (
elem: elem,
}))
}
+
+ pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> LvalueTy<'tcx>
+ {
+ match self {
+ &Lvalue::Var(index) =>
+ LvalueTy::Ty { ty: mir.var_decls[index].ty },
+ &Lvalue::Temp(index) =>
+ LvalueTy::Ty { ty: mir.temp_decls[index].ty },
+ &Lvalue::Arg(index) =>
+ LvalueTy::Ty { ty: mir.arg_decls[index].ty },
+ &Lvalue::Static(def_id) =>
+ LvalueTy::Ty { ty: tcx.lookup_item_type(def_id).ty },
+ &Lvalue::ReturnPointer =>
+ LvalueTy::Ty { ty: mir.return_ty.unwrap() },
+ &Lvalue::Projection(ref proj) =>
+ proj.base.ty(mir, tcx).projection_ty(tcx, &proj.elem),
+ }
+ }
}
+
+
+
impl<'tcx> Debug for Lvalue<'tcx> {
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
use self::Lvalue::*;
-> Ty<'tcx>
{
match *operand {
- Operand::Consume(ref l) => self.lvalue_ty(tcx, l).to_ty(tcx),
+ Operand::Consume(ref l) => l.ty(self, tcx).to_ty(tcx),
Operand::Constant(ref c) => c.ty,
}
}
}
}
- pub fn lvalue_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
- lvalue: &Lvalue<'tcx>)
- -> LvalueTy<'tcx>
- {
- match *lvalue {
- Lvalue::Var(index) =>
- LvalueTy::Ty { ty: self.var_decls[index].ty },
- Lvalue::Temp(index) =>
- LvalueTy::Ty { ty: self.temp_decls[index].ty },
- Lvalue::Arg(index) =>
- LvalueTy::Ty { ty: self.arg_decls[index].ty },
- Lvalue::Static(def_id) =>
- LvalueTy::Ty { ty: tcx.lookup_item_type(def_id).ty },
- Lvalue::ReturnPointer =>
- LvalueTy::Ty { ty: self.return_ty.unwrap() },
- Lvalue::Projection(ref proj) =>
- self.lvalue_ty(tcx, &proj.base).projection_ty(tcx, &proj.elem)
- }
- }
-
pub fn rvalue_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
rvalue: &Rvalue<'tcx>)
-> Option<Ty<'tcx>>
Some(tcx.mk_array(op_ty, count as usize))
}
Rvalue::Ref(reg, bk, ref lv) => {
- let lv_ty = self.lvalue_ty(tcx, lv).to_ty(tcx);
+ let lv_ty = lv.ty(self, tcx).to_ty(tcx);
Some(tcx.mk_ref(
tcx.mk_region(reg),
ty::TypeAndMut {
{
match self.move_data().move_paths[path].content {
MovePathContent::Lvalue(ref lvalue) => {
- let ty = self.mir.lvalue_ty(self.tcx, lvalue).to_ty(self.tcx);
+ let ty = lvalue.ty(self.mir, self.tcx).to_ty(self.tcx);
debug!("path_needs_drop({:?}, {:?} : {:?})", path, lvalue, ty);
self.tcx.type_needs_drop_given_env(ty, self.param_env())
let mut fields = fields;
fields.retain(|&(ref lvalue, _)| {
- let ty = self.mir.lvalue_ty(self.tcx, lvalue).to_ty(self.tcx);
+ let ty = lvalue.ty(self.mir, self.tcx).to_ty(self.tcx);
self.tcx.type_needs_drop_given_env(ty, self.param_env())
});
/// This creates a "drop ladder" that drops the needed fields of the
/// ADT, both in the success case or if one of the destructors fail.
fn open_drop<'a>(&mut self, c: &DropCtxt<'a, 'tcx>) -> BasicBlock {
- let ty = self.mir.lvalue_ty(self.tcx, c.lvalue).to_ty(self.tcx);
+ let ty = c.lvalue.ty(self.mir, self.tcx).to_ty(self.tcx);
match ty.sty {
ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
self.open_drop_for_adt(c, def, substs)
// dataflow can create unneeded children in some cases
// - be sure to ignore them.
- let ty = self.mir.lvalue_ty(self.tcx, c.lvalue).to_ty(self.tcx);
+ let ty = c.lvalue.ty(self.mir, self.tcx).to_ty(self.tcx);
match ty.sty {
ty::TyStruct(def, _) | ty::TyEnum(def, _) => {
fn lvalue_contents_drop_state_cannot_differ<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
mir: &Mir<'tcx>,
lv: &repr::Lvalue<'tcx>) -> bool {
- let ty = mir.lvalue_ty(tcx, lv).to_ty(tcx);
+ let ty = lv.ty(mir, tcx).to_ty(tcx);
match ty.sty {
ty::TyArray(..) | ty::TySlice(..) | ty::TyRef(..) | ty::TyRawPtr(..) => {
debug!("lvalue_contents_drop_state_cannot_differ lv: {:?} ty: {:?} refd => false",
// don't move out of non-Copy things
if let MovePathContent::Lvalue(ref lvalue) = move_data.move_paths[path].content {
- let ty = mir.lvalue_ty(tcx, lvalue).to_ty(tcx);
+ let ty = lvalue.ty(mir, tcx).to_ty(tcx);
if !ty.moves_by_default(tcx, param_env, DUMMY_SP) {
continue;
}
continue;
}
}
- (statement.source_info.span, mir.lvalue_ty(tcx, dest).to_ty(tcx))
+ (statement.source_info.span, dest.ty(mir, tcx).to_ty(tcx))
}
Candidate::ShuffleIndices(bb) => {
let terminator = mir[bb].terminator();
this.add(Qualif::STATIC);
}
- let base_ty = this.mir.lvalue_ty(this.tcx, &proj.base)
- .to_ty(this.tcx);
+ let base_ty = proj.base.ty(this.mir, this.tcx).to_ty(this.tcx);
if let ty::TyRawPtr(_) = base_ty.sty {
this.add(Qualif::NOT_CONST);
if this.mode != Mode::Fn {
"cannot refer to the interior of another \
static, use a constant instead");
}
- let ty = this.mir.lvalue_ty(this.tcx, lvalue)
- .to_ty(this.tcx);
+ let ty = lvalue.ty(this.mir, this.tcx).to_ty(this.tcx);
this.qualif.restrict(ty, this.tcx, &this.param_env);
}
self.add(Qualif::STATIC_REF);
}
- let ty = self.mir.lvalue_ty(self.tcx, lvalue).to_ty(self.tcx);
+ let ty = lvalue.ty(self.mir, self.tcx).to_ty(self.tcx);
if kind == BorrowKind::Mut {
// In theory, any zero-sized value could be borrowed
// mutably without consequences. However, only &mut []
} else {
// Be conservative about the returned value of a const fn.
let tcx = self.tcx;
- let ty = self.mir.lvalue_ty(tcx, dest).to_ty(tcx);
+ let ty = dest.ty(self.mir, tcx).to_ty(tcx);
self.qualif = Qualif::empty();
self.add_type(ty);
let tcx = self.tcx();
match stmt.kind {
StatementKind::Assign(ref lv, ref rv) => {
- let lv_ty = mir.lvalue_ty(tcx, lv).to_ty(tcx);
+ let lv_ty = lv.ty(mir, tcx).to_ty(tcx);
let rv_ty = mir.rvalue_ty(tcx, rv);
if let Some(rv_ty) = rv_ty {
if let Err(terr) = self.sub_types(self.last_span, rv_ty, lv_ty) {
ref value,
..
} => {
- let lv_ty = mir.lvalue_ty(tcx, location).to_ty(tcx);
+ let lv_ty = location.ty(mir, tcx).to_ty(tcx);
let rv_ty = mir.operand_ty(tcx, value);
if let Err(terr) = self.sub_types(self.last_span, rv_ty, lv_ty) {
span_mirbug!(self, term, "bad DropAndReplace ({:?} = {:?}): {:?}",
}
}
TerminatorKind::SwitchInt { ref discr, switch_ty, .. } => {
- let discr_ty = mir.lvalue_ty(tcx, discr).to_ty(tcx);
+ let discr_ty = discr.ty(mir, tcx).to_ty(tcx);
if let Err(terr) = self.sub_types(self.last_span, discr_ty, switch_ty) {
span_mirbug!(self, term, "bad SwitchInt ({:?} on {:?}): {:?}",
switch_ty, discr_ty, terr);
// FIXME: check the values
}
TerminatorKind::Switch { ref discr, adt_def, ref targets } => {
- let discr_ty = mir.lvalue_ty(tcx, discr).to_ty(tcx);
+ let discr_ty = discr.ty(mir, tcx).to_ty(tcx);
match discr_ty.sty {
ty::TyEnum(def, _)
if def == adt_def && adt_def.variants.len() == targets.len()
span_mirbug!(self, term, "call to diverging function {:?} with dest", sig);
}
(&Some((ref dest, _)), ty::FnConverging(ty)) => {
- let dest_ty = mir.lvalue_ty(tcx, dest).to_ty(tcx);
+ let dest_ty = dest.ty(mir, tcx).to_ty(tcx);
if let Err(terr) = self.sub_types(self.last_span, ty, dest_ty) {
span_mirbug!(self, term,
"call dest mismatch ({:?} <- {:?}): {:?}",
debug!("visiting lvalue {:?}", *lvalue);
if let mir_visit::LvalueContext::Drop = context {
- let ty = self.mir.lvalue_ty(self.scx.tcx(), lvalue)
- .to_ty(self.scx.tcx());
+ let ty = lvalue.ty(self.mir, self.scx.tcx())
+ .to_ty(self.scx.tcx());
let ty = monomorphize::apply_param_substs(self.scx.tcx(),
self.param_substs,
// Allow uses of projections of immediate pair fields.
if let mir::Lvalue::Projection(ref proj) = *lvalue {
if self.mir.local_index(&proj.base).is_some() {
- let ty = self.mir.lvalue_ty(self.bcx.tcx(), &proj.base);
+ let ty = proj.base.ty(self.mir, self.bcx.tcx());
+
let ty = self.bcx.monomorphize(&ty.to_ty(self.bcx.tcx()));
if common::type_is_imm_pair(self.bcx.ccx(), ty) {
if let mir::ProjectionElem::Field(..) = proj.elem {
self.mark_as_lvalue(index);
}
LvalueContext::Drop => {
- let ty = self.mir.lvalue_ty(self.bcx.tcx(), lvalue);
+ let ty = lvalue.ty(self.mir, self.bcx.tcx());
let ty = self.bcx.monomorphize(&ty.to_ty(self.bcx.tcx()));
// Only need the lvalue if we're actually dropping it.
}
mir::TerminatorKind::Drop { ref location, target, unwind } => {
- let ty = mir.lvalue_ty(bcx.tcx(), location).to_ty(bcx.tcx());
+ let ty = location.ty(&mir, bcx.tcx()).to_ty(bcx.tcx());
let ty = bcx.monomorphize(&ty);
// Double check for necessity to drop
return ReturnDest::Nothing;
}
let dest = if let Some(index) = self.mir.local_index(dest) {
- let ret_ty = self.lvalue_ty(dest);
+ let ret_ty = self.monomorphized_lvalue_ty(dest);
match self.locals[index] {
LocalRef::Lvalue(dest) => dest,
LocalRef::Operand(None) => {
let span = statement.source_info.span;
match statement.kind {
mir::StatementKind::Assign(ref dest, ref rvalue) => {
- let ty = self.mir.lvalue_ty(tcx, dest);
+ let ty = dest.ty(self.mir, tcx);
let ty = self.monomorphize(&ty).to_ty(tcx);
match self.const_rvalue(rvalue, ty, span) {
Ok(value) => self.store(dest, value, span),
ConstLvalue {
base: Base::Static(consts::get_static(self.ccx, def_id).val),
llextra: ptr::null_mut(),
- ty: self.mir.lvalue_ty(tcx, lvalue).to_ty(tcx)
+ ty: lvalue.ty(self.mir, tcx).to_ty(tcx)
}
}
mir::Lvalue::Projection(ref projection) => {
mir::Lvalue::Arg(_) |
mir::Lvalue::ReturnPointer => bug!(), // handled above
mir::Lvalue::Static(def_id) => {
- let const_ty = self.lvalue_ty(lvalue);
+ let const_ty = self.monomorphized_lvalue_ty(lvalue);
LvalueRef::new_sized(consts::get_static(ccx, def_id).val,
LvalueTy::from_ty(const_ty))
},
ty::TyArray(..) => {
// must cast the lvalue pointer type to the new
// array type (*[%_; new_len]).
- let base_ty = self.lvalue_ty(lvalue);
+ let base_ty = self.monomorphized_lvalue_ty(lvalue);
let llbasety = type_of::type_of(bcx.ccx(), base_ty).ptr_to();
let llbase = bcx.pointercast(llbase, llbasety);
(llbase, ptr::null_mut())
match self.locals[index] {
LocalRef::Lvalue(lvalue) => f(self, lvalue),
LocalRef::Operand(None) => {
- let lvalue_ty = self.lvalue_ty(lvalue);
+ let lvalue_ty = self.monomorphized_lvalue_ty(lvalue);
let lvalue = LvalueRef::alloca(bcx,
lvalue_ty,
"lvalue_temp");
LocalRef::Operand(Some(_)) => {
// See comments in LocalRef::new_operand as to why
// we always have Some in a ZST LocalRef::Operand.
- let ty = self.lvalue_ty(lvalue);
+ let ty = self.monomorphized_lvalue_ty(lvalue);
if common::type_is_zero_size(bcx.ccx(), ty) {
// Pass an undef pointer as no stores can actually occur.
let llptr = C_undef(type_of(bcx.ccx(), ty).ptr_to());
}
}
- pub fn lvalue_ty(&self, lvalue: &mir::Lvalue<'tcx>) -> Ty<'tcx> {
+ pub fn monomorphized_lvalue_ty(&self, lvalue: &mir::Lvalue<'tcx>) -> Ty<'tcx> {
let tcx = self.fcx.ccx.tcx();
- let lvalue_ty = self.mir.lvalue_ty(tcx, lvalue);
+ let lvalue_ty = lvalue.ty(&self.mir, tcx);
self.fcx.monomorphize(&lvalue_ty.to_ty(tcx))
}
}
bcx
}
LocalRef::Operand(Some(_)) => {
- let ty = self.lvalue_ty(lvalue);
+ let ty = self.monomorphized_lvalue_ty(lvalue);
if !common::type_is_zero_size(bcx.ccx(), ty) {
span_bug!(statement.source_info.span,