X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Flibrustc_mir%2Fhair%2Fcx%2Fexpr.rs;h=801f4388ebd9e63ebc5aa8cd61822c6665eb7e9a;hb=b423a0f9ef488ca4cd9ff620a44566bb441eb21f;hp=90d049cdc731a1d7e20552ab376bddd4845c098f;hpb=9f0e39ba16a319e5d30f16c579e3fa205824862b;p=rust.git diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 90d049cdc73..801f4388ebd 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -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, 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()