]> git.proxmox.com Git - rustc.git/blobdiff - src/librustc_mir/hair/cx/expr.rs
Imported Upstream version 1.9.0+dfsg1
[rustc.git] / src / librustc_mir / hair / cx / expr.rs
index ac1cff527fe91f68cf6976db76b5ed4e5a7034aa..12dcb32da3fcd81fbf9ff3f6892ff66244553a90 100644 (file)
 
 use hair::*;
 use rustc_data_structures::fnv::FnvHashMap;
+use rustc_const_math::ConstInt;
 use hair::cx::Cx;
 use hair::cx::block;
 use hair::cx::to_ref::ToRef;
-use rustc::front::map;
-use rustc::middle::def::Def;
-use rustc::middle::const_eval;
+use rustc::hir::map;
+use rustc::hir::def::Def;
+use rustc::middle::const_val::ConstVal;
+use rustc_const_eval as const_eval;
 use rustc::middle::region::CodeExtent;
-use rustc::middle::pat_util;
-use rustc::middle::ty::{self, VariantDef, Ty};
+use rustc::hir::pat_util;
+use rustc::ty::{self, VariantDef, Ty};
 use rustc::mir::repr::*;
-use rustc_front::hir;
-use rustc_front::util as hir_util;
-use syntax::parse::token;
+use rustc::hir;
 use syntax::ptr::P;
 
 impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
