Skip to content

refactor lvalue_ty to be method of lvalue #35403

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 11, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 73 additions & 77 deletions src/librustc/mir/tcx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,75 +113,38 @@ impl<'tcx> TypeFoldable<'tcx> for LvalueTy<'tcx> {
}
}

impl<'a, 'gcx, 'tcx> Mir<'tcx> {
pub fn operand_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
operand: &Operand<'tcx>)
-> Ty<'tcx>
{
match *operand {
Operand::Consume(ref l) => self.lvalue_ty(tcx, l).to_ty(tcx),
Operand::Constant(ref c) => c.ty,
}
}

pub fn binop_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
op: BinOp,
lhs_ty: Ty<'tcx>,
rhs_ty: Ty<'tcx>)
-> Ty<'tcx>
{
// FIXME: handle SIMD correctly
match op {
BinOp::Add | BinOp::Sub | BinOp::Mul | BinOp::Div | BinOp::Rem |
BinOp::BitXor | BinOp::BitAnd | BinOp::BitOr => {
// these should be integers or floats of the same size.
assert_eq!(lhs_ty, rhs_ty);
lhs_ty
}
BinOp::Shl | BinOp::Shr => {
lhs_ty // lhs_ty can be != rhs_ty
}
BinOp::Eq | BinOp::Lt | BinOp::Le |
BinOp::Ne | BinOp::Ge | BinOp::Gt => {
tcx.types.bool
}
}
}

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) =>
impl<'tcx> Lvalue<'tcx> {
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: self.return_ty.unwrap() },
Lvalue::Projection(ref proj) =>
self.lvalue_ty(tcx, &proj.base).projection_ty(tcx, &proj.elem)
&Lvalue::ReturnPointer =>
LvalueTy::Ty { ty: mir.return_ty.unwrap() },
&Lvalue::Projection(ref proj) =>
proj.base.ty(mir, tcx).projection_ty(tcx, &proj.elem),
}
}
}

