]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_mir/hair/cx/expr.rs
Split TyBareFn into TyFnDef and TyFnPtr.
[rust.git] / src / librustc_mir / hair / cx / expr.rs
index 90d049cdc731a1d7e20552ab376bddd4845c098f..801f4388ebd9e63ebc5aa8cd61822c6665eb7e9a 100644 (file)
@@ -22,7 +22,6 @@
 use rustc::mir::repr::*;
 use rustc_front::hir;
 use rustc_front::util as hir_util;
-use syntax::parse::token;
 use syntax::ptr::P;
 
 impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
@@ -32,6 +31,8 @@ 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:
@@ -54,14 +55,35 @@ fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
                     // 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 mut argrefs = vec![fun.to_ref()];
-                    argrefs.extend(args.iter().map(|a| a.to_ref()));
+
+                    let sig = match method.ty.sty {
+                        ty::TyFnDef(_, fn_ty) => &fn_ty.sig,
+                        _ => cx.tcx.sess.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")
+                    });
+
+                    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: argrefs,
+                        args: vec![fun.to_ref(), tupled_args.to_ref()]
                     }
                 } else {
                     let adt_data = if let hir::ExprPath(..) = fun.node {
@@ -125,11 +147,20 @@ fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
             }
 
             hir::ExprAssignOp(op, ref lhs, ref rhs) => {
-                let op = bin_op(op.node);
-                ExprKind::AssignOp {
-                    op: op,
-                    lhs: lhs.to_ref(),
-                    rhs: rhs.to_ref(),
+                if cx.tcx.is_method_call(self.id) {
+                    let pass_args = if hir_util::is_by_value_binop(op.node) {
+                        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(),
+                    }
                 }
             }
 
@@ -227,13 +258,23 @@ fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
                             variant_index: 0,
                             substs: substs,
                             fields: field_refs,
-                            base: base.to_ref(),
+                            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 {
@@ -241,7 +282,7 @@ fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
                                     variant_index: index,
                                     substs: substs,
                                     fields: field_refs,
-                                    base: base.to_ref(),
+                                    base: None
                                 }
                             }
                             ref def => {
@@ -282,38 +323,6 @@ fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
                 }
             }
 
-            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)
             }
@@ -385,9 +394,6 @@ fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
                 ExprKind::Tuple { fields: fields.to_ref() },
         };
 
-        let temp_lifetime = cx.tcx.region_maps.temporary_scope(self.id);
-        let expr_extent = cx.tcx.region_maps.node_extent(self.id);
-
         let mut expr = Expr {
             temp_lifetime: temp_lifetime,
             ty: expr_ty,
@@ -395,6 +401,9 @@ fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
             kind: kind,
         };
 
+        debug!("make_mirror: unadjusted-expr={:?} applying adjustments={:?}",
+               expr, cx.tcx.tables.borrow().adjustments.get(&self.id));
+
         // Now apply adjustments, if any.
         match cx.tcx.tables.borrow().adjustments.get(&self.id) {
             None => {}
@@ -416,6 +425,15 @@ fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
                     kind: ExprKind::UnsafeFnPointer { source: expr.to_ref() },
                 };
             }
+            Some(&ty::adjustment::AdjustMutToConstPointer) => {
+                let adjusted_ty = cx.tcx.expr_ty_adjusted(self);
+                expr = Expr {
+                    temp_lifetime: temp_lifetime,
+                    ty: adjusted_ty,
+                    span: self.span,
+                    kind: ExprKind::Cast { source: expr.to_ref() },
+                };
+            }
             Some(&ty::adjustment::AdjustDerefRef(ref adj)) => {
                 for i in 0..adj.autoderefs {
                     let i = i as u32;
@@ -426,10 +444,38 @@ fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
                             self.span,
                             i,
                             |mc| cx.tcx.tables.borrow().method_map.get(&mc).map(|m| m.ty));
-                    let kind = if cx.tcx.is_overloaded_autoderef(self.id, i) {
-                        overloaded_lvalue(cx, self, ty::MethodCall::autoderef(self.id, i),
-                                          PassArgs::ByValue, expr.to_ref(), vec![])
+                    debug!("make_mirror: autoderef #{}, adjusted_ty={:?}", i, adjusted_ty);
+                    let method_key = ty::MethodCall::autoderef(self.id, i);
+                    let meth_ty =
+                        cx.tcx.tables.borrow().method_map.get(&method_key).map(|m| m.ty);
+                    let kind = if let Some(meth_ty) = meth_ty {
+                        debug!("make_mirror: overloaded autoderef (meth_ty={:?})", meth_ty);
+
+                        let ref_ty = cx.tcx.no_late_bound_regions(&meth_ty.fn_ret());
+                        let (region, mutbl) = match ref_ty {
+                            Some(ty::FnConverging(&ty::TyS {
+                                sty: ty::TyRef(region, mt), ..
+                            })) => (region, mt.mutbl),
+                            _ => cx.tcx.sess.span_bug(
+                                expr.span, "autoderef returned bad type")
+                        };
+
+                        expr = Expr {
+                            temp_lifetime: temp_lifetime,
+                            ty: cx.tcx.mk_ref(
+                                region, ty::TypeAndMut { ty: expr.ty, mutbl: mutbl }),
+                            span: expr.span,
+                            kind: ExprKind::Borrow {
+                                region: *region,
+                                borrow_kind: to_borrow_kind(mutbl),
+                                arg: expr.to_ref()
+                            }
+                        };
+
+                        overloaded_lvalue(cx, self, method_key,
+                                          PassArgs::ByRef, expr.to_ref(), vec![])
                     } else {
+                        debug!("make_mirror: built-in autoderef");
                         ExprKind::Deref { arg: expr.to_ref() }
                     };
                     expr = Expr {
@@ -579,7 +625,7 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr)
         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, ItemKind::Function),
             // 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 {
@@ -594,7 +640,7 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr)
         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, ItemKind::Function),
             // A unit variant, similar special case to the struct case above.
             ty::TyEnum(adt_def, substs) => {
                 debug_assert!(adt_def.did == enum_id);
@@ -679,7 +725,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,
@@ -698,7 +744,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,
@@ -717,7 +763,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,
@@ -749,11 +795,16 @@ fn convert_var<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
             };
             match upvar_capture {
                 ty::UpvarCapture::ByValue => field_kind,
-                ty::UpvarCapture::ByRef(_) => {
+                ty::UpvarCapture::ByRef(borrow) => {
                     ExprKind::Deref {
                         arg: Expr {
                             temp_lifetime: temp_lifetime,
-                            ty: var_ty,
+                            ty: cx.tcx.mk_ref(
+                                cx.tcx.mk_region(borrow.region),
+                                ty::TypeAndMut {
+                                    ty: var_ty,
+                                    mutbl: borrow.kind.to_mutbl_lossy()
+                                }),
                             span: expr.span,
                             kind: field_kind,
                         }.to_ref()