@@ -62,12 +62,12 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
                     let method = method_callee(cx, self, ty::MethodCall::expr(self.id));
 
                     let sig = match method.ty.sty {
-                        ty::TyBareFn(_, fn_ty) => &fn_ty.sig,
-                        _ => cx.tcx.sess.span_bug(self.span, "type of method is not an fn")
+                        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(|| {
-                        cx.tcx.sess.span_bug(self.span, "method call has late-bound regions")
+                        span_bug!(self.span, "method call has late-bound regions")
                     });
 
                     assert_eq!(sig.inputs.len(), 2);
@@ -127,7 +127,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
             hir::ExprAddrOf(mutbl, ref expr) => {
                 let region = match expr_ty.sty {
                     ty::TyRef(r, _) => r,
-                    _ => cx.tcx.sess.span_bug(expr.span, "type of & not region"),
+                    _ => span_bug!(expr.span, "type of & not region"),
                 };
                 ExprKind::Borrow {
                     region: *region,
@@ -149,7 +149,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
 
             hir::ExprAssignOp(op, ref lhs, ref rhs) => {
                 if cx.tcx.is_method_call(self.id) {
-                    let pass_args = if hir_util::is_by_value_binop(op.node) {
+                    let pass_args = if op.node.is_by_value() {
                         PassArgs::ByValue
                     } else {
                         PassArgs::ByRef
@@ -171,7 +171,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
 
             hir::ExprBinary(op, ref lhs, ref rhs) => {
                 if cx.tcx.is_method_call(self.id) {
-                    let pass_args = if hir_util::is_by_value_binop(op.node) {
+                    let pass_args = if op.node.is_by_value() {
                         PassArgs::ByValue
                     } else {
                         PassArgs::ByRef
@@ -228,28 +228,37 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
                 }
             }
 
-            hir::ExprUnary(op, ref arg) => {
+            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 {
-                    // FIXME overflow
-                    let op = match op {
-                        hir::UnOp::UnNot => UnOp::Not,
-                        hir::UnOp::UnNeg => UnOp::Neg,
-                        hir::UnOp::UnDeref => {
-                            cx.tcx.sess.span_bug(
-                                self.span,
-                                "UnDeref should have been handled elsewhere");
-                        }
-                    };
                     ExprKind::Unary {
-                        op: op,
+                        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) => {
@@ -287,16 +296,18 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
                                 }
                             }
                             ref def => {
-                                cx.tcx.sess.span_bug(
+                                span_bug!(
                                     self.span,
-                                    &format!("unexpected def: {:?}", def));
+                                    "unexpected def: {:?}",
+                                    def);
                             }
                         }
                     }
                     _ => {
-                        cx.tcx.sess.span_bug(
+                        span_bug!(
                             self.span,
-                            &format!("unexpected type for struct literal: {:?}", expr_ty));
+                            "unexpected type for struct literal: {:?}",
+                            expr_ty);
                     }
                 }
             }
@@ -306,9 +317,9 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
                 let (def_id, substs) = match closure_ty.sty {
                     ty::TyClosure(def_id, ref substs) => (def_id, substs),
                     _ => {
-                        cx.tcx.sess.span_bug(self.span,
-                                             &format!("closure expr w/o closure type: {:?}",
-                                                      closure_ty));
+                        span_bug!(self.span,
+                                  "closure expr w/o closure type: {:?}",
+                                  closure_ty);
                     }
                 };
                 let upvars = cx.tcx.with_freevars(self.id, |freevars| {
@@ -324,44 +335,16 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
                 }
             }
 
-            hir::ExprRange(ref start, ref end) => {
-                let range_ty = cx.tcx.expr_ty(self);
-                let (adt_def, substs) = match range_ty.sty {
-                    ty::TyStruct(adt_def, substs) => (adt_def, substs),
-                    _ => {
-                        cx.tcx.sess.span_bug(self.span, "unexpanded ast");
-                    }
-                };
-
-                let field_expr_ref = |s: &'tcx P<hir::Expr>, name: &str| {
-                    let name = token::intern(name);
-                    let index = adt_def.variants[0].index_of_field_named(name).unwrap();
-                    FieldExprRef { name: Field::new(index), expr: s.to_ref() }
-                };
-
-                let start_field = start.as_ref()
-                                       .into_iter()
-                                       .map(|s| field_expr_ref(s, "start"));
-
-                let end_field = end.as_ref()
-                                   .into_iter()
-                                   .map(|e| field_expr_ref(e, "end"));
-
-                ExprKind::Adt {
-                    adt_def: adt_def,
-                    variant_index: 0,
-                    substs: substs,
-                    fields: start_field.chain(end_field).collect(),
-                    base: None,
-                }
-            }
-
             hir::ExprPath(..) => {
                 convert_path_expr(cx, self)
             }
 
-            hir::ExprInlineAsm(ref asm) => {
-                ExprKind::InlineAsm { asm: asm }
+            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:
@@ -371,7 +354,10 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
                 count: TypedConstVal {
                     ty: cx.tcx.expr_ty(c),
                     span: c.span,
-                    value: const_eval::eval_const_expr(cx.tcx, c)
+                    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) =>
@@ -398,14 +384,16 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
                     ty::TyStruct(adt_def, _) =>
                         adt_def.variants[0].index_of_field_named(name.node),
                     ref ty =>
-                        cx.tcx.sess.span_bug(
+                        span_bug!(
                             self.span,
-                            &format!("field of non-struct: {:?}", ty)),
+                            "field of non-struct: {:?}",
+                            ty),
                 };
                 let index = index.unwrap_or_else(|| {
-                    cx.tcx.sess.span_bug(
+                    span_bug!(
                         self.span,
-                        &format!("no index found for field `{}`", name.node));
+                        "no index found for field `{}`",
+                        name.node)
                 });
                 ExprKind::Field { lhs: source.to_ref(), name: Field::new(index) }
             }
@@ -489,8 +477,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
                             Some(ty::FnConverging(&ty::TyS {
                                 sty: ty::TyRef(region, mt), ..
                             })) => (region, mt.mutbl),
-                            _ => cx.tcx.sess.span_bug(
-                                expr.span, "autoderef returned bad type")
+                            _ => span_bug!(expr.span, "autoderef returned bad type")
                         };
 
                         expr = Expr {
@@ -614,7 +601,6 @@ fn method_callee<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
         kind: ExprKind::Literal {
             literal: Literal::Item {
                 def_id: callee.def_id,
-                kind: ItemKind::Method,
                 substs: callee.substs,
             },
         },
@@ -651,14 +637,13 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr)
     let substs = cx.tcx.mk_substs(cx.tcx.node_id_item_substs(expr.id).substs);
     // Otherwise there may be def_map borrow conflicts
     let def = cx.tcx.def_map.borrow()[&expr.id].full_def();
-    let (def_id, kind) = match def {
+    let def_id = match def {
         // A regular function.
-        Def::Fn(def_id) => (def_id, ItemKind::Function),
-        Def::Method(def_id) => (def_id, ItemKind::Method),
+        Def::Fn(def_id) | Def::Method(def_id) => def_id,
         Def::Struct(def_id) => match cx.tcx.node_id_to_type(expr.id).sty {
             // A tuple-struct constructor. Should only be reached if not called in the same
             // expression.
-            ty::TyBareFn(..) => (def_id, ItemKind::Function),
+            ty::TyFnDef(..) => def_id,
             // A unit struct which is used as a value. We return a completely different ExprKind
             // here to account for this special case.
             ty::TyStruct(adt_def, substs) => return ExprKind::Adt {
@@ -668,12 +653,12 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr)
                 fields: vec![],
                 base: None
             },
-            ref sty => panic!("unexpected sty: {:?}", sty)
+            ref sty => bug!("unexpected sty: {:?}", sty)
         },
         Def::Variant(enum_id, variant_id) => match cx.tcx.node_id_to_type(expr.id).sty {
             // A variant constructor. Should only be reached if not called in the same
             // expression.
-            ty::TyBareFn(..) => (variant_id, ItemKind::Function),
+            ty::TyFnDef(..) => variant_id,
             // A unit variant, similar special case to the struct case above.
             ty::TyEnum(adt_def, substs) => {
                 debug_assert!(adt_def.did == enum_id);
@@ -686,15 +671,20 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr)
                     base: None
                 };
             },
-            ref sty => panic!("unexpected sty: {:?}", sty)
+            ref sty => bug!("unexpected sty: {:?}", sty)
         },
         Def::Const(def_id) |
         Def::AssociatedConst(def_id) => {
-            if let Some(v) = cx.try_const_eval_literal(expr) {
-                return ExprKind::Literal { literal: v };
-            } else {
-                (def_id, ItemKind::Constant)
+            let substs = Some(cx.tcx.node_id_item_substs(expr.id).substs);
+            if let Some((e, _)) = const_eval::lookup_const_by_id(cx.tcx, def_id, substs) {
+                // FIXME ConstVal can't be yet used with adjustments, as they would be lost.
+                if !cx.tcx.tables.borrow().adjustments.contains_key(&e.id) {
+                    if let Some(v) = cx.try_const_eval_literal(e) {
+                        return ExprKind::Literal { literal: v };
+                    }
+                }
             }
+            def_id
         }
 
         Def::Static(node_id, _) => return ExprKind::StaticRef {
@@ -705,12 +695,13 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr)
         def @ Def::Upvar(..) => return convert_var(cx, expr, def),
 
         def =>
-            cx.tcx.sess.span_bug(
+            span_bug!(
                 expr.span,
-                &format!("def `{:?}` not yet implemented", def)),
+                "def `{:?}` not yet implemented",
+                def),
     };
     ExprKind::Literal {
-        literal: Literal::Item { def_id: def_id, kind: kind, substs: substs }
+        literal: Literal::Item { def_id: def_id, substs: substs }
     }
 }
 
@@ -736,12 +727,12 @@ fn convert_var<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
                     match expr.node {
                         hir::ExprClosure(_, _, ref body) => body.id,
                         _ => {
-                            cx.tcx.sess.span_bug(expr.span, "closure expr is not a closure expr");
+                            span_bug!(expr.span, "closure expr is not a closure expr");
                         }
                     }
                 }
                 _ => {
-                    cx.tcx.sess.span_bug(expr.span, "ast-map has garbage for closure expr");
+                    span_bug!(expr.span, "ast-map has garbage for closure expr");
                 }
             };
 
