]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/hair/cx/expr.rs
50140880a368df329bdbf08b35f3cb833cffb9a4
[rust.git] / src / librustc_mir / hair / cx / expr.rs
1 use crate::hair::*;
2 use crate::hair::cx::Cx;
3 use crate::hair::cx::block;
4 use crate::hair::cx::to_ref::ToRef;
5 use crate::hair::util::UserAnnotatedTyHelpers;
6 use rustc_data_structures::indexed_vec::Idx;
7 use rustc::hir::def::{CtorOf, Res, DefKind, CtorKind};
8 use rustc::mir::interpret::{GlobalId, ErrorHandled, ConstValue};
9 use rustc::ty::{self, AdtKind, Ty};
10 use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability, PointerCast};
11 use rustc::ty::subst::{InternalSubsts, SubstsRef};
12 use rustc::hir;
13 use rustc::hir::def_id::LocalDefId;
14 use rustc::mir::BorrowKind;
15 use syntax_pos::Span;
16
17 impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
18     type Output = Expr<'tcx>;
19
20     fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
21         let temp_lifetime = cx.region_scope_tree.temporary_scope(self.hir_id.local_id);
22         let expr_scope = region::Scope {
23             id: self.hir_id.local_id,
24             data: region::ScopeData::Node
25         };
26
27         debug!("Expr::make_mirror(): id={}, span={:?}", self.hir_id, self.span);
28
29         let mut expr = make_mirror_unadjusted(cx, self);
30
31         // Now apply adjustments, if any.
32         for adjustment in cx.tables().expr_adjustments(self) {
33             debug!("make_mirror: expr={:?} applying adjustment={:?}",
34                    expr,
35                    adjustment);
36             expr = apply_adjustment(cx, self, expr, adjustment);
37         }
38
39         // Next, wrap this up in the expr's scope.
40         expr = Expr {
41             temp_lifetime,
42             ty: expr.ty,
43             span: self.span,
44             kind: ExprKind::Scope {
45                 region_scope: expr_scope,
46                 value: expr.to_ref(),
47                 lint_level: LintLevel::Explicit(self.hir_id),
48             },
49         };
50
51         // Finally, create a destruction scope, if any.
52         if let Some(region_scope) =
53             cx.region_scope_tree.opt_destruction_scope(self.hir_id.local_id) {
54                 expr = Expr {
55                     temp_lifetime,
56                     ty: expr.ty,
57                     span: self.span,
58                     kind: ExprKind::Scope {
59                         region_scope,
60                         value: expr.to_ref(),
61                         lint_level: LintLevel::Inherited,
62                     },
63                 };
64             }
65
66         // OK, all done!
67         expr
68     }
69 }
70
71 fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
72                                     hir_expr: &'tcx hir::Expr,
73                                     mut expr: Expr<'tcx>,
74                                     adjustment: &Adjustment<'tcx>)
75                                     -> Expr<'tcx> {
76     let Expr { temp_lifetime, mut span, .. } = expr;
77
78     // Adjust the span from the block, to the last expression of the
79     // block. This is a better span when returning a mutable reference
80     // with too short a lifetime. The error message will use the span
81     // from the assignment to the return place, which should only point
82     // at the returned value, not the entire function body.
83     //
84     // fn return_short_lived<'a>(x: &'a mut i32) -> &'static mut i32 {
85     //      x
86     //   // ^ error message points at this expression.
87     // }
88     let mut adjust_span = |expr: &mut Expr<'tcx>| {
89         if let ExprKind::Block { body } = expr.kind {
90             if let Some(ref last_expr) = body.expr {
91                 span = last_expr.span;
92                 expr.span = span;
93             }
94         }
95     };
96
97     let kind = match adjustment.kind {
98         Adjust::Pointer(PointerCast::Unsize) => {
99             adjust_span(&mut expr);
100             ExprKind::Pointer { cast: PointerCast::Unsize, source: expr.to_ref() }
101         }
102         Adjust::Pointer(cast) => {
103             ExprKind::Pointer { cast, source: expr.to_ref() }
104         }
105         Adjust::NeverToAny => {
106             ExprKind::NeverToAny { source: expr.to_ref() }
107         }
108         Adjust::Deref(None) => {
109             adjust_span(&mut expr);
110             ExprKind::Deref { arg: expr.to_ref() }
111         }
112         Adjust::Deref(Some(deref)) => {
113             // We don't need to do call adjust_span here since
114             // deref coercions always start with a built-in deref.
115             let call = deref.method_call(cx.tcx(), expr.ty);
116
117             expr = Expr {
118                 temp_lifetime,
119                 ty: cx.tcx.mk_ref(deref.region,
120                                   ty::TypeAndMut {
121                                     ty: expr.ty,
122                                     mutbl: deref.mutbl,
123                                   }),
124                 span,
125                 kind: ExprKind::Borrow {
126                     borrow_kind: deref.mutbl.to_borrow_kind(),
127                     arg: expr.to_ref(),
128                 },
129             };
130
131             overloaded_place(cx, hir_expr, adjustment.target, Some(call), vec![expr.to_ref()])
132         }
133         Adjust::Borrow(AutoBorrow::Ref(_, m)) => {
134             ExprKind::Borrow {
135                 borrow_kind: m.to_borrow_kind(),
136                 arg: expr.to_ref(),
137             }
138         }
139         Adjust::Borrow(AutoBorrow::RawPtr(m)) => {
140             // Convert this to a suitable `&foo` and
141             // then an unsafe coercion.
142             expr = Expr {
143                 temp_lifetime,
144                 ty: cx.tcx.mk_ref(cx.tcx.lifetimes.re_erased,
145                                   ty::TypeAndMut {
146                                     ty: expr.ty,
147                                     mutbl: m,
148                                   }),
149                 span,
150                 kind: ExprKind::Borrow {
151                     borrow_kind: m.to_borrow_kind(),
152                     arg: expr.to_ref(),
153                 },
154             };
155             let cast_expr = Expr {
156                 temp_lifetime,
157                 ty: adjustment.target,
158                 span,
159                 kind: ExprKind::Cast { source: expr.to_ref() }
160             };
161
162             // To ensure that both implicit and explicit coercions are
163             // handled the same way, we insert an extra layer of indirection here.
164             // For explicit casts (e.g., 'foo as *const T'), the source of the 'Use'
165             // will be an ExprKind::Hair with the appropriate cast expression. Here,
166             // we make our Use source the generated Cast from the original coercion.
167             //
168             // In both cases, this outer 'Use' ensures that the inner 'Cast' is handled by
169             // as_operand, not by as_rvalue - causing the cast result to be stored in a temporary.
170             // Ordinary, this is identical to using the cast directly as an rvalue. However, if the
171             // source of the cast was previously borrowed as mutable, storing the cast in a
172             // temporary gives the source a chance to expire before the cast is used. For
173             // structs with a self-referential *mut ptr, this allows assignment to work as
174             // expected.
175             //
176             // For example, consider the type 'struct Foo { field: *mut Foo }',
177             // The method 'fn bar(&mut self) { self.field = self }'
178             // triggers a coercion from '&mut self' to '*mut self'. In order
179             // for the assignment to be valid, the implicit borrow
180             // of 'self' involved in the coercion needs to end before the local
181             // containing the '*mut T' is assigned to 'self.field' - otherwise,
182             // we end up trying to assign to 'self.field' while we have another mutable borrow
183             // active.
184             //
185             // We only need to worry about this kind of thing for coercions from refs to ptrs,
186             // since they get rid of a borrow implicitly.
187             ExprKind::Use { source: cast_expr.to_ref() }
188         }
189     };
190
191     Expr {
192         temp_lifetime,
193         ty: adjustment.target,
194         span,
195         kind,
196     }
197 }
198
199 fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
200                                           expr: &'tcx hir::Expr)
201                                           -> Expr<'tcx> {
202     let expr_ty = cx.tables().expr_ty(expr);
203     let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id);
204
205     let kind = match expr.node {
206         // Here comes the interesting stuff:
207         hir::ExprKind::MethodCall(_, method_span, ref args) => {
208             // Rewrite a.b(c) into UFCS form like Trait::b(a, c)
209             let expr = method_callee(cx, expr, method_span,None);
210             let args = args.iter()
211                 .map(|e| e.to_ref())
212                 .collect();
213             ExprKind::Call {
214                 ty: expr.ty,
215                 fun: expr.to_ref(),
216                 args,
217                 from_hir_call: true,
218             }
219         }
220
221         hir::ExprKind::Call(ref fun, ref args) => {
222             if cx.tables().is_method_call(expr) {
223                 // The callee is something implementing Fn, FnMut, or FnOnce.
224                 // Find the actual method implementation being called and
225                 // build the appropriate UFCS call expression with the
226                 // callee-object as expr parameter.
227
228                 // rewrite f(u, v) into FnOnce::call_once(f, (u, v))
229
230                 let method = method_callee(cx, expr, fun.span,None);
231
232                 let arg_tys = args.iter().map(|e| cx.tables().expr_ty_adjusted(e));
233                 let tupled_args = Expr {
234                     ty: cx.tcx.mk_tup(arg_tys),
235                     temp_lifetime,
236                     span: expr.span,
237                     kind: ExprKind::Tuple { fields: args.iter().map(ToRef::to_ref).collect() },
238                 };
239
240                 ExprKind::Call {
241                     ty: method.ty,
242                     fun: method.to_ref(),
243                     args: vec![fun.to_ref(), tupled_args.to_ref()],
244                     from_hir_call: true,
245                 }
246             } else {
247                 let adt_data = if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) =
248                     fun.node
249                 {
250                     // Tuple-like ADTs are represented as ExprKind::Call. We convert them here.
251                     expr_ty.ty_adt_def().and_then(|adt_def| {
252                         match path.res {
253                             Res::Def(DefKind::Ctor(_, CtorKind::Fn), ctor_id) =>
254                                 Some((adt_def, adt_def.variant_index_with_ctor_id(ctor_id))),
255                             Res::SelfCtor(..) => Some((adt_def, VariantIdx::new(0))),
256                             _ => None,
257                         }
258                     })
259                 } else {
260                     None
261                 };
262                 if let Some((adt_def, index)) = adt_data {
263                     let substs = cx.tables().node_substs(fun.hir_id);
264                     let user_provided_types = cx.tables().user_provided_types();
265                     let user_ty = user_provided_types.get(fun.hir_id)
266                         .map(|u_ty| *u_ty)
267                         .map(|mut u_ty| {
268                             if let UserType::TypeOf(ref mut did, _) = &mut u_ty.value {
269                                 *did = adt_def.did;
270                             }
271                             u_ty
272                         });
273                     debug!("make_mirror_unadjusted: (call) user_ty={:?}", user_ty);
274
275                     let field_refs = args.iter()
276                         .enumerate()
277                         .map(|(idx, e)| {
278                             FieldExprRef {
279                                 name: Field::new(idx),
280                                 expr: e.to_ref(),
281                             }
282                         })
283                         .collect();
284                     ExprKind::Adt {
285                         adt_def,
286                         substs,
287                         variant_index: index,
288                         fields: field_refs,
289                         user_ty,
290                         base: None,
291                     }
292                 } else {
293                     ExprKind::Call {
294                         ty: cx.tables().node_type(fun.hir_id),
295                         fun: fun.to_ref(),
296                         args: args.to_ref(),
297                         from_hir_call: true,
298                     }
299                 }
300             }
301         }
302
303         hir::ExprKind::AddrOf(mutbl, ref expr) => {
304             ExprKind::Borrow {
305                 borrow_kind: mutbl.to_borrow_kind(),
306                 arg: expr.to_ref(),
307             }
308         }
309
310         hir::ExprKind::Block(ref blk, _) => ExprKind::Block { body: &blk },
311
312         hir::ExprKind::Assign(ref lhs, ref rhs) => {
313             ExprKind::Assign {
314                 lhs: lhs.to_ref(),
315                 rhs: rhs.to_ref(),
316             }
317         }
318
319         hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => {
320             if cx.tables().is_method_call(expr) {
321                 overloaded_operator(cx, expr, vec![lhs.to_ref(), rhs.to_ref()])
322             } else {
323                 ExprKind::AssignOp {
324                     op: bin_op(op.node),
325                     lhs: lhs.to_ref(),
326                     rhs: rhs.to_ref(),
327                 }
328             }
329         }
330
331         hir::ExprKind::Lit(ref lit) => ExprKind::Literal {
332             literal: cx.tcx.mk_const(
333                 cx.const_eval_literal(&lit.node, expr_ty, lit.span, false)
334             ),
335             user_ty: None,
336         },
337
338         hir::ExprKind::Binary(op, ref lhs, ref rhs) => {
339             if cx.tables().is_method_call(expr) {
340                 overloaded_operator(cx, expr, vec![lhs.to_ref(), rhs.to_ref()])
341             } else {
342                 // FIXME overflow
343                 match (op.node, cx.constness) {
344                     // FIXME(eddyb) use logical ops in constants when
345                     // they can handle that kind of control-flow.
346                     (hir::BinOpKind::And, hir::Constness::Const) => {
347                         cx.control_flow_destroyed.push((
348                             op.span,
349                             "`&&` operator".into(),
350                         ));
351                         ExprKind::Binary {
352                             op: BinOp::BitAnd,
353                             lhs: lhs.to_ref(),
354                             rhs: rhs.to_ref(),
355                         }
356                     }
357                     (hir::BinOpKind::Or, hir::Constness::Const) => {
358                         cx.control_flow_destroyed.push((
359                             op.span,
360                             "`||` operator".into(),
361                         ));
362                         ExprKind::Binary {
363                             op: BinOp::BitOr,
364                             lhs: lhs.to_ref(),
365                             rhs: rhs.to_ref(),
366                         }
367                     }
368
369                     (hir::BinOpKind::And, hir::Constness::NotConst) => {
370                         ExprKind::LogicalOp {
371                             op: LogicalOp::And,
372                             lhs: lhs.to_ref(),
373                             rhs: rhs.to_ref(),
374                         }
375                     }
376                     (hir::BinOpKind::Or, hir::Constness::NotConst) => {
377                         ExprKind::LogicalOp {
378                             op: LogicalOp::Or,
379                             lhs: lhs.to_ref(),
380                             rhs: rhs.to_ref(),
381                         }
382                     }
383
384                     _ => {
385                         let op = bin_op(op.node);
386                         ExprKind::Binary {
387                             op,
388                             lhs: lhs.to_ref(),
389                             rhs: rhs.to_ref(),
390                         }
391                     }
392                 }
393             }
394         }
395
396         hir::ExprKind::Index(ref lhs, ref index) => {
397             if cx.tables().is_method_call(expr) {
398                 overloaded_place(cx, expr, expr_ty, None, vec![lhs.to_ref(), index.to_ref()])
399             } else {
400                 ExprKind::Index {
401                     lhs: lhs.to_ref(),
402                     index: index.to_ref(),
403                 }
404             }
405         }
406
407         hir::ExprKind::Unary(hir::UnOp::UnDeref, ref arg) => {
408             if cx.tables().is_method_call(expr) {
409                 overloaded_place(cx, expr, expr_ty, None, vec![arg.to_ref()])
410             } else {
411                 ExprKind::Deref { arg: arg.to_ref() }
412             }
413         }
414
415         hir::ExprKind::Unary(hir::UnOp::UnNot, ref arg) => {
416             if cx.tables().is_method_call(expr) {
417                 overloaded_operator(cx, expr, vec![arg.to_ref()])
418             } else {
419                 ExprKind::Unary {
420                     op: UnOp::Not,
421                     arg: arg.to_ref(),
422                 }
423             }
424         }
425
426         hir::ExprKind::Unary(hir::UnOp::UnNeg, ref arg) => {
427             if cx.tables().is_method_call(expr) {
428                 overloaded_operator(cx, expr, vec![arg.to_ref()])
429             } else {
430                 if let hir::ExprKind::Lit(ref lit) = arg.node {
431                     ExprKind::Literal {
432                         literal: cx.tcx.mk_const(
433                             cx.const_eval_literal(&lit.node, expr_ty, lit.span, true)
434                         ),
435                         user_ty: None,
436                     }
437                 } else {
438                     ExprKind::Unary {
439                         op: UnOp::Neg,
440                         arg: arg.to_ref(),
441                     }
442                 }
443             }
444         }
445
446         hir::ExprKind::Struct(ref qpath, ref fields, ref base) => {
447             match expr_ty.sty {
448                 ty::Adt(adt, substs) => {
449                     match adt.adt_kind() {
450                         AdtKind::Struct | AdtKind::Union => {
451                             let user_provided_types = cx.tables().user_provided_types();
452                             let user_ty = user_provided_types.get(expr.hir_id).map(|u_ty| *u_ty);
453                             debug!("make_mirror_unadjusted: (struct/union) user_ty={:?}", user_ty);
454                             ExprKind::Adt {
455                                 adt_def: adt,
456                                 variant_index: VariantIdx::new(0),
457                                 substs,
458                                 user_ty,
459                                 fields: field_refs(cx, fields),
460                                 base: base.as_ref().map(|base| {
461                                     FruInfo {
462                                         base: base.to_ref(),
463                                         field_types: cx.tables()
464                                                        .fru_field_types()[expr.hir_id]
465                                                        .clone(),
466                                     }
467                                 }),
468                             }
469                         }
470                         AdtKind::Enum => {
471                             let res = cx.tables().qpath_res(qpath, expr.hir_id);
472                             match res {
473                                 Res::Def(DefKind::Variant, variant_id) => {
474                                     assert!(base.is_none());
475
476                                     let index = adt.variant_index_with_id(variant_id);
477                                     let user_provided_types = cx.tables().user_provided_types();
478                                     let user_ty = user_provided_types.get(expr.hir_id)
479                                         .map(|u_ty| *u_ty);
480                                     debug!(
481                                         "make_mirror_unadjusted: (variant) user_ty={:?}",
482                                         user_ty
483                                     );
484                                     ExprKind::Adt {
485                                         adt_def: adt,
486                                         variant_index: index,
487                                         substs,
488                                         user_ty,
489                                         fields: field_refs(cx, fields),
490                                         base: None,
491                                     }
492                                 }
493                                 _ => {
494                                     span_bug!(expr.span, "unexpected res: {:?}", res);
495                                 }
496                             }
497                         }
498                     }
499                 }
500                 _ => {
501                     span_bug!(expr.span,
502                               "unexpected type for struct literal: {:?}",
503                               expr_ty);
504                 }
505             }
506         }
507
508         hir::ExprKind::Closure(..) => {
509             let closure_ty = cx.tables().expr_ty(expr);
510             let (def_id, substs, movability) = match closure_ty.sty {
511                 ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs), None),
512                 ty::Generator(def_id, substs, movability) => {
513                     (def_id, UpvarSubsts::Generator(substs), Some(movability))
514                 }
515                 _ => {
516                     span_bug!(expr.span, "closure expr w/o closure type: {:?}", closure_ty);
517                 }
518             };
519             let upvars = cx.tcx.upvars(def_id).iter()
520                 .flat_map(|upvars| upvars.iter())
521                 .zip(substs.upvar_tys(def_id, cx.tcx))
522                 .map(|(upvar, ty)| capture_upvar(cx, expr, upvar, ty))
523                 .collect();
524             ExprKind::Closure {
525                 closure_id: def_id,
526                 substs,
527                 upvars,
528                 movability,
529             }
530         }
531
532         hir::ExprKind::Path(ref qpath) => {
533             let res = cx.tables().qpath_res(qpath, expr.hir_id);
534             convert_path_expr(cx, expr, res)
535         }
536
537         hir::ExprKind::InlineAsm(ref asm, ref outputs, ref inputs) => {
538             ExprKind::InlineAsm {
539                 asm,
540                 outputs: outputs.to_ref(),
541                 inputs: inputs.to_ref(),
542             }
543         }
544
545         // Now comes the rote stuff:
546         hir::ExprKind::Repeat(ref v, ref count) => {
547             let def_id = cx.tcx.hir().local_def_id_from_hir_id(count.hir_id);
548             let substs = InternalSubsts::identity_for_item(cx.tcx.global_tcx(), def_id);
549             let instance = ty::Instance::resolve(
550                 cx.tcx.global_tcx(),
551                 cx.param_env,
552                 def_id,
553                 substs,
554             ).unwrap();
555             let global_id = GlobalId {
556                 instance,
557                 promoted: None
558             };
559             let span = cx.tcx.def_span(def_id);
560             let count = match cx.tcx.at(span).const_eval(cx.param_env.and(global_id)) {
561                 Ok(cv) => cv.unwrap_usize(cx.tcx),
562                 Err(ErrorHandled::Reported) => 0,
563                 Err(ErrorHandled::TooGeneric) => {
564                     cx.tcx.sess.span_err(span, "array lengths can't depend on generic parameters");
565                     0
566                 },
567             };
568
569             ExprKind::Repeat {
570                 value: v.to_ref(),
571                 count,
572             }
573         }
574         hir::ExprKind::Ret(ref v) => ExprKind::Return { value: v.to_ref() },
575         hir::ExprKind::Break(dest, ref value) => {
576             match dest.target_id {
577                 Ok(target_id) => ExprKind::Break {
578                     label: region::Scope {
579                         id: target_id.local_id,
580                         data: region::ScopeData::Node
581                     },
582                     value: value.to_ref(),
583                 },
584                 Err(err) => bug!("invalid loop id for break: {}", err)
585             }
586         }
587         hir::ExprKind::Continue(dest) => {
588             match dest.target_id {
589                 Ok(loop_id) => ExprKind::Continue {
590                     label: region::Scope {
591                         id: loop_id.local_id,
592                         data: region::ScopeData::Node
593                     },
594                 },
595                 Err(err) => bug!("invalid loop id for continue: {}", err)
596             }
597         }
598         hir::ExprKind::Match(ref discr, ref arms, _) => {
599             ExprKind::Match {
600                 scrutinee: discr.to_ref(),
601                 arms: arms.iter().map(|a| convert_arm(cx, a)).collect(),
602             }
603         }
604         hir::ExprKind::While(ref cond, ref body, _) => {
605             ExprKind::Loop {
606                 condition: Some(cond.to_ref()),
607                 body: block::to_expr_ref(cx, body),
608             }
609         }
610         hir::ExprKind::Loop(ref body, _, _) => {
611             ExprKind::Loop {
612                 condition: None,
613                 body: block::to_expr_ref(cx, body),
614             }
615         }
616         hir::ExprKind::Field(ref source, ..) => {
617             ExprKind::Field {
618                 lhs: source.to_ref(),
619                 name: Field::new(cx.tcx.field_index(expr.hir_id, cx.tables)),
620             }
621         }
622         hir::ExprKind::Cast(ref source, ref cast_ty) => {
623             // Check for a user-given type annotation on this `cast`
624             let user_provided_types = cx.tables.user_provided_types();
625             let user_ty = user_provided_types.get(cast_ty.hir_id);
626
627             debug!(
628                 "cast({:?}) has ty w/ hir_id {:?} and user provided ty {:?}",
629                 expr,
630                 cast_ty.hir_id,
631                 user_ty,
632             );
633
634             // Check to see if this cast is a "coercion cast", where the cast is actually done
635             // using a coercion (or is a no-op).
636             let cast = if cx.tables().is_coercion_cast(source.hir_id) {
637                 // Convert the lexpr to a vexpr.
638                 ExprKind::Use { source: source.to_ref() }
639             } else {
640                 // check whether this is casting an enum variant discriminant
641                 // to prevent cycles, we refer to the discriminant initializer
642                 // which is always an integer and thus doesn't need to know the
643                 // enum's layout (or its tag type) to compute it during const eval
644                 // Example:
645                 // enum Foo {
646                 //     A,
647                 //     B = A as isize + 4,
648                 // }
649                 // The correct solution would be to add symbolic computations to miri,
650                 // so we wouldn't have to compute and store the actual value
651                 let var = if let hir::ExprKind::Path(ref qpath) = source.node {
652                     let res = cx.tables().qpath_res(qpath, source.hir_id);
653                     cx
654                         .tables()
655                         .node_type(source.hir_id)
656                         .ty_adt_def()
657                         .and_then(|adt_def| {
658                         match res {
659                             Res::Def(
660                                 DefKind::Ctor(CtorOf::Variant, CtorKind::Const),
661                                 variant_ctor_id,
662                             ) => {
663                                 let idx = adt_def.variant_index_with_ctor_id(variant_ctor_id);
664                                 let (d, o) = adt_def.discriminant_def_for_variant(idx);
665                                 use rustc::ty::util::IntTypeExt;
666                                 let ty = adt_def.repr.discr_type();
667                                 let ty = ty.to_ty(cx.tcx());
668                                 Some((d, o, ty))
669                             }
670                             _ => None,
671                         }
672                     })
673                 } else {
674                     None
675                 };
676
677                 let source = if let Some((did, offset, var_ty)) = var {
678                     let mk_const = |literal| Expr {
679                         temp_lifetime,
680                         ty: var_ty,
681                         span: expr.span,
682                         kind: ExprKind::Literal {
683                             literal: cx.tcx.mk_const(literal),
684                             user_ty: None
685                         },
686                     }.to_ref();
687                     let offset = mk_const(ty::Const::from_bits(
688                         cx.tcx,
689                         offset as u128,
690                         cx.param_env.and(var_ty),
691                     ));
692                     match did {
693                         Some(did) => {
694                             // in case we are offsetting from a computed discriminant
695                             // and not the beginning of discriminants (which is always `0`)
696                             let substs = InternalSubsts::identity_for_item(cx.tcx(), did);
697                             let lhs = mk_const(ty::Const {
698                                 val: ConstValue::Unevaluated(did, substs),
699                                 ty: var_ty,
700                             });
701                             let bin = ExprKind::Binary {
702                                 op: BinOp::Add,
703                                 lhs,
704                                 rhs: offset,
705                             };
706                             Expr {
707                                 temp_lifetime,
708                                 ty: var_ty,
709                                 span: expr.span,
710                                 kind: bin,
711                             }.to_ref()
712                         },
713                         None => offset,
714                     }
715                 } else {
716                     source.to_ref()
717                 };
718
719                 ExprKind::Cast { source }
720             };
721
722             if let Some(user_ty) = user_ty {
723                 // NOTE: Creating a new Expr and wrapping a Cast inside of it may be
724                 //       inefficient, revisit this when performance becomes an issue.
725                 let cast_expr = Expr {
726                     temp_lifetime,
727                     ty: expr_ty,
728                     span: expr.span,
729                     kind: cast,
730                 };
731                 debug!("make_mirror_unadjusted: (cast) user_ty={:?}", user_ty);
732
733                 ExprKind::ValueTypeAscription {
734                     source: cast_expr.to_ref(),
735                     user_ty: Some(*user_ty),
736                 }
737             } else {
738                 cast
739             }
740         }
741         hir::ExprKind::Type(ref source, ref ty) => {
742             let user_provided_types = cx.tables.user_provided_types();
743             let user_ty = user_provided_types.get(ty.hir_id).map(|u_ty| *u_ty);
744             debug!("make_mirror_unadjusted: (type) user_ty={:?}", user_ty);
745             if source.is_place_expr() {
746                 ExprKind::PlaceTypeAscription {
747                     source: source.to_ref(),
748                     user_ty,
749                 }
750             } else {
751                 ExprKind::ValueTypeAscription {
752                     source: source.to_ref(),
753                     user_ty,
754                 }
755             }
756         }
757         hir::ExprKind::DropTemps(ref source) => {
758             ExprKind::Use { source: source.to_ref() }
759         }
760         hir::ExprKind::Box(ref value) => {
761             ExprKind::Box {
762                 value: value.to_ref(),
763             }
764         }
765         hir::ExprKind::Array(ref fields) => ExprKind::Array { fields: fields.to_ref() },
766         hir::ExprKind::Tup(ref fields) => ExprKind::Tuple { fields: fields.to_ref() },
767
768         hir::ExprKind::Yield(ref v) => ExprKind::Yield { value: v.to_ref() },
769         hir::ExprKind::Err => unreachable!(),
770     };
771
772     Expr {
773         temp_lifetime,
774         ty: expr_ty,
775         span: expr.span,
776         kind,
777     }
778 }
779
780 fn user_substs_applied_to_res(
781     cx: &mut Cx<'a, 'gcx, 'tcx>,
782     hir_id: hir::HirId,
783     res: Res,
784 ) -> Option<ty::CanonicalUserType<'tcx>> {
785     debug!("user_substs_applied_to_res: res={:?}", res);
786     let user_provided_type = match res {
787         // A reference to something callable -- e.g., a fn, method, or
788         // a tuple-struct or tuple-variant. This has the type of a
789         // `Fn` but with the user-given substitutions.
790         Res::Def(DefKind::Fn, _) |
791         Res::Def(DefKind::Method, _) |
792         Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) |
793         Res::Def(DefKind::Const, _) |
794         Res::Def(DefKind::AssociatedConst, _) =>
795             cx.tables().user_provided_types().get(hir_id).map(|u_ty| *u_ty),
796
797         // A unit struct/variant which is used as a value (e.g.,
798         // `None`). This has the type of the enum/struct that defines
799         // this variant -- but with the substitutions given by the
800         // user.
801         Res::Def(DefKind::Ctor(_, CtorKind::Const), _) =>
802             cx.user_substs_applied_to_ty_of_hir_id(hir_id),
803
804         // `Self` is used in expression as a tuple struct constructor or an unit struct constructor
805         Res::SelfCtor(_) =>
806             cx.user_substs_applied_to_ty_of_hir_id(hir_id),
807
808         _ =>
809             bug!("user_substs_applied_to_res: unexpected res {:?} at {:?}", res, hir_id)
810     };
811     debug!("user_substs_applied_to_res: user_provided_type={:?}", user_provided_type);
812     user_provided_type
813 }
814
815 fn method_callee<'a, 'gcx, 'tcx>(
816     cx: &mut Cx<'a, 'gcx, 'tcx>,
817     expr: &hir::Expr,
818     span: Span,
819     overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>,
820 ) -> Expr<'tcx> {
821     let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id);
822     let (def_id, substs, user_ty) = match overloaded_callee {
823         Some((def_id, substs)) => (def_id, substs, None),
824         None => {
825             let (kind, def_id) = cx.tables().type_dependent_def(expr.hir_id)
826                 .unwrap_or_else(|| {
827                     span_bug!(expr.span, "no type-dependent def for method callee")
828                 });
829             let user_ty = user_substs_applied_to_res(cx, expr.hir_id, Res::Def(kind, def_id));
830             debug!("method_callee: user_ty={:?}", user_ty);
831             (def_id, cx.tables().node_substs(expr.hir_id), user_ty)
832         }
833     };
834     let ty = cx.tcx().mk_fn_def(def_id, substs);
835     Expr {
836         temp_lifetime,
837         ty,
838         span,
839         kind: ExprKind::Literal {
840             literal: cx.tcx().mk_const(
841                 ty::Const::zero_sized(ty)
842             ),
843             user_ty,
844         },
845     }
846 }
847
848 trait ToBorrowKind { fn to_borrow_kind(&self) -> BorrowKind; }
849
850 impl ToBorrowKind for AutoBorrowMutability {
851     fn to_borrow_kind(&self) -> BorrowKind {
852         use rustc::ty::adjustment::AllowTwoPhase;
853         match *self {
854             AutoBorrowMutability::Mutable { allow_two_phase_borrow } =>
855                 BorrowKind::Mut { allow_two_phase_borrow: match allow_two_phase_borrow {
856                     AllowTwoPhase::Yes => true,
857                     AllowTwoPhase::No => false
858                 }},
859             AutoBorrowMutability::Immutable =>
860                 BorrowKind::Shared,
861         }
862     }
863 }
864
865 impl ToBorrowKind for hir::Mutability {
866     fn to_borrow_kind(&self) -> BorrowKind {
867         match *self {
868             hir::MutMutable => BorrowKind::Mut { allow_two_phase_borrow: false },
869             hir::MutImmutable => BorrowKind::Shared,
870         }
871     }
872 }
873
874 fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> {
875     Arm {
876         patterns: arm.pats.iter().map(|p| cx.pattern_from_hir(p)).collect(),
877         guard: match arm.guard {
878                 Some(hir::Guard::If(ref e)) => Some(Guard::If(e.to_ref())),
879                 _ => None,
880             },
881         body: arm.body.to_ref(),
882         // BUG: fix this
883         lint_level: LintLevel::Inherited,
884     }
885 }
886
887 fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
888                                      expr: &'tcx hir::Expr,
889                                      res: Res)
890                                      -> ExprKind<'tcx> {
891     let substs = cx.tables().node_substs(expr.hir_id);
892     match res {
893         // A regular function, constructor function or a constant.
894         Res::Def(DefKind::Fn, _) |
895         Res::Def(DefKind::Method, _) |
896         Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) |
897         Res::SelfCtor(..) => {
898             let user_ty = user_substs_applied_to_res(cx, expr.hir_id, res);
899             debug!("convert_path_expr: user_ty={:?}", user_ty);
900             ExprKind::Literal {
901                 literal: cx.tcx.mk_const(ty::Const::zero_sized(
902                     cx.tables().node_type(expr.hir_id),
903                 )),
904                 user_ty,
905             }
906         }
907
908         Res::Def(DefKind::ConstParam, def_id) => {
909             let node_id = cx.tcx.hir().as_local_node_id(def_id).unwrap();
910             let item_id = cx.tcx.hir().get_parent_node(node_id);
911             let item_def_id = cx.tcx.hir().local_def_id(item_id);
912             let generics = cx.tcx.generics_of(item_def_id);
913             let index = generics.param_def_id_to_index[&cx.tcx.hir().local_def_id(node_id)];
914             let name = cx.tcx.hir().name(node_id).as_interned_str();
915             let val = ConstValue::Param(ty::ParamConst::new(index, name));
916             ExprKind::Literal {
917                 literal: cx.tcx.mk_const(
918                     ty::Const {
919                         val,
920                         ty: cx.tables().node_type(expr.hir_id),
921                     }
922                 ),
923                 user_ty: None,
924             }
925         }
926
927         Res::Def(DefKind::Const, def_id) |
928         Res::Def(DefKind::AssociatedConst, def_id) => {
929             let user_ty = user_substs_applied_to_res(cx, expr.hir_id, res);
930             debug!("convert_path_expr: (const) user_ty={:?}", user_ty);
931             ExprKind::Literal {
932                 literal: cx.tcx.mk_const(ty::Const {
933                     val: ConstValue::Unevaluated(def_id, substs),
934                     ty: cx.tcx.type_of(def_id),
935                 }),
936                 user_ty,
937             }
938         },
939
940         Res::Def(DefKind::Ctor(_, CtorKind::Const), def_id) => {
941             let user_provided_types = cx.tables.user_provided_types();
942             let user_provided_type = user_provided_types.get(expr.hir_id).map(|u_ty| *u_ty);
943             debug!("convert_path_expr: user_provided_type={:?}", user_provided_type);
944             let ty = cx.tables().node_type(expr.hir_id);
945             match ty.sty {
946                 // A unit struct/variant which is used as a value.
947                 // We return a completely different ExprKind here to account for this special case.
948                 ty::Adt(adt_def, substs) => {
949                     ExprKind::Adt {
950                         adt_def,
951                         variant_index: adt_def.variant_index_with_ctor_id(def_id),
952                         substs,
953                         user_ty: user_provided_type,
954                         fields: vec![],
955                         base: None,
956                     }
957                 }
958                 _ => bug!("unexpected ty: {:?}", ty),
959             }
960         }
961
962         Res::Def(DefKind::Static, id) => ExprKind::StaticRef { id },
963
964         Res::Local(..) | Res::Upvar(..) => convert_var(cx, expr, res),
965
966         _ => span_bug!(expr.span, "res `{:?}` not yet implemented", res),
967     }
968 }
969
970 fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
971                                expr: &'tcx hir::Expr,
972                                res: Res)
973                                -> ExprKind<'tcx> {
974     let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id);
975
976     match res {
977         Res::Local(id) => ExprKind::VarRef { id },
978
979         Res::Upvar(var_hir_id, index, closure_expr_id) => {
980             debug!("convert_var(upvar({:?}, {:?}, {:?}))",
981                    var_hir_id,
982                    index,
983                    closure_expr_id);
984             let var_ty = cx.tables().node_type(var_hir_id);
985
986             // FIXME free regions in closures are not right
987             let closure_ty = cx.tables()
988                                .node_type(cx.tcx.hir().node_to_hir_id(closure_expr_id));
989
990             // FIXME we're just hard-coding the idea that the
991             // signature will be &self or &mut self and hence will
992             // have a bound region with number 0
993             let closure_def_id = cx.tcx.hir().local_def_id(closure_expr_id);
994             let region = ty::ReFree(ty::FreeRegion {
995                 scope: closure_def_id,
996                 bound_region: ty::BoundRegion::BrAnon(0),
997             });
998             let region = cx.tcx.mk_region(region);
999
1000             let self_expr = if let ty::Closure(_, closure_substs) = closure_ty.sty {
1001                 match cx.infcx.closure_kind(closure_def_id, closure_substs).unwrap() {
1002                     ty::ClosureKind::Fn => {
1003                         let ref_closure_ty = cx.tcx.mk_ref(region,
1004                                                            ty::TypeAndMut {
1005                                                                ty: closure_ty,
1006                                                                mutbl: hir::MutImmutable,
1007                                                            });
1008                         Expr {
1009                             ty: closure_ty,
1010                             temp_lifetime: temp_lifetime,
1011                             span: expr.span,
1012                             kind: ExprKind::Deref {
1013                                 arg: Expr {
1014                                     ty: ref_closure_ty,
1015                                     temp_lifetime,
1016                                     span: expr.span,
1017                                     kind: ExprKind::SelfRef,
1018                                 }
1019                                 .to_ref(),
1020                             },
1021                         }
1022                     }
1023                     ty::ClosureKind::FnMut => {
1024                         let ref_closure_ty = cx.tcx.mk_ref(region,
1025                                                            ty::TypeAndMut {
1026                                                                ty: closure_ty,
1027                                                                mutbl: hir::MutMutable,
1028                                                            });
1029                         Expr {
1030                             ty: closure_ty,
1031                             temp_lifetime,
1032                             span: expr.span,
1033                             kind: ExprKind::Deref {
1034                                 arg: Expr {
1035                                     ty: ref_closure_ty,
1036                                     temp_lifetime,
1037                                     span: expr.span,
1038                                     kind: ExprKind::SelfRef,
1039                                 }.to_ref(),
1040                             },
1041                         }
1042                     }
1043                     ty::ClosureKind::FnOnce => {
1044                         Expr {
1045                             ty: closure_ty,
1046                             temp_lifetime,
1047                             span: expr.span,
1048                             kind: ExprKind::SelfRef,
1049                         }
1050                     }
1051                 }
1052             } else {
1053                 Expr {
1054                     ty: closure_ty,
1055                     temp_lifetime,
1056                     span: expr.span,
1057                     kind: ExprKind::SelfRef,
1058                 }
1059             };
1060
1061             // at this point we have `self.n`, which loads up the upvar
1062             let field_kind = ExprKind::Field {
1063                 lhs: self_expr.to_ref(),
1064                 name: Field::new(index),
1065             };
1066
1067             // ...but the upvar might be an `&T` or `&mut T` capture, at which
1068             // point we need an implicit deref
1069             let upvar_id = ty::UpvarId {
1070                 var_path: ty::UpvarPath {hir_id: var_hir_id},
1071                 closure_expr_id: LocalDefId::from_def_id(closure_def_id),
1072             };
1073             match cx.tables().upvar_capture(upvar_id) {
1074                 ty::UpvarCapture::ByValue => field_kind,
1075                 ty::UpvarCapture::ByRef(borrow) => {
1076                     ExprKind::Deref {
1077                         arg: Expr {
1078                             temp_lifetime,
1079                             ty: cx.tcx.mk_ref(borrow.region,
1080                                               ty::TypeAndMut {
1081                                                   ty: var_ty,
1082                                                   mutbl: borrow.kind.to_mutbl_lossy(),
1083                                               }),
1084                             span: expr.span,
1085                             kind: field_kind,
1086                         }.to_ref(),
1087                     }
1088                 }
1089             }
1090         }
1091
1092         _ => span_bug!(expr.span, "type of & not region"),
1093     }
1094 }
1095
1096
1097 fn bin_op(op: hir::BinOpKind) -> BinOp {
1098     match op {
1099         hir::BinOpKind::Add => BinOp::Add,
1100         hir::BinOpKind::Sub => BinOp::Sub,
1101         hir::BinOpKind::Mul => BinOp::Mul,
1102         hir::BinOpKind::Div => BinOp::Div,
1103         hir::BinOpKind::Rem => BinOp::Rem,
1104         hir::BinOpKind::BitXor => BinOp::BitXor,
1105         hir::BinOpKind::BitAnd => BinOp::BitAnd,
1106         hir::BinOpKind::BitOr => BinOp::BitOr,
1107         hir::BinOpKind::Shl => BinOp::Shl,
1108         hir::BinOpKind::Shr => BinOp::Shr,
1109         hir::BinOpKind::Eq => BinOp::Eq,
1110         hir::BinOpKind::Lt => BinOp::Lt,
1111         hir::BinOpKind::Le => BinOp::Le,
1112         hir::BinOpKind::Ne => BinOp::Ne,
1113         hir::BinOpKind::Ge => BinOp::Ge,
1114         hir::BinOpKind::Gt => BinOp::Gt,
1115         _ => bug!("no equivalent for ast binop {:?}", op),
1116     }
1117 }
1118
1119 fn overloaded_operator<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
1120                                        expr: &'tcx hir::Expr,
1121                                        args: Vec<ExprRef<'tcx>>)
1122                                        -> ExprKind<'tcx> {
1123     let fun = method_callee(cx, expr, expr.span, None);
1124     ExprKind::Call {
1125         ty: fun.ty,
1126         fun: fun.to_ref(),
1127         args,
1128         from_hir_call: false,
1129     }
1130 }
1131
1132 fn overloaded_place<'a, 'gcx, 'tcx>(
1133     cx: &mut Cx<'a, 'gcx, 'tcx>,
1134     expr: &'tcx hir::Expr,
1135     place_ty: Ty<'tcx>,
1136     overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>,
1137     args: Vec<ExprRef<'tcx>>,
1138 ) -> ExprKind<'tcx> {
1139     // For an overloaded *x or x[y] expression of type T, the method
1140     // call returns an &T and we must add the deref so that the types
1141     // line up (this is because `*x` and `x[y]` represent places):
1142
1143     let recv_ty = match args[0] {
1144         ExprRef::Hair(e) => cx.tables().expr_ty_adjusted(e),
1145         ExprRef::Mirror(ref e) => e.ty
1146     };
1147
1148     // Reconstruct the output assuming it's a reference with the
1149     // same region and mutability as the receiver. This holds for
1150     // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
1151     let (region, mutbl) = match recv_ty.sty {
1152         ty::Ref(region, _, mutbl) => (region, mutbl),
1153         _ => span_bug!(expr.span, "overloaded_place: receiver is not a reference"),
1154     };
1155     let ref_ty = cx.tcx.mk_ref(region, ty::TypeAndMut {
1156         ty: place_ty,
1157         mutbl,
1158     });
1159
1160     // construct the complete expression `foo()` for the overloaded call,
1161     // which will yield the &T type
1162     let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id);
1163     let fun = method_callee(cx, expr, expr.span, overloaded_callee);
1164     let ref_expr = Expr {
1165         temp_lifetime,
1166         ty: ref_ty,
1167         span: expr.span,
1168         kind: ExprKind::Call {
1169             ty: fun.ty,
1170             fun: fun.to_ref(),
1171             args,
1172             from_hir_call: false,
1173         },
1174     };
1175
1176     // construct and return a deref wrapper `*foo()`
1177     ExprKind::Deref { arg: ref_expr.to_ref() }
1178 }
1179
1180 fn capture_upvar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
1181                                    closure_expr: &'tcx hir::Expr,
1182                                    upvar: &hir::Upvar,
1183                                    upvar_ty: Ty<'tcx>)
1184                                    -> ExprRef<'tcx> {
1185     let var_hir_id = upvar.var_id();
1186     let upvar_id = ty::UpvarId {
1187         var_path: ty::UpvarPath { hir_id: var_hir_id },
1188         closure_expr_id: cx.tcx.hir().local_def_id_from_hir_id(closure_expr.hir_id).to_local(),
1189     };
1190     let upvar_capture = cx.tables().upvar_capture(upvar_id);
1191     let temp_lifetime = cx.region_scope_tree.temporary_scope(closure_expr.hir_id.local_id);
1192     let var_ty = cx.tables().node_type(var_hir_id);
1193     let captured_var = Expr {
1194         temp_lifetime,
1195         ty: var_ty,
1196         span: closure_expr.span,
1197         kind: convert_var(cx, closure_expr, upvar.res),
1198     };
1199     match upvar_capture {
1200         ty::UpvarCapture::ByValue => captured_var.to_ref(),
1201         ty::UpvarCapture::ByRef(upvar_borrow) => {
1202             let borrow_kind = match upvar_borrow.kind {
1203                 ty::BorrowKind::ImmBorrow => BorrowKind::Shared,
1204                 ty::BorrowKind::UniqueImmBorrow => BorrowKind::Unique,
1205                 ty::BorrowKind::MutBorrow => BorrowKind::Mut { allow_two_phase_borrow: false }
1206             };
1207             Expr {
1208                 temp_lifetime,
1209                 ty: upvar_ty,
1210                 span: closure_expr.span,
1211                 kind: ExprKind::Borrow {
1212                     borrow_kind,
1213                     arg: captured_var.to_ref(),
1214                 },
1215             }.to_ref()
1216         }
1217     }
1218 }
1219
1220 /// Converts a list of named fields (i.e., for struct-like struct/enum ADTs) into FieldExprRef.
1221 fn field_refs<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
1222                               fields: &'tcx [hir::Field])
1223                               -> Vec<FieldExprRef<'tcx>> {
1224     fields.iter()
1225         .map(|field| {
1226             FieldExprRef {
1227                 name: Field::new(cx.tcx.field_index(field.hir_id, cx.tables)),
1228                 expr: field.expr.to_ref(),
1229             }
1230         })
1231         .collect()
1232 }