use rustc::middle::region::CodeExtent;
use rustc::hir::pat_util;
use rustc::ty::{self, VariantDef, Ty};
+use rustc::ty::cast::CastKind as TyCastKind;
use rustc::mir::repr::*;
use rustc::hir;
use syntax::ptr::P;
type Output = Expr<'tcx>;
fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
- debug!("Expr::make_mirror(): id={}, span={:?}", self.id, self.span);
-
- let expr_ty = cx.tcx.expr_ty(self); // note: no adjustments (yet)!
let temp_lifetime = cx.tcx.region_maps.temporary_scope(self.id);
let expr_extent = cx.tcx.region_maps.node_extent(self.id);
- let kind = match self.node {
- // Here comes the interesting stuff:
- hir::ExprMethodCall(_, _, ref args) => {
- // Rewrite a.b(c) into UFCS form like Trait::b(a, c)
- let expr = method_callee(cx, self, ty::MethodCall::expr(self.id));
- let args = args.iter()
- .map(|e| e.to_ref())
- .collect();
- ExprKind::Call {
- ty: expr.ty,
- fun: expr.to_ref(),
- args: args,
- }
- }
-
- hir::ExprCall(ref fun, ref args) => {
- if cx.tcx.is_method_call(self.id) {
- // The callee is something implementing Fn, FnMut, or FnOnce.
- // Find the actual method implementation being called and
- // build the appropriate UFCS call expression with the
- // callee-object as self parameter.
-
- // rewrite f(u, v) into FnOnce::call_once(f, (u, v))
-
- let method = method_callee(cx, self, ty::MethodCall::expr(self.id));
-
- let sig = match method.ty.sty {
- ty::TyFnDef(_, _, fn_ty) => &fn_ty.sig,
- _ => span_bug!(self.span, "type of method is not an fn")
- };
-
- let sig = cx.tcx.no_late_bound_regions(sig).unwrap_or_else(|| {
- span_bug!(self.span, "method call has late-bound regions")
- });
-
- assert_eq!(sig.inputs.len(), 2);
-
- let tupled_args = Expr {
- ty: sig.inputs[1],
- temp_lifetime: temp_lifetime,
- span: self.span,
- kind: ExprKind::Tuple {
- fields: args.iter().map(ToRef::to_ref).collect()
- }
- };
-
- ExprKind::Call {
- ty: method.ty,
- fun: method.to_ref(),
- args: vec![fun.to_ref(), tupled_args.to_ref()]
- }
- } else {
- let adt_data = if let hir::ExprPath(..) = fun.node {
- // Tuple-like ADTs are represented as ExprCall. We convert them here.
- expr_ty.ty_adt_def().and_then(|adt_def|{
- match cx.tcx.def_map.borrow()[&fun.id].full_def() {
- Def::Variant(_, variant_id) => {
- Some((adt_def, adt_def.variant_index_with_id(variant_id)))
- },
- Def::Struct(..) => {
- Some((adt_def, 0))
- },
- _ => None
- }
- })
- } else { None };
- if let Some((adt_def, index)) = adt_data {
- let substs = cx.tcx.mk_substs(cx.tcx.node_id_item_substs(fun.id).substs);
- let field_refs = args.iter().enumerate().map(|(idx, e)| FieldExprRef {
- name: Field::new(idx),
- expr: e.to_ref()
- }).collect();
- ExprKind::Adt {
- adt_def: adt_def,
- substs: substs,
- variant_index: index,
- fields: field_refs,
- base: None
- }
- } else {
- ExprKind::Call {
- ty: cx.tcx.node_id_to_type(fun.id),
- fun: fun.to_ref(),
- args: args.to_ref(),
- }
- }
- }
- }
-
- hir::ExprAddrOf(mutbl, ref expr) => {
- let region = match expr_ty.sty {
- ty::TyRef(r, _) => r,
- _ => span_bug!(expr.span, "type of & not region"),
- };
- ExprKind::Borrow {
- region: *region,
- borrow_kind: to_borrow_kind(mutbl),
- arg: expr.to_ref(),
- }
- }
-
- hir::ExprBlock(ref blk) => {
- ExprKind::Block { body: &blk }
- }
-
- hir::ExprAssign(ref lhs, ref rhs) => {
- ExprKind::Assign {
- lhs: lhs.to_ref(),
- rhs: rhs.to_ref(),
- }
- }
-
- hir::ExprAssignOp(op, ref lhs, ref rhs) => {
- if cx.tcx.is_method_call(self.id) {
- let pass_args = if op.node.is_by_value() {
- PassArgs::ByValue
- } else {
- PassArgs::ByRef
- };
- overloaded_operator(cx, self, ty::MethodCall::expr(self.id),
- pass_args, lhs.to_ref(), vec![rhs])
- } else {
- ExprKind::AssignOp {
- op: bin_op(op.node),
- lhs: lhs.to_ref(),
- rhs: rhs.to_ref(),
- }
- }
- }
-
- hir::ExprLit(..) => ExprKind::Literal {
- literal: cx.const_eval_literal(self)
- },
-
- hir::ExprBinary(op, ref lhs, ref rhs) => {
- if cx.tcx.is_method_call(self.id) {
- let pass_args = if op.node.is_by_value() {
- PassArgs::ByValue
- } else {
- PassArgs::ByRef
- };
- overloaded_operator(cx, self, ty::MethodCall::expr(self.id),
- pass_args, lhs.to_ref(), vec![rhs])
- } else {
- // FIXME overflow
- match op.node {
- hir::BinOp_::BiAnd => {
- ExprKind::LogicalOp {
- op: LogicalOp::And,
- lhs: lhs.to_ref(),
- rhs: rhs.to_ref(),
- }
- }
- hir::BinOp_::BiOr => {
- ExprKind::LogicalOp {
- op: LogicalOp::Or,
- lhs: lhs.to_ref(),
- rhs: rhs.to_ref(),
- }
- }
- _ => {
- let op = bin_op(op.node);
- ExprKind::Binary {
- op: op,
- lhs: lhs.to_ref(),
- rhs: rhs.to_ref(),
- }
- }
- }
- }
- }
-
- hir::ExprIndex(ref lhs, ref index) => {
- if cx.tcx.is_method_call(self.id) {
- overloaded_lvalue(cx, self, ty::MethodCall::expr(self.id),
- PassArgs::ByValue, lhs.to_ref(), vec![index])
- } else {
- ExprKind::Index {
- lhs: lhs.to_ref(),
- index: index.to_ref(),
- }
- }
- }
-
- hir::ExprUnary(hir::UnOp::UnDeref, ref arg) => {
- if cx.tcx.is_method_call(self.id) {
- overloaded_lvalue(cx, self, ty::MethodCall::expr(self.id),
- PassArgs::ByValue, arg.to_ref(), vec![])
- } else {
- ExprKind::Deref { arg: arg.to_ref() }
- }
- }
-
- hir::ExprUnary(hir::UnOp::UnNot, ref arg) => {
- if cx.tcx.is_method_call(self.id) {
- overloaded_operator(cx, self, ty::MethodCall::expr(self.id),
- PassArgs::ByValue, arg.to_ref(), vec![])
- } else {
- ExprKind::Unary {
- op: UnOp::Not,
- arg: arg.to_ref(),
- }
- }
- }
-
- hir::ExprUnary(hir::UnOp::UnNeg, ref arg) => {
- if cx.tcx.is_method_call(self.id) {
- overloaded_operator(cx, self, ty::MethodCall::expr(self.id),
- PassArgs::ByValue, arg.to_ref(), vec![])
- } else {
- // FIXME runtime-overflow
- if let hir::ExprLit(_) = arg.node {
- ExprKind::Literal {
- literal: cx.const_eval_literal(self),
- }
- } else {
- ExprKind::Unary {
- op: UnOp::Neg,
- arg: arg.to_ref(),
- }
- }
- }
- }
-
- hir::ExprStruct(_, ref fields, ref base) => {
- match expr_ty.sty {
- ty::TyStruct(adt, substs) => {
- let field_refs = field_refs(&adt.variants[0], fields);
- ExprKind::Adt {
- adt_def: adt,
- variant_index: 0,
- substs: substs,
- fields: field_refs,
- base: base.as_ref().map(|base| {
- FruInfo {
- base: base.to_ref(),
- field_types: cx.tcx.tables
- .borrow()
- .fru_field_types[&self.id]
- .clone()
- }
- })
- }
- }
- ty::TyEnum(adt, substs) => {
- match cx.tcx.def_map.borrow()[&self.id].full_def() {
- Def::Variant(enum_id, variant_id) => {
- debug_assert!(adt.did == enum_id);
- assert!(base.is_none());
-
- let index = adt.variant_index_with_id(variant_id);
- let field_refs = field_refs(&adt.variants[index], fields);
- ExprKind::Adt {
- adt_def: adt,
- variant_index: index,
- substs: substs,
- fields: field_refs,
- base: None
- }
- }
- ref def => {
- span_bug!(
- self.span,
- "unexpected def: {:?}",
- def);
- }
- }
- }
- _ => {
- span_bug!(
- self.span,
- "unexpected type for struct literal: {:?}",
- expr_ty);
- }
- }
- }
-
- hir::ExprClosure(..) => {
- let closure_ty = cx.tcx.expr_ty(self);
- let (def_id, substs) = match closure_ty.sty {
- ty::TyClosure(def_id, ref substs) => (def_id, substs),
- _ => {
- span_bug!(self.span,
- "closure expr w/o closure type: {:?}",
- closure_ty);
- }
- };
- let upvars = cx.tcx.with_freevars(self.id, |freevars| {
- freevars.iter()
- .enumerate()
- .map(|(i, fv)| capture_freevar(cx, self, fv, substs.upvar_tys[i]))
- .collect()
- });
- ExprKind::Closure {
- closure_id: def_id,
- substs: &substs,
- upvars: upvars,
- }
- }
-
- hir::ExprPath(..) => {
- convert_path_expr(cx, self)
- }
-
- hir::ExprInlineAsm(ref asm, ref outputs, ref inputs) => {
- ExprKind::InlineAsm {
- asm: asm,
- outputs: outputs.to_ref(),
- inputs: inputs.to_ref()
- }
- }
-
- // Now comes the rote stuff:
-
- hir::ExprRepeat(ref v, ref c) => ExprKind::Repeat {
- value: v.to_ref(),
- count: TypedConstVal {
- ty: cx.tcx.expr_ty(c),
- span: c.span,
- value: match const_eval::eval_const_expr(cx.tcx, c) {
- ConstVal::Integral(ConstInt::Usize(u)) => u,
- other => bug!("constant evaluation of repeat count yielded {:?}", other),
- },
- }
- },
- hir::ExprRet(ref v) =>
- ExprKind::Return { value: v.to_ref() },
- hir::ExprBreak(label) =>
- ExprKind::Break { label: label.map(|_| loop_label(cx, self)) },
- hir::ExprAgain(label) =>
- ExprKind::Continue { label: label.map(|_| loop_label(cx, self)) },
- hir::ExprMatch(ref discr, ref arms, _) =>
- ExprKind::Match { discriminant: discr.to_ref(),
- arms: arms.iter().map(|a| convert_arm(cx, a)).collect() },
- hir::ExprIf(ref cond, ref then, ref otherwise) =>
- ExprKind::If { condition: cond.to_ref(),
- then: block::to_expr_ref(cx, then),
- otherwise: otherwise.to_ref() },
- hir::ExprWhile(ref cond, ref body, _) =>
- ExprKind::Loop { condition: Some(cond.to_ref()),
- body: block::to_expr_ref(cx, body) },
- hir::ExprLoop(ref body, _) =>
- ExprKind::Loop { condition: None,
- body: block::to_expr_ref(cx, body) },
- hir::ExprField(ref source, name) => {
- let index = match cx.tcx.expr_ty_adjusted(source).sty {
- ty::TyStruct(adt_def, _) =>
- adt_def.variants[0].index_of_field_named(name.node),
- ref ty =>
- span_bug!(
- self.span,
- "field of non-struct: {:?}",
- ty),
- };
- let index = index.unwrap_or_else(|| {
- span_bug!(
- self.span,
- "no index found for field `{}`",
- name.node)
- });
- ExprKind::Field { lhs: source.to_ref(), name: Field::new(index) }
- }
- hir::ExprTupField(ref source, index) =>
- ExprKind::Field { lhs: source.to_ref(),
- name: Field::new(index.node as usize) },
- hir::ExprCast(ref source, _) =>
- ExprKind::Cast { source: source.to_ref() },
- hir::ExprType(ref source, _) =>
- return source.make_mirror(cx),
- hir::ExprBox(ref value) =>
- ExprKind::Box {
- value: value.to_ref(),
- value_extents: cx.tcx.region_maps.node_extent(value.id)
- },
- hir::ExprVec(ref fields) =>
- ExprKind::Vec { fields: fields.to_ref() },
- hir::ExprTup(ref fields) =>
- ExprKind::Tuple { fields: fields.to_ref() },
- };
+ debug!("Expr::make_mirror(): id={}, span={:?}", self.id, self.span);
- let mut expr = Expr {
- temp_lifetime: temp_lifetime,
- ty: expr_ty,
- span: self.span,
- kind: kind,
- };
+ let mut expr = make_mirror_unadjusted(cx, self);
debug!("make_mirror: unadjusted-expr={:?} applying adjustments={:?}",
expr, cx.tcx.tables.borrow().adjustments.get(&self.id));
}
}
+fn make_mirror_unadjusted<'a, 'tcx>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr) -> Expr<'tcx> {
+ let expr_ty = cx.tcx.expr_ty(expr);
+ let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id);
+
+ let kind = match expr.node {
+ // Here comes the interesting stuff:
+ hir::ExprMethodCall(_, _, ref args) => {
+ // Rewrite a.b(c) into UFCS form like Trait::b(a, c)
+ let expr = method_callee(cx, expr, ty::MethodCall::expr(expr.id));
+ let args = args.iter()
+ .map(|e| e.to_ref())
+ .collect();
+ ExprKind::Call {
+ ty: expr.ty,
+ fun: expr.to_ref(),
+ args: args,
+ }
+ }
+
+ hir::ExprCall(ref fun, ref args) => {
+ if cx.tcx.is_method_call(expr.id) {
+ // The callee is something implementing Fn, FnMut, or FnOnce.
+ // Find the actual method implementation being called and
+ // build the appropriate UFCS call expression with the
+ // callee-object as expr parameter.
+
+ // rewrite f(u, v) into FnOnce::call_once(f, (u, v))
+
+ let method = method_callee(cx, expr, ty::MethodCall::expr(expr.id));
+
+ let sig = match method.ty.sty {
+ ty::TyFnDef(_, _, fn_ty) => &fn_ty.sig,
+ _ => span_bug!(expr.span, "type of method is not an fn")
+ };
+
+ let sig = cx.tcx.no_late_bound_regions(sig).unwrap_or_else(|| {
+ span_bug!(expr.span, "method call has late-bound regions")
+ });
+
+ assert_eq!(sig.inputs.len(), 2);
+
+ let tupled_args = Expr {
+ ty: sig.inputs[1],
+ temp_lifetime: temp_lifetime,
+ span: expr.span,
+ kind: ExprKind::Tuple {
+ fields: args.iter().map(ToRef::to_ref).collect()
+ }
+ };
+
+ ExprKind::Call {
+ ty: method.ty,
+ fun: method.to_ref(),
+ args: vec![fun.to_ref(), tupled_args.to_ref()]
+ }
+ } else {
+ let adt_data = if let hir::ExprPath(..) = fun.node {
+ // Tuple-like ADTs are represented as ExprCall. We convert them here.
+ expr_ty.ty_adt_def().and_then(|adt_def|{
+ match cx.tcx.def_map.borrow()[&fun.id].full_def() {
+ Def::Variant(_, variant_id) => {
+ Some((adt_def, adt_def.variant_index_with_id(variant_id)))
+ },
+ Def::Struct(..) => {
+ Some((adt_def, 0))
+ },
+ _ => None
+ }
+ })
+ } else { None };
+ if let Some((adt_def, index)) = adt_data {
+ let substs = cx.tcx.mk_substs(cx.tcx.node_id_item_substs(fun.id).substs);
+ let field_refs = args.iter().enumerate().map(|(idx, e)| FieldExprRef {
+ name: Field::new(idx),
+ expr: e.to_ref()
+ }).collect();
+ ExprKind::Adt {
+ adt_def: adt_def,
+ substs: substs,
+ variant_index: index,
+ fields: field_refs,
+ base: None
+ }
+ } else {
+ ExprKind::Call {
+ ty: cx.tcx.node_id_to_type(fun.id),
+ fun: fun.to_ref(),
+ args: args.to_ref(),
+ }
+ }
+ }
+ }
+
+ hir::ExprAddrOf(mutbl, ref expr) => {
+ let region = match expr_ty.sty {
+ ty::TyRef(r, _) => r,
+ _ => span_bug!(expr.span, "type of & not region"),
+ };
+ ExprKind::Borrow {
+ region: *region,
+ borrow_kind: to_borrow_kind(mutbl),
+ arg: expr.to_ref(),
+ }
+ }
+
+ hir::ExprBlock(ref blk) => {
+ ExprKind::Block { body: &blk }
+ }
+
+ hir::ExprAssign(ref lhs, ref rhs) => {
+ ExprKind::Assign {
+ lhs: lhs.to_ref(),
+ rhs: rhs.to_ref(),
+ }
+ }
+
+ hir::ExprAssignOp(op, ref lhs, ref rhs) => {
+ if cx.tcx.is_method_call(expr.id) {
+ let pass_args = if op.node.is_by_value() {
+ PassArgs::ByValue
+ } else {
+ PassArgs::ByRef
+ };
+ overloaded_operator(cx, expr, ty::MethodCall::expr(expr.id),
+ pass_args, lhs.to_ref(), vec![rhs])
+ } else {
+ ExprKind::AssignOp {
+ op: bin_op(op.node),
+ lhs: lhs.to_ref(),
+ rhs: rhs.to_ref(),
+ }
+ }
+ }
+
+ hir::ExprLit(..) => ExprKind::Literal {
+ literal: cx.const_eval_literal(expr)
+ },
+
+ hir::ExprBinary(op, ref lhs, ref rhs) => {
+ if cx.tcx.is_method_call(expr.id) {
+ let pass_args = if op.node.is_by_value() {
+ PassArgs::ByValue
+ } else {
+ PassArgs::ByRef
+ };
+ overloaded_operator(cx, expr, ty::MethodCall::expr(expr.id),
+ pass_args, lhs.to_ref(), vec![rhs])
+ } else {
+ // FIXME overflow
+ match op.node {
+ hir::BinOp_::BiAnd => {
+ ExprKind::LogicalOp {
+ op: LogicalOp::And,
+ lhs: lhs.to_ref(),
+ rhs: rhs.to_ref(),
+ }
+ }
+ hir::BinOp_::BiOr => {
+ ExprKind::LogicalOp {
+ op: LogicalOp::Or,
+ lhs: lhs.to_ref(),
+ rhs: rhs.to_ref(),
+ }
+ }
+ _ => {
+ let op = bin_op(op.node);
+ ExprKind::Binary {
+ op: op,
+ lhs: lhs.to_ref(),
+ rhs: rhs.to_ref(),
+ }
+ }
+ }
+ }
+ }
+
+ hir::ExprIndex(ref lhs, ref index) => {
+ if cx.tcx.is_method_call(expr.id) {
+ overloaded_lvalue(cx, expr, ty::MethodCall::expr(expr.id),
+ PassArgs::ByValue, lhs.to_ref(), vec![index])
+ } else {
+ ExprKind::Index {
+ lhs: lhs.to_ref(),
+ index: index.to_ref(),
+ }
+ }
+ }
+
+ hir::ExprUnary(hir::UnOp::UnDeref, ref arg) => {
+ if cx.tcx.is_method_call(expr.id) {
+ overloaded_lvalue(cx, expr, ty::MethodCall::expr(expr.id),
+ PassArgs::ByValue, arg.to_ref(), vec![])
+ } else {
+ ExprKind::Deref { arg: arg.to_ref() }
+ }
+ }
+
+ hir::ExprUnary(hir::UnOp::UnNot, ref arg) => {
+ if cx.tcx.is_method_call(expr.id) {
+ overloaded_operator(cx, expr, ty::MethodCall::expr(expr.id),
+ PassArgs::ByValue, arg.to_ref(), vec![])
+ } else {
+ ExprKind::Unary {
+ op: UnOp::Not,
+ arg: arg.to_ref(),
+ }
+ }
+ }
+
+ hir::ExprUnary(hir::UnOp::UnNeg, ref arg) => {
+ if cx.tcx.is_method_call(expr.id) {
+ overloaded_operator(cx, expr, ty::MethodCall::expr(expr.id),
+ PassArgs::ByValue, arg.to_ref(), vec![])
+ } else {
+ // FIXME runtime-overflow
+ if let hir::ExprLit(_) = arg.node {
+ ExprKind::Literal {
+ literal: cx.const_eval_literal(expr),
+ }
+ } else {
+ ExprKind::Unary {
+ op: UnOp::Neg,
+ arg: arg.to_ref(),
+ }
+ }
+ }
+ }
+
+ hir::ExprStruct(_, ref fields, ref base) => {
+ match expr_ty.sty {
+ ty::TyStruct(adt, substs) => {
+ let field_refs = field_refs(&adt.variants[0], fields);
+ ExprKind::Adt {
+ adt_def: adt,
+ variant_index: 0,
+ substs: substs,
+ fields: field_refs,
+ base: base.as_ref().map(|base| {
+ FruInfo {
+ base: base.to_ref(),
+ field_types: cx.tcx.tables
+ .borrow()
+ .fru_field_types[&expr.id]
+ .clone()
+ }
+ })
+ }
+ }
+ ty::TyEnum(adt, substs) => {
+ match cx.tcx.def_map.borrow()[&expr.id].full_def() {
+ Def::Variant(enum_id, variant_id) => {
+ debug_assert!(adt.did == enum_id);
+ assert!(base.is_none());
+
+ let index = adt.variant_index_with_id(variant_id);
+ let field_refs = field_refs(&adt.variants[index], fields);
+ ExprKind::Adt {
+ adt_def: adt,
+ variant_index: index,
+ substs: substs,
+ fields: field_refs,
+ base: None
+ }
+ }
+ ref def => {
+ span_bug!(
+ expr.span,
+ "unexpected def: {:?}",
+ def);
+ }
+ }
+ }
+ _ => {
+ span_bug!(
+ expr.span,
+ "unexpected type for struct literal: {:?}",
+ expr_ty);
+ }
+ }
+ }
+
+ hir::ExprClosure(..) => {
+ let closure_ty = cx.tcx.expr_ty(expr);
+ let (def_id, substs) = match closure_ty.sty {
+ ty::TyClosure(def_id, ref substs) => (def_id, substs),
+ _ => {
+ span_bug!(expr.span,
+ "closure expr w/o closure type: {:?}",
+ closure_ty);
+ }
+ };
+ let upvars = cx.tcx.with_freevars(expr.id, |freevars| {
+ freevars.iter()
+ .enumerate()
+ .map(|(i, fv)| capture_freevar(cx, expr, fv, substs.upvar_tys[i]))
+ .collect()
+ });
+ ExprKind::Closure {
+ closure_id: def_id,
+ substs: &substs,
+ upvars: upvars,
+ }
+ }
+
+ hir::ExprPath(..) => {
+ convert_path_expr(cx, expr)
+ }
+
+ hir::ExprInlineAsm(ref asm, ref outputs, ref inputs) => {
+ ExprKind::InlineAsm {
+ asm: asm,
+ outputs: outputs.to_ref(),
+ inputs: inputs.to_ref()
+ }
+ }
+
+ // Now comes the rote stuff:
+
+ hir::ExprRepeat(ref v, ref c) => ExprKind::Repeat {
+ value: v.to_ref(),
+ count: TypedConstVal {
+ ty: cx.tcx.expr_ty(c),
+ span: c.span,
+ value: match const_eval::eval_const_expr(cx.tcx, c) {
+ ConstVal::Integral(ConstInt::Usize(u)) => u,
+ other => bug!("constant evaluation of repeat count yielded {:?}", other),
+ },
+ }
+ },
+ hir::ExprRet(ref v) =>
+ ExprKind::Return { value: v.to_ref() },
+ hir::ExprBreak(label) =>
+ ExprKind::Break { label: label.map(|_| loop_label(cx, expr)) },
+ hir::ExprAgain(label) =>
+ ExprKind::Continue { label: label.map(|_| loop_label(cx, expr)) },
+ hir::ExprMatch(ref discr, ref arms, _) =>
+ ExprKind::Match { discriminant: discr.to_ref(),
+ arms: arms.iter().map(|a| convert_arm(cx, a)).collect() },
+ hir::ExprIf(ref cond, ref then, ref otherwise) =>
+ ExprKind::If { condition: cond.to_ref(),
+ then: block::to_expr_ref(cx, then),
+ otherwise: otherwise.to_ref() },
+ hir::ExprWhile(ref cond, ref body, _) =>
+ ExprKind::Loop { condition: Some(cond.to_ref()),
+ body: block::to_expr_ref(cx, body) },
+ hir::ExprLoop(ref body, _) =>
+ ExprKind::Loop { condition: None,
+ body: block::to_expr_ref(cx, body) },
+ hir::ExprField(ref source, name) => {
+ let index = match cx.tcx.expr_ty_adjusted(source).sty {
+ ty::TyStruct(adt_def, _) =>
+ adt_def.variants[0].index_of_field_named(name.node),
+ ref ty =>
+ span_bug!(
+ expr.span,
+ "field of non-struct: {:?}",
+ ty),
+ };
+ let index = index.unwrap_or_else(|| {
+ span_bug!(
+ expr.span,
+ "no index found for field `{}`",
+ name.node)
+ });
+ ExprKind::Field { lhs: source.to_ref(), name: Field::new(index) }
+ }
+ hir::ExprTupField(ref source, index) =>
+ ExprKind::Field { lhs: source.to_ref(),
+ name: Field::new(index.node as usize) },
+ hir::ExprCast(ref source, _) => {
+ // Check to see if this cast is a "coercion cast", where the cast is actually done
+ // using a coercion (or is a no-op).
+ if let Some(&TyCastKind::CoercionCast) = cx.tcx.cast_kinds.borrow().get(&source.id) {
+ // Skip the actual cast itexpr, as it's now a no-op.
+ return source.make_mirror(cx);
+ } else {
+ ExprKind::Cast { source: source.to_ref() }
+ }
+ }
+ hir::ExprType(ref source, _) =>
+ return source.make_mirror(cx),
+ hir::ExprBox(ref value) =>
+ ExprKind::Box {
+ value: value.to_ref(),
+ value_extents: cx.tcx.region_maps.node_extent(value.id)
+ },
+ hir::ExprVec(ref fields) =>
+ ExprKind::Vec { fields: fields.to_ref() },
+ hir::ExprTup(ref fields) =>
+ ExprKind::Tuple { fields: fields.to_ref() },
+ };
+
+ Expr {
+ temp_lifetime: temp_lifetime,
+ ty: expr_ty,
+ span: expr.span,
+ kind: kind,
+ }
+}
+
fn method_callee<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
expr: &hir::Expr,
method_call: ty::MethodCall)