@@ -758,7 +749,7 @@ fn convert_var<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
             let region = cx.tcx.mk_region(region);
 
             let self_expr = match cx.tcx.closure_kind(cx.tcx.map.local_def_id(closure_expr_id)) {
-                ty::ClosureKind::FnClosureKind => {
+                ty::ClosureKind::Fn => {
                     let ref_closure_ty =
                         cx.tcx.mk_ref(region,
                                    ty::TypeAndMut { ty: closure_ty,
@@ -777,7 +768,7 @@ fn convert_var<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
                         }
                     }
                 }
-                ty::ClosureKind::FnMutClosureKind => {
+                ty::ClosureKind::FnMut => {
                     let ref_closure_ty =
                         cx.tcx.mk_ref(region,
                                    ty::TypeAndMut { ty: closure_ty,
@@ -796,7 +787,7 @@ fn convert_var<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
                         }
                     }
                 }
-                ty::ClosureKind::FnOnceClosureKind => {
+                ty::ClosureKind::FnOnce => {
                     Expr {
                         ty: closure_ty,
                         temp_lifetime: temp_lifetime,
@@ -821,9 +812,10 @@ fn convert_var<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
             let upvar_capture = match cx.tcx.upvar_capture(upvar_id) {
                 Some(c) => c,
                 None => {
-                    cx.tcx.sess.span_bug(
+                    span_bug!(
                         expr.span,
-                        &format!("no upvar_capture for {:?}", upvar_id));
+                        "no upvar_capture for {:?}",
+                        upvar_id);
                 }
             };
             match upvar_capture {
@@ -846,7 +838,7 @@ fn convert_var<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
             }
         }
 
-        _ => cx.tcx.sess.span_bug(expr.span, "type of & not region"),
+        _ => span_bug!(expr.span, "type of & not region"),
     }
 }
 
@@ -869,7 +861,7 @@ fn bin_op(op: hir::BinOp_) -> BinOp {
         hir::BinOp_::BiNe => BinOp::Ne,
         hir::BinOp_::BiGe => BinOp::Ge,
         hir::BinOp_::BiGt => BinOp::Gt,
-        _ => panic!("no equivalent for ast binop {:?}", op),
+        _ => bug!("no equivalent for ast binop {:?}", op),
     }
 }
 
@@ -966,7 +958,7 @@ fn overloaded_lvalue<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
 
 fn capture_freevar<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
                                  closure_expr: &'tcx hir::Expr,
-                                 freevar: &ty::Freevar,
+                                 freevar: &hir::Freevar,
                                  freevar_ty: Ty<'tcx>)
                                  -> ExprRef<'tcx> {
     let id_var = freevar.def.var_id();
@@ -1009,7 +1001,7 @@ fn loop_label<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr) -> Cod
     match cx.tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()) {
         Some(Def::Label(loop_id)) => cx.tcx.region_maps.node_extent(loop_id),
         d => {
-            cx.tcx.sess.span_bug(expr.span, &format!("loop scope resolved to {:?}", d));
+            span_bug!(expr.span, "loop scope resolved to {:?}", d);
         }
     }
 }