Skip to content

Commit

Permalink
Auto merge of rust-lang#35403 - scottcarr:lvalue_refactor, r=nikomats…
Browse files Browse the repository at this point in the history
…akis

refactor lvalue_ty to be method of lvalue

Currently `Mir` (and `MirContext`) implement a method `lvalue_ty` (and actually many more `foo_ty`).  But this should be a method of `Lvalue`.

If you have an `lvalue` and you want to get its type, the natural thing to write is:

```
lvalue.ty()
```

Of course it needs context, but still:

```
lvalue.ty(mir, tcx)
```

Makes more sense than

```
mir.lvalue_ty(lvalue, tcx)
```

I actually think we should go a step farther and have traits so we could get the type of some value generically, but that's up for debate.  The thing I'm running into a lot in the compiler is I have a value of type `Foo` and I know that there is some related type `Bar` which I can get through some combination of method calls, but it's often not as direct as I would imagine.  Unless you already know the code, its not clear why you would look in `Mir` for a method to get the type of an `Lvalue`.
  • Loading branch information
bors authored Aug 11, 2016
2 parents 695b3d8 + f37bf6d commit 42001ed
Show file tree
Hide file tree
Showing 13 changed files with 129 additions and 134 deletions.
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 @@ -486,8 +486,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 @@ -506,8 +505,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 @@ -592,7 +590,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 @@ -652,7 +650,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 @@ -670,7 +668,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 @@ -702,7 +700,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 @@ -724,7 +722,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 @@ -804,7 +802,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

0 comments on commit 42001ed

Please sign in to comment.