pub fn rvalue_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
rvalue: &Rvalue<'tcx>)
-> Option<Ty<'tcx>>
impl<'tcx> Rvalue<'tcx> {
pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Ty<'tcx>>
{
match *rvalue {
Rvalue::Use(ref operand) => Some(self.operand_ty(tcx, operand)),
Rvalue::Repeat(ref operand, ref count) => {
let op_ty = self.operand_ty(tcx, operand);
match self {
&Rvalue::Use(ref operand) => Some(operand.ty(mir, tcx)),
&Rvalue::Repeat(ref operand, ref count) => {
let op_ty = operand.ty(mir, tcx);
let count = count.value.as_u64(tcx.sess.target.uint_type);
assert_eq!(count as usize as u64, count);
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);
&Rvalue::Ref(reg, bk, ref lv) => {
let lv_ty = lv.ty(mir, tcx).to_ty(tcx);
Some(tcx.mk_ref(
tcx.mk_region(reg),
ty::TypeAndMut {
Expand All @@ -190,39 +153,39 @@ impl<'a, 'gcx, 'tcx> Mir<'tcx> {
}
))
}
Rvalue::Len(..) => Some(tcx.types.usize),
Rvalue::Cast(_, _, ty) => Some(ty),
Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
let lhs_ty = self.operand_ty(tcx, lhs);
let rhs_ty = self.operand_ty(tcx, rhs);
Some(self.binop_ty(tcx, op, lhs_ty, rhs_ty))
&Rvalue::Len(..) => Some(tcx.types.usize),
&Rvalue::Cast(_, _, ty) => Some(ty),
&Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
let lhs_ty = lhs.ty(mir, tcx);
let rhs_ty = rhs.ty(mir, tcx);
Some(op.ty(tcx, lhs_ty, rhs_ty))
}
Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) => {
let lhs_ty = self.operand_ty(tcx, lhs);
let rhs_ty = self.operand_ty(tcx, rhs);
let ty = self.binop_ty(tcx, op, 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 ty = op.ty(tcx, lhs_ty, rhs_ty);
let ty = tcx.mk_tup(vec![ty, tcx.types.bool]);
Some(ty)
}
Rvalue::UnaryOp(_, ref operand) => {
Some(self.operand_ty(tcx, operand))
&Rvalue::UnaryOp(_, ref operand) => {
Some(operand.ty(mir, tcx))
}
Rvalue::Box(t) => {
&Rvalue::Box(t) => {
Some(tcx.mk_box(t))
}
Rvalue::Aggregate(ref ak, ref ops) => {
&Rvalue::Aggregate(ref ak, ref ops) => {
match *ak {
AggregateKind::Vec => {
if let Some(operand) = ops.get(0) {
let ty = self.operand_ty(tcx, operand);
let ty = operand.ty(mir, tcx);
Some(tcx.mk_array(ty, ops.len()))
} else {
None
}
}
AggregateKind::Tuple => {
Some(tcx.mk_tup(
ops.iter().map(|op| self.operand_ty(tcx, op)).collect()
ops.iter().map(|op| op.ty(mir, tcx)).collect()
))
}
AggregateKind::Adt(def, _, substs) => {
Expand All @@ -233,7 +196,40 @@ impl<'a, 'gcx, 'tcx> Mir<'tcx> {
}
}
}
Rvalue::InlineAsm { .. } => None
&Rvalue::InlineAsm { .. } => None
}
}
}

impl<'tcx> Operand<'tcx> {
pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
match self {
&Operand::Consume(ref l) => l.ty(mir, tcx).to_ty(tcx),
&Operand::Constant(ref c) => c.ty,
}
}
}

impl<'tcx> BinOp {
pub fn ty<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
lhs_ty: Ty<'tcx>,
rhs_ty: Ty<'tcx>)
-> Ty<'tcx> {
// FIXME: handle SIMD correctly
match self {
&BinOp::Add | &BinOp::Sub | &BinOp::Mul | &BinOp::Div | &BinOp::Rem |
&BinOp::BitXor | &BinOp::BitAnd | &BinOp::BitOr => {
// these should be integers or floats of the same size.
assert_eq!(lhs_ty, rhs_ty);
lhs_ty
}
&BinOp::Shl | &BinOp::Shr => {
lhs_ty // lhs_ty can be != rhs_ty
}
&BinOp::Eq | &BinOp::Lt | &BinOp::Le |
&BinOp::Ne | &BinOp::Ge | &BinOp::Gt => {
tcx.types.bool
}
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
{
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())
Expand Down Expand Up @@ -555,7 +555,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {

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())
});

Expand Down Expand Up @@ -706,7 +706,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
/// 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)
Expand Down Expand Up @@ -892,7 +892,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
// 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, _) => {
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_borrowck/borrowck/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ fn move_path_children_matching<'tcx, F>(move_paths: &MovePathData<'tcx>,
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",
Expand Down Expand Up @@ -355,7 +355,7 @@ fn drop_flag_effects_for_location<'a, 'tcx, F>(

// 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;
}
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_mir/transform/promote_consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,13 +347,13 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
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();
let ty = match terminator.kind {
TerminatorKind::Call { ref args, .. } => {
mir.operand_ty(tcx, &args[2])
args[2].ty(mir, tcx)
}
_ => {
span_bug!(terminator.source_info.span,
Expand Down
18 changes: 8 additions & 10 deletions src/librustc_mir/transform/qualify_consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -485,8 +485,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
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 {
Expand All @@ -505,8 +504,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
"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);
}

Expand Down Expand Up @@ -591,7 +589,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
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 []
Expand Down Expand Up @@ -651,7 +649,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
}

Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) => {
let operand_ty = self.mir.operand_ty(self.tcx, operand);
let operand_ty = operand.ty(self.mir, self.tcx);
let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast");
let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
match (cast_in, cast_out) {
Expand All @@ -669,7 +667,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
}

Rvalue::BinaryOp(op, ref lhs, _) => {
if let ty::TyRawPtr(_) = self.mir.operand_ty(self.tcx, lhs).sty {
if let ty::TyRawPtr(_) = lhs.ty(self.mir, self.tcx).sty {
assert!(op == BinOp::Eq || op == BinOp::Ne ||
op == BinOp::Le || op == BinOp::Lt ||
op == BinOp::Ge || op == BinOp::Gt);
Expand Down Expand Up @@ -699,7 +697,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
}

if Some(def.did) == self.tcx.lang_items.unsafe_cell_type() {
let ty = self.mir.rvalue_ty(self.tcx, rvalue).unwrap();
let ty = rvalue.ty(self.mir, self.tcx).unwrap();
self.add_type(ty);
assert!(self.qualif.intersects(Qualif::MUTABLE_INTERIOR));
// Even if the value inside may not need dropping,
Expand All @@ -721,7 +719,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
if let TerminatorKind::Call { ref func, ref args, ref destination, .. } = *kind {
self.visit_operand(func);

let fn_ty = self.mir.operand_ty(self.tcx, func);
let fn_ty = func.ty(self.mir, self.tcx);
let (is_shuffle, is_const_fn) = match fn_ty.sty {
ty::TyFnDef(def_id, _, f) => {
(f.abi == Abi::PlatformIntrinsic &&
Expand Down Expand Up @@ -801,7 +799,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
} 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);

Expand Down
Loading