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