Skip to content

Commit 42001ed

Browse files
authored
Auto merge of #35403 - scottcarr:lvalue_refactor, r=nikomatsakis
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`.
2 parents 695b3d8 + f37bf6d commit 42001ed

File tree

13 files changed

+129
-134
lines changed

13 files changed

+129
-134
lines changed

src/librustc/mir/tcx.rs

+73-77
Original file line numberDiff line numberDiff line change
@@ -113,75 +113,38 @@ impl<'tcx> TypeFoldable<'tcx> for LvalueTy<'tcx> {
113113
}
114114
}
115115

116-
impl<'a, 'gcx, 'tcx> Mir<'tcx> {
117-
pub fn operand_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
118-
operand: &Operand<'tcx>)
119-
-> Ty<'tcx>
120-
{
121-
match *operand {
122-
Operand::Consume(ref l) => self.lvalue_ty(tcx, l).to_ty(tcx),
123-
Operand::Constant(ref c) => c.ty,
124-
}
125-
}
126-
127-
pub fn binop_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
128-
op: BinOp,
129-
lhs_ty: Ty<'tcx>,
130-
rhs_ty: Ty<'tcx>)
131-
-> Ty<'tcx>
132-
{
133-
// FIXME: handle SIMD correctly
134-
match op {
135-
BinOp::Add | BinOp::Sub | BinOp::Mul | BinOp::Div | BinOp::Rem |
136-
BinOp::BitXor | BinOp::BitAnd | BinOp::BitOr => {
137-
// these should be integers or floats of the same size.
138-
assert_eq!(lhs_ty, rhs_ty);
139-
lhs_ty
140-
}
141-
BinOp::Shl | BinOp::Shr => {
142-
lhs_ty // lhs_ty can be != rhs_ty
143-
}
144-
BinOp::Eq | BinOp::Lt | BinOp::Le |
145-
BinOp::Ne | BinOp::Ge | BinOp::Gt => {
146-
tcx.types.bool
147-
}
148-
}
149-
}
150-
151-
pub fn lvalue_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
152-
lvalue: &Lvalue<'tcx>)
153-
-> LvalueTy<'tcx>
154-
{
155-
match *lvalue {
156-
Lvalue::Var(index) =>
157-
LvalueTy::Ty { ty: self.var_decls[index].ty },
158-
Lvalue::Temp(index) =>
159-
LvalueTy::Ty { ty: self.temp_decls[index].ty },
160-
Lvalue::Arg(index) =>
161-
LvalueTy::Ty { ty: self.arg_decls[index].ty },
162-
Lvalue::Static(def_id) =>
116+
impl<'tcx> Lvalue<'tcx> {
117+
pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> LvalueTy<'tcx> {
118+
match self {
119+
&Lvalue::Var(index) =>
120+
LvalueTy::Ty { ty: mir.var_decls[index].ty },
121+
&Lvalue::Temp(index) =>
122+
LvalueTy::Ty { ty: mir.temp_decls[index].ty },
123+
&Lvalue::Arg(index) =>
124+
LvalueTy::Ty { ty: mir.arg_decls[index].ty },
125+
&Lvalue::Static(def_id) =>
163126
LvalueTy::Ty { ty: tcx.lookup_item_type(def_id).ty },
164-
Lvalue::ReturnPointer =>
165-
LvalueTy::Ty { ty: self.return_ty.unwrap() },
166-
Lvalue::Projection(ref proj) =>
167-
self.lvalue_ty(tcx, &proj.base).projection_ty(tcx, &proj.elem)
127+
&Lvalue::ReturnPointer =>
128+
LvalueTy::Ty { ty: mir.return_ty.unwrap() },
129+
&Lvalue::Projection(ref proj) =>
130+
proj.base.ty(mir, tcx).projection_ty(tcx, &proj.elem),
168131
}
169132
}
133+
}
170134

171-
pub fn rvalue_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
172-
rvalue: &Rvalue<'tcx>)
173-
-> Option<Ty<'tcx>>
135+
impl<'tcx> Rvalue<'tcx> {
136+
pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Ty<'tcx>>
174137
{
175-
match *rvalue {
176-
Rvalue::Use(ref operand) => Some(self.operand_ty(tcx, operand)),
177-
Rvalue::Repeat(ref operand, ref count) => {
178-
let op_ty = self.operand_ty(tcx, operand);
138+
match self {
139+
&Rvalue::Use(ref operand) => Some(operand.ty(mir, tcx)),
140+
&Rvalue::Repeat(ref operand, ref count) => {
141+
let op_ty = operand.ty(mir, tcx);
179142
let count = count.value.as_u64(tcx.sess.target.uint_type);
180143
assert_eq!(count as usize as u64, count);
181144
Some(tcx.mk_array(op_ty, count as usize))
182145
}
183-
Rvalue::Ref(reg, bk, ref lv) => {
184-
let lv_ty = self.lvalue_ty(tcx, lv).to_ty(tcx);
146+
&Rvalue::Ref(reg, bk, ref lv) => {
147+
let lv_ty = lv.ty(mir, tcx).to_ty(tcx);
185148
Some(tcx.mk_ref(
186149
tcx.mk_region(reg),
187150
ty::TypeAndMut {
@@ -190,39 +153,39 @@ impl<'a, 'gcx, 'tcx> Mir<'tcx> {
190153
}
191154
))
192155
}
193-
Rvalue::Len(..) => Some(tcx.types.usize),
194-
Rvalue::Cast(_, _, ty) => Some(ty),
195-
Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
196-
let lhs_ty = self.operand_ty(tcx, lhs);
197-
let rhs_ty = self.operand_ty(tcx, rhs);
198-
Some(self.binop_ty(tcx, op, lhs_ty, rhs_ty))
156+
&Rvalue::Len(..) => Some(tcx.types.usize),
157+
&Rvalue::Cast(_, _, ty) => Some(ty),
158+
&Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
159+
let lhs_ty = lhs.ty(mir, tcx);
160+
let rhs_ty = rhs.ty(mir, tcx);
161+
Some(op.ty(tcx, lhs_ty, rhs_ty))
199162
}
200-
Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) => {
201-
let lhs_ty = self.operand_ty(tcx, lhs);
202-
let rhs_ty = self.operand_ty(tcx, rhs);
203-
let ty = self.binop_ty(tcx, op, lhs_ty, rhs_ty);
163+
&Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) => {
164+
let lhs_ty = lhs.ty(mir, tcx);
165+
let rhs_ty = rhs.ty(mir, tcx);
166+
let ty = op.ty(tcx, lhs_ty, rhs_ty);
204167
let ty = tcx.mk_tup(vec![ty, tcx.types.bool]);
205168
Some(ty)
206169
}
207-
Rvalue::UnaryOp(_, ref operand) => {
208-
Some(self.operand_ty(tcx, operand))
170+
&Rvalue::UnaryOp(_, ref operand) => {
171+
Some(operand.ty(mir, tcx))
209172
}
210-
Rvalue::Box(t) => {
173+
&Rvalue::Box(t) => {
211174
Some(tcx.mk_box(t))
212175
}
213-
Rvalue::Aggregate(ref ak, ref ops) => {
176+
&Rvalue::Aggregate(ref ak, ref ops) => {
214177
match *ak {
215178
AggregateKind::Vec => {
216179
if let Some(operand) = ops.get(0) {
217-
let ty = self.operand_ty(tcx, operand);
180+
let ty = operand.ty(mir, tcx);
218181
Some(tcx.mk_array(ty, ops.len()))
219182
} else {
220183
None
221184
}
222185
}
223186
AggregateKind::Tuple => {
224187
Some(tcx.mk_tup(
225-
ops.iter().map(|op| self.operand_ty(tcx, op)).collect()
188+
ops.iter().map(|op| op.ty(mir, tcx)).collect()
226189
))
227190
}
228191
AggregateKind::Adt(def, _, substs) => {
@@ -233,7 +196,40 @@ impl<'a, 'gcx, 'tcx> Mir<'tcx> {
233196
}
234197
}
235198
}
236-
Rvalue::InlineAsm { .. } => None
199+
&Rvalue::InlineAsm { .. } => None
200+
}
201+
}
202+
}
203+
204+
impl<'tcx> Operand<'tcx> {
205+
pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
206+
match self {
207+
&Operand::Consume(ref l) => l.ty(mir, tcx).to_ty(tcx),
208+
&Operand::Constant(ref c) => c.ty,
209+
}
210+
}
211+
}
212+
213+
impl<'tcx> BinOp {
214+
pub fn ty<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
215+
lhs_ty: Ty<'tcx>,
216+
rhs_ty: Ty<'tcx>)
217+
-> Ty<'tcx> {
218+
// FIXME: handle SIMD correctly
219+
match self {
220+
&BinOp::Add | &BinOp::Sub | &BinOp::Mul | &BinOp::Div | &BinOp::Rem |
221+
&BinOp::BitXor | &BinOp::BitAnd | &BinOp::BitOr => {
222+
// these should be integers or floats of the same size.
223+
assert_eq!(lhs_ty, rhs_ty);
224+
lhs_ty
225+
}
226+
&BinOp::Shl | &BinOp::Shr => {
227+
lhs_ty // lhs_ty can be != rhs_ty
228+
}
229+
&BinOp::Eq | &BinOp::Lt | &BinOp::Le |
230+
&BinOp::Ne | &BinOp::Ge | &BinOp::Gt => {
231+
tcx.types.bool
232+
}
237233
}
238234
}
239235
}

src/librustc_borrowck/borrowck/mir/elaborate_drops.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
185185
{
186186
match self.move_data().move_paths[path].content {
187187
MovePathContent::Lvalue(ref lvalue) => {
188-
let ty = self.mir.lvalue_ty(self.tcx, lvalue).to_ty(self.tcx);
188+
let ty = lvalue.ty(self.mir, self.tcx).to_ty(self.tcx);
189189
debug!("path_needs_drop({:?}, {:?} : {:?})", path, lvalue, ty);
190190

191191
self.tcx.type_needs_drop_given_env(ty, self.param_env())
@@ -555,7 +555,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
555555

556556
let mut fields = fields;
557557
fields.retain(|&(ref lvalue, _)| {
558-
let ty = self.mir.lvalue_ty(self.tcx, lvalue).to_ty(self.tcx);
558+
let ty = lvalue.ty(self.mir, self.tcx).to_ty(self.tcx);
559559
self.tcx.type_needs_drop_given_env(ty, self.param_env())
560560
});
561561

@@ -706,7 +706,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
706706
/// This creates a "drop ladder" that drops the needed fields of the
707707
/// ADT, both in the success case or if one of the destructors fail.
708708
fn open_drop<'a>(&mut self, c: &DropCtxt<'a, 'tcx>) -> BasicBlock {
709-
let ty = self.mir.lvalue_ty(self.tcx, c.lvalue).to_ty(self.tcx);
709+
let ty = c.lvalue.ty(self.mir, self.tcx).to_ty(self.tcx);
710710
match ty.sty {
711711
ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
712712
self.open_drop_for_adt(c, def, substs)
@@ -892,7 +892,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
892892
// dataflow can create unneeded children in some cases
893893
// - be sure to ignore them.
894894

895-
let ty = self.mir.lvalue_ty(self.tcx, c.lvalue).to_ty(self.tcx);
895+
let ty = c.lvalue.ty(self.mir, self.tcx).to_ty(self.tcx);
896896

897897
match ty.sty {
898898
ty::TyStruct(def, _) | ty::TyEnum(def, _) => {

src/librustc_borrowck/borrowck/mir/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ fn move_path_children_matching<'tcx, F>(move_paths: &MovePathData<'tcx>,
256256
fn lvalue_contents_drop_state_cannot_differ<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
257257
mir: &Mir<'tcx>,
258258
lv: &repr::Lvalue<'tcx>) -> bool {
259-
let ty = mir.lvalue_ty(tcx, lv).to_ty(tcx);
259+
let ty = lv.ty(mir, tcx).to_ty(tcx);
260260
match ty.sty {
261261
ty::TyArray(..) | ty::TySlice(..) | ty::TyRef(..) | ty::TyRawPtr(..) => {
262262
debug!("lvalue_contents_drop_state_cannot_differ lv: {:?} ty: {:?} refd => false",
@@ -355,7 +355,7 @@ fn drop_flag_effects_for_location<'a, 'tcx, F>(
355355

356356
// don't move out of non-Copy things
357357
if let MovePathContent::Lvalue(ref lvalue) = move_data.move_paths[path].content {
358-
let ty = mir.lvalue_ty(tcx, lvalue).to_ty(tcx);
358+
let ty = lvalue.ty(mir, tcx).to_ty(tcx);
359359
if !ty.moves_by_default(tcx, param_env, DUMMY_SP) {
360360
continue;
361361
}

src/librustc_mir/transform/promote_consts.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -347,13 +347,13 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
347347
continue;
348348
}
349349
}
350-
(statement.source_info.span, mir.lvalue_ty(tcx, dest).to_ty(tcx))
350+
(statement.source_info.span, dest.ty(mir, tcx).to_ty(tcx))
351351
}
352352
Candidate::ShuffleIndices(bb) => {
353353
let terminator = mir[bb].terminator();
354354
let ty = match terminator.kind {
355355
TerminatorKind::Call { ref args, .. } => {
356-
mir.operand_ty(tcx, &args[2])
356+
args[2].ty(mir, tcx)
357357
}
358358
_ => {
359359
span_bug!(terminator.source_info.span,

src/librustc_mir/transform/qualify_consts.rs

+8-10
Original file line numberDiff line numberDiff line change
@@ -486,8 +486,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
486486
this.add(Qualif::STATIC);
487487
}
488488

489-
let base_ty = this.mir.lvalue_ty(this.tcx, &proj.base)
490-
.to_ty(this.tcx);
489+
let base_ty = proj.base.ty(this.mir, this.tcx).to_ty(this.tcx);
491490
if let ty::TyRawPtr(_) = base_ty.sty {
492491
this.add(Qualif::NOT_CONST);
493492
if this.mode != Mode::Fn {
@@ -506,8 +505,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
506505
"cannot refer to the interior of another \
507506
static, use a constant instead");
508507
}
509-
let ty = this.mir.lvalue_ty(this.tcx, lvalue)
510-
.to_ty(this.tcx);
508+
let ty = lvalue.ty(this.mir, this.tcx).to_ty(this.tcx);
511509
this.qualif.restrict(ty, this.tcx, &this.param_env);
512510
}
513511

@@ -592,7 +590,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
592590
self.add(Qualif::STATIC_REF);
593591
}
594592

595-
let ty = self.mir.lvalue_ty(self.tcx, lvalue).to_ty(self.tcx);
593+
let ty = lvalue.ty(self.mir, self.tcx).to_ty(self.tcx);
596594
if kind == BorrowKind::Mut {
597595
// In theory, any zero-sized value could be borrowed
598596
// mutably without consequences. However, only &mut []
@@ -652,7 +650,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
652650
}
653651

654652
Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) => {
655-
let operand_ty = self.mir.operand_ty(self.tcx, operand);
653+
let operand_ty = operand.ty(self.mir, self.tcx);
656654
let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast");
657655
let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
658656
match (cast_in, cast_out) {
@@ -670,7 +668,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
670668
}
671669

672670
Rvalue::BinaryOp(op, ref lhs, _) => {
673-
if let ty::TyRawPtr(_) = self.mir.operand_ty(self.tcx, lhs).sty {
671+
if let ty::TyRawPtr(_) = lhs.ty(self.mir, self.tcx).sty {
674672
assert!(op == BinOp::Eq || op == BinOp::Ne ||
675673
op == BinOp::Le || op == BinOp::Lt ||
676674
op == BinOp::Ge || op == BinOp::Gt);
@@ -702,7 +700,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
702700
}
703701

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

727-
let fn_ty = self.mir.operand_ty(self.tcx, func);
725+
let fn_ty = func.ty(self.mir, self.tcx);
728726
let (is_shuffle, is_const_fn) = match fn_ty.sty {
729727
ty::TyFnDef(def_id, _, f) => {
730728
(f.abi == Abi::PlatformIntrinsic &&
@@ -804,7 +802,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
804802
} else {
805803
// Be conservative about the returned value of a const fn.
806804
let tcx = self.tcx;
807-
let ty = self.mir.lvalue_ty(tcx, dest).to_ty(tcx);
805+
let ty = dest.ty(self.mir, tcx).to_ty(tcx);
808806
self.qualif = Qualif::empty();
809807
self.add_type(ty);
810808

0 commit comments

Comments
 (0)