]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_mir_build/src/thir/cx/expr.rs
Pull `thir::Cx` out of the MIR `Builder`
[rust.git] / compiler / rustc_mir_build / src / thir / cx / expr.rs
1 use crate::thir::cx::Cx;
2 use crate::thir::util::UserAnnotatedTyHelpers;
3 use crate::thir::*;
4 use rustc_hir as hir;
5 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
6 use rustc_index::vec::Idx;
7 use rustc_middle::hir::place::PlaceBase as HirPlaceBase;
8 use rustc_middle::hir::place::ProjectionKind as HirProjectionKind;
9 use rustc_middle::mir::interpret::Scalar;
10 use rustc_middle::mir::BorrowKind;
11 use rustc_middle::ty::adjustment::{
12     Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, PointerCast,
13 };
14 use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
15 use rustc_middle::ty::{self, AdtKind, Ty};
16 use rustc_span::Span;
17
18 impl<'tcx> Cx<'tcx> {
19     crate fn mirror_expr(&mut self, hir_expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> {
20         let temp_lifetime = self.region_scope_tree.temporary_scope(hir_expr.hir_id.local_id);
21         let expr_scope =
22             region::Scope { id: hir_expr.hir_id.local_id, data: region::ScopeData::Node };
23
24         debug!("Expr::make_mirror(): id={}, span={:?}", hir_expr.hir_id, hir_expr.span);
25
26         let mut expr = self.make_mirror_unadjusted(hir_expr);
27
28         // Now apply adjustments, if any.
29         for adjustment in self.typeck_results.expr_adjustments(hir_expr) {
30             debug!("make_mirror: expr={:?} applying adjustment={:?}", expr, adjustment);
31             expr = self.apply_adjustment(hir_expr, expr, adjustment);
32         }
33
34         // Next, wrap this up in the expr's scope.
35         expr = Expr {
36             temp_lifetime,
37             ty: expr.ty,
38             span: hir_expr.span,
39             kind: ExprKind::Scope {
40                 region_scope: expr_scope,
41                 value: Box::new(expr),
42                 lint_level: LintLevel::Explicit(hir_expr.hir_id),
43             },
44         };
45
46         // Finally, create a destruction scope, if any.
47         if let Some(region_scope) =
48             self.region_scope_tree.opt_destruction_scope(hir_expr.hir_id.local_id)
49         {
50             expr = Expr {
51                 temp_lifetime,
52                 ty: expr.ty,
53                 span: hir_expr.span,
54                 kind: ExprKind::Scope {
55                     region_scope,
56                     value: Box::new(expr),
57                     lint_level: LintLevel::Inherited,
58                 },
59             };
60         }
61
62         // OK, all done!
63         expr
64     }
65
66     crate fn mirror_exprs(&mut self, exprs: &'tcx [hir::Expr<'tcx>]) -> Vec<Expr<'tcx>> {
67         exprs.iter().map(|expr| self.mirror_expr(expr)).collect()
68     }
69
70     crate fn mirror_expr_boxed(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Box<Expr<'tcx>> {
71         Box::new(self.mirror_expr(expr))
72     }
73
74     fn apply_adjustment(
75         &mut self,
76         hir_expr: &'tcx hir::Expr<'tcx>,
77         mut expr: Expr<'tcx>,
78         adjustment: &Adjustment<'tcx>,
79     ) -> Expr<'tcx> {
80         let Expr { temp_lifetime, mut span, .. } = expr;
81
82         // Adjust the span from the block, to the last expression of the
83         // block. This is a better span when returning a mutable reference
84         // with too short a lifetime. The error message will use the span
85         // from the assignment to the return place, which should only point
86         // at the returned value, not the entire function body.
87         //
88         // fn return_short_lived<'a>(x: &'a mut i32) -> &'static mut i32 {
89         //      x
90         //   // ^ error message points at this expression.
91         // }
92         let mut adjust_span = |expr: &mut Expr<'tcx>| {
93             if let ExprKind::Block { body } = &expr.kind {
94                 if let Some(ref last_expr) = body.expr {
95                     span = last_expr.span;
96                     expr.span = span;
97                 }
98             }
99         };
100
101         let kind = match adjustment.kind {
102             Adjust::Pointer(PointerCast::Unsize) => {
103                 adjust_span(&mut expr);
104                 ExprKind::Pointer { cast: PointerCast::Unsize, source: Box::new(expr) }
105             }
106             Adjust::Pointer(cast) => ExprKind::Pointer { cast, source: Box::new(expr) },
107             Adjust::NeverToAny => ExprKind::NeverToAny { source: Box::new(expr) },
108             Adjust::Deref(None) => {
109                 adjust_span(&mut expr);
110                 ExprKind::Deref { arg: Box::new(expr) }
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(self.tcx(), expr.ty);
116
117                 expr = Expr {
118                     temp_lifetime,
119                     ty: self
120                         .tcx
121                         .mk_ref(deref.region, ty::TypeAndMut { ty: expr.ty, mutbl: deref.mutbl }),
122                     span,
123                     kind: ExprKind::Borrow {
124                         borrow_kind: deref.mutbl.to_borrow_kind(),
125                         arg: Box::new(expr),
126                     },
127                 };
128
129                 self.overloaded_place(
130                     hir_expr,
131                     adjustment.target,
132                     Some(call),
133                     vec![expr],
134                     deref.span,
135                 )
136             }
137             Adjust::Borrow(AutoBorrow::Ref(_, m)) => {
138                 ExprKind::Borrow { borrow_kind: m.to_borrow_kind(), arg: Box::new(expr) }
139             }
140             Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => {
141                 ExprKind::AddressOf { mutability, arg: Box::new(expr) }
142             }
143         };
144
145         Expr { temp_lifetime, ty: adjustment.target, span, kind }
146     }
147
148     fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> {
149         let expr_ty = self.typeck_results().expr_ty(expr);
150         let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id);
151
152         let kind = match expr.kind {
153             // Here comes the interesting stuff:
154             hir::ExprKind::MethodCall(_, method_span, ref args, fn_span) => {
155                 // Rewrite a.b(c) into UFCS form like Trait::b(a, c)
156                 let expr = self.method_callee(expr, method_span, None);
157                 let args = self.mirror_exprs(args);
158                 ExprKind::Call {
159                     ty: expr.ty,
160                     fun: Box::new(expr),
161                     args,
162                     from_hir_call: true,
163                     fn_span,
164                 }
165             }
166
167             hir::ExprKind::Call(ref fun, ref args) => {
168                 if self.typeck_results().is_method_call(expr) {
169                     // The callee is something implementing Fn, FnMut, or FnOnce.
170                     // Find the actual method implementation being called and
171                     // build the appropriate UFCS call expression with the
172                     // callee-object as expr parameter.
173
174                     // rewrite f(u, v) into FnOnce::call_once(f, (u, v))
175
176                     let method = self.method_callee(expr, fun.span, None);
177
178                     let arg_tys = args.iter().map(|e| self.typeck_results().expr_ty_adjusted(e));
179                     let tupled_args = Expr {
180                         ty: self.tcx.mk_tup(arg_tys),
181                         temp_lifetime,
182                         span: expr.span,
183                         kind: ExprKind::Tuple { fields: self.mirror_exprs(args) },
184                     };
185
186                     ExprKind::Call {
187                         ty: method.ty,
188                         fun: Box::new(method),
189                         args: vec![self.mirror_expr(fun), tupled_args],
190                         from_hir_call: true,
191                         fn_span: expr.span,
192                     }
193                 } else {
194                     let adt_data =
195                         if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = fun.kind {
196                             // Tuple-like ADTs are represented as ExprKind::Call. We convert them here.
197                             expr_ty.ty_adt_def().and_then(|adt_def| match path.res {
198                                 Res::Def(DefKind::Ctor(_, CtorKind::Fn), ctor_id) => {
199                                     Some((adt_def, adt_def.variant_index_with_ctor_id(ctor_id)))
200                                 }
201                                 Res::SelfCtor(..) => Some((adt_def, VariantIdx::new(0))),
202                                 _ => None,
203                             })
204                         } else {
205                             None
206                         };
207                     if let Some((adt_def, index)) = adt_data {
208                         let substs = self.typeck_results().node_substs(fun.hir_id);
209                         let user_provided_types = self.typeck_results().user_provided_types();
210                         let user_ty =
211                             user_provided_types.get(fun.hir_id).copied().map(|mut u_ty| {
212                                 if let UserType::TypeOf(ref mut did, _) = &mut u_ty.value {
213                                     *did = adt_def.did;
214                                 }
215                                 u_ty
216                             });
217                         debug!("make_mirror_unadjusted: (call) user_ty={:?}", user_ty);
218
219                         let field_refs = args
220                             .iter()
221                             .enumerate()
222                             .map(|(idx, e)| FieldExpr {
223                                 name: Field::new(idx),
224                                 expr: self.mirror_expr(e),
225                             })
226                             .collect();
227                         ExprKind::Adt {
228                             adt_def,
229                             substs,
230                             variant_index: index,
231                             fields: field_refs,
232                             user_ty,
233                             base: None,
234                         }
235                     } else {
236                         ExprKind::Call {
237                             ty: self.typeck_results().node_type(fun.hir_id),
238                             fun: self.mirror_expr_boxed(fun),
239                             args: self.mirror_exprs(args),
240                             from_hir_call: true,
241                             fn_span: expr.span,
242                         }
243                     }
244                 }
245             }
246
247             hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mutbl, ref arg) => ExprKind::Borrow {
248                 borrow_kind: mutbl.to_borrow_kind(),
249                 arg: self.mirror_expr_boxed(arg),
250             },
251
252             hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutability, ref arg) => {
253                 ExprKind::AddressOf { mutability, arg: self.mirror_expr_boxed(arg) }
254             }
255
256             hir::ExprKind::Block(ref blk, _) => ExprKind::Block { body: self.mirror_block(blk) },
257
258             hir::ExprKind::Assign(ref lhs, ref rhs, _) => ExprKind::Assign {
259                 lhs: self.mirror_expr_boxed(lhs),
260                 rhs: self.mirror_expr_boxed(rhs),
261             },
262
263             hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => {
264                 if self.typeck_results().is_method_call(expr) {
265                     let lhs = self.mirror_expr(lhs);
266                     let rhs = self.mirror_expr(rhs);
267                     self.overloaded_operator(expr, vec![lhs, rhs])
268                 } else {
269                     ExprKind::AssignOp {
270                         op: bin_op(op.node),
271                         lhs: self.mirror_expr_boxed(lhs),
272                         rhs: self.mirror_expr_boxed(rhs),
273                     }
274                 }
275             }
276
277             hir::ExprKind::Lit(ref lit) => ExprKind::Literal {
278                 literal: self.const_eval_literal(&lit.node, expr_ty, lit.span, false),
279                 user_ty: None,
280                 const_id: None,
281             },
282
283             hir::ExprKind::Binary(op, ref lhs, ref rhs) => {
284                 if self.typeck_results().is_method_call(expr) {
285                     let lhs = self.mirror_expr(lhs);
286                     let rhs = self.mirror_expr(rhs);
287                     self.overloaded_operator(expr, vec![lhs, rhs])
288                 } else {
289                     // FIXME overflow
290                     match op.node {
291                         hir::BinOpKind::And => ExprKind::LogicalOp {
292                             op: LogicalOp::And,
293                             lhs: self.mirror_expr_boxed(lhs),
294                             rhs: self.mirror_expr_boxed(rhs),
295                         },
296                         hir::BinOpKind::Or => ExprKind::LogicalOp {
297                             op: LogicalOp::Or,
298                             lhs: self.mirror_expr_boxed(lhs),
299                             rhs: self.mirror_expr_boxed(rhs),
300                         },
301
302                         _ => {
303                             let op = bin_op(op.node);
304                             ExprKind::Binary {
305                                 op,
306                                 lhs: self.mirror_expr_boxed(lhs),
307                                 rhs: self.mirror_expr_boxed(rhs),
308                             }
309                         }
310                     }
311                 }
312             }
313
314             hir::ExprKind::Index(ref lhs, ref index) => {
315                 if self.typeck_results().is_method_call(expr) {
316                     let lhs = self.mirror_expr(lhs);
317                     let index = self.mirror_expr(index);
318                     self.overloaded_place(expr, expr_ty, None, vec![lhs, index], expr.span)
319                 } else {
320                     ExprKind::Index {
321                         lhs: self.mirror_expr_boxed(lhs),
322                         index: self.mirror_expr_boxed(index),
323                     }
324                 }
325             }
326
327             hir::ExprKind::Unary(hir::UnOp::Deref, ref arg) => {
328                 if self.typeck_results().is_method_call(expr) {
329                     let arg = self.mirror_expr(arg);
330                     self.overloaded_place(expr, expr_ty, None, vec![arg], expr.span)
331                 } else {
332                     ExprKind::Deref { arg: self.mirror_expr_boxed(arg) }
333                 }
334             }
335
336             hir::ExprKind::Unary(hir::UnOp::Not, ref arg) => {
337                 if self.typeck_results().is_method_call(expr) {
338                     let arg = self.mirror_expr(arg);
339                     self.overloaded_operator(expr, vec![arg])
340                 } else {
341                     ExprKind::Unary { op: UnOp::Not, arg: self.mirror_expr_boxed(arg) }
342                 }
343             }
344
345             hir::ExprKind::Unary(hir::UnOp::Neg, ref arg) => {
346                 if self.typeck_results().is_method_call(expr) {
347                     let arg = self.mirror_expr(arg);
348                     self.overloaded_operator(expr, vec![arg])
349                 } else if let hir::ExprKind::Lit(ref lit) = arg.kind {
350                     ExprKind::Literal {
351                         literal: self.const_eval_literal(&lit.node, expr_ty, lit.span, true),
352                         user_ty: None,
353                         const_id: None,
354                     }
355                 } else {
356                     ExprKind::Unary { op: UnOp::Neg, arg: self.mirror_expr_boxed(arg) }
357                 }
358             }
359
360             hir::ExprKind::Struct(ref qpath, ref fields, ref base) => match expr_ty.kind() {
361                 ty::Adt(adt, substs) => match adt.adt_kind() {
362                     AdtKind::Struct | AdtKind::Union => {
363                         let user_provided_types = self.typeck_results().user_provided_types();
364                         let user_ty = user_provided_types.get(expr.hir_id).copied();
365                         debug!("make_mirror_unadjusted: (struct/union) user_ty={:?}", user_ty);
366                         ExprKind::Adt {
367                             adt_def: adt,
368                             variant_index: VariantIdx::new(0),
369                             substs,
370                             user_ty,
371                             fields: self.field_refs(fields),
372                             base: base.as_ref().map(|base| FruInfo {
373                                 base: self.mirror_expr_boxed(base),
374                                 field_types: self.typeck_results().fru_field_types()[expr.hir_id]
375                                     .clone(),
376                             }),
377                         }
378                     }
379                     AdtKind::Enum => {
380                         let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
381                         match res {
382                             Res::Def(DefKind::Variant, variant_id) => {
383                                 assert!(base.is_none());
384
385                                 let index = adt.variant_index_with_id(variant_id);
386                                 let user_provided_types =
387                                     self.typeck_results().user_provided_types();
388                                 let user_ty = user_provided_types.get(expr.hir_id).copied();
389                                 debug!("make_mirror_unadjusted: (variant) user_ty={:?}", user_ty);
390                                 ExprKind::Adt {
391                                     adt_def: adt,
392                                     variant_index: index,
393                                     substs,
394                                     user_ty,
395                                     fields: self.field_refs(fields),
396                                     base: None,
397                                 }
398                             }
399                             _ => {
400                                 span_bug!(expr.span, "unexpected res: {:?}", res);
401                             }
402                         }
403                     }
404                 },
405                 _ => {
406                     span_bug!(expr.span, "unexpected type for struct literal: {:?}", expr_ty);
407                 }
408             },
409
410             hir::ExprKind::Closure(..) => {
411                 let closure_ty = self.typeck_results().expr_ty(expr);
412                 let (def_id, substs, movability) = match *closure_ty.kind() {
413                     ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs), None),
414                     ty::Generator(def_id, substs, movability) => {
415                         (def_id, UpvarSubsts::Generator(substs), Some(movability))
416                     }
417                     _ => {
418                         span_bug!(expr.span, "closure expr w/o closure type: {:?}", closure_ty);
419                     }
420                 };
421
422                 let upvars = self
423                     .typeck_results
424                     .closure_min_captures_flattened(def_id)
425                     .zip(substs.upvar_tys())
426                     .map(|(captured_place, ty)| self.capture_upvar(expr, captured_place, ty))
427                     .collect();
428                 ExprKind::Closure { closure_id: def_id, substs, upvars, movability }
429             }
430
431             hir::ExprKind::Path(ref qpath) => {
432                 let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
433                 self.convert_path_expr(expr, res)
434             }
435
436             hir::ExprKind::InlineAsm(ref asm) => ExprKind::InlineAsm {
437                 template: asm.template,
438                 operands: asm
439                     .operands
440                     .iter()
441                     .map(|(op, _op_sp)| {
442                         match *op {
443                             hir::InlineAsmOperand::In { reg, ref expr } => {
444                                 InlineAsmOperand::In { reg, expr: self.mirror_expr(expr) }
445                             }
446                             hir::InlineAsmOperand::Out { reg, late, ref expr } => {
447                                 InlineAsmOperand::Out {
448                                     reg,
449                                     late,
450                                     expr: expr.as_ref().map(|expr| self.mirror_expr(expr)),
451                                 }
452                             }
453                             hir::InlineAsmOperand::InOut { reg, late, ref expr } => {
454                                 InlineAsmOperand::InOut { reg, late, expr: self.mirror_expr(expr) }
455                             }
456                             hir::InlineAsmOperand::SplitInOut {
457                                 reg,
458                                 late,
459                                 ref in_expr,
460                                 ref out_expr,
461                             } => InlineAsmOperand::SplitInOut {
462                                 reg,
463                                 late,
464                                 in_expr: self.mirror_expr(in_expr),
465                                 out_expr: out_expr.as_ref().map(|expr| self.mirror_expr(expr)),
466                             },
467                             hir::InlineAsmOperand::Const { ref expr } => {
468                                 InlineAsmOperand::Const { expr: self.mirror_expr(expr) }
469                             }
470                             hir::InlineAsmOperand::Sym { ref expr } => {
471                                 let qpath = match expr.kind {
472                                     hir::ExprKind::Path(ref qpath) => qpath,
473                                     _ => span_bug!(
474                                         expr.span,
475                                         "asm `sym` operand should be a path, found {:?}",
476                                         expr.kind
477                                     ),
478                                 };
479                                 let temp_lifetime =
480                                     self.region_scope_tree.temporary_scope(expr.hir_id.local_id);
481                                 let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
482                                 let ty;
483                                 match res {
484                                     Res::Def(DefKind::Fn, _) | Res::Def(DefKind::AssocFn, _) => {
485                                         ty = self.typeck_results().node_type(expr.hir_id);
486                                         let user_ty =
487                                             self.user_substs_applied_to_res(expr.hir_id, res);
488                                         InlineAsmOperand::SymFn {
489                                             expr: Expr {
490                                                 ty,
491                                                 temp_lifetime,
492                                                 span: expr.span,
493                                                 kind: ExprKind::Literal {
494                                                     literal: ty::Const::zero_sized(self.tcx, ty),
495                                                     user_ty,
496                                                     const_id: None,
497                                                 },
498                                             },
499                                         }
500                                     }
501
502                                     Res::Def(DefKind::Static, def_id) => {
503                                         InlineAsmOperand::SymStatic { def_id }
504                                     }
505
506                                     _ => {
507                                         self.tcx.sess.span_err(
508                                             expr.span,
509                                             "asm `sym` operand must point to a fn or static",
510                                         );
511
512                                         // Not a real fn, but we're not reaching codegen anyways...
513                                         ty = self.tcx.ty_error();
514                                         InlineAsmOperand::SymFn {
515                                             expr: Expr {
516                                                 ty,
517                                                 temp_lifetime,
518                                                 span: expr.span,
519                                                 kind: ExprKind::Literal {
520                                                     literal: ty::Const::zero_sized(self.tcx, ty),
521                                                     user_ty: None,
522                                                     const_id: None,
523                                                 },
524                                             },
525                                         }
526                                     }
527                                 }
528                             }
529                         }
530                     })
531                     .collect(),
532                 options: asm.options,
533                 line_spans: asm.line_spans,
534             },
535
536             hir::ExprKind::LlvmInlineAsm(ref asm) => ExprKind::LlvmInlineAsm {
537                 asm: &asm.inner,
538                 outputs: self.mirror_exprs(asm.outputs_exprs),
539                 inputs: self.mirror_exprs(asm.inputs_exprs),
540             },
541
542             hir::ExprKind::ConstBlock(ref anon_const) => {
543                 let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id);
544                 let value = ty::Const::from_anon_const(self.tcx, anon_const_def_id);
545
546                 ExprKind::ConstBlock { value }
547             }
548             // Now comes the rote stuff:
549             hir::ExprKind::Repeat(ref v, ref count) => {
550                 let count_def_id = self.tcx.hir().local_def_id(count.hir_id);
551                 let count = ty::Const::from_anon_const(self.tcx, count_def_id);
552
553                 ExprKind::Repeat { value: self.mirror_expr_boxed(v), count }
554             }
555             hir::ExprKind::Ret(ref v) => {
556                 ExprKind::Return { value: v.as_ref().map(|v| self.mirror_expr_boxed(v)) }
557             }
558             hir::ExprKind::Break(dest, ref value) => match dest.target_id {
559                 Ok(target_id) => ExprKind::Break {
560                     label: region::Scope { id: target_id.local_id, data: region::ScopeData::Node },
561                     value: value.as_ref().map(|value| self.mirror_expr_boxed(value)),
562                 },
563                 Err(err) => bug!("invalid loop id for break: {}", err),
564             },
565             hir::ExprKind::Continue(dest) => match dest.target_id {
566                 Ok(loop_id) => ExprKind::Continue {
567                     label: region::Scope { id: loop_id.local_id, data: region::ScopeData::Node },
568                 },
569                 Err(err) => bug!("invalid loop id for continue: {}", err),
570             },
571             hir::ExprKind::If(cond, then, else_opt) => ExprKind::If {
572                 cond: self.mirror_expr_boxed(cond),
573                 then: self.mirror_expr_boxed(then),
574                 else_opt: else_opt.map(|el| self.mirror_expr_boxed(el)),
575             },
576             hir::ExprKind::Match(ref discr, ref arms, _) => ExprKind::Match {
577                 scrutinee: self.mirror_expr_boxed(discr),
578                 arms: arms.iter().map(|a| self.convert_arm(a)).collect(),
579             },
580             hir::ExprKind::Loop(ref body, ..) => {
581                 let block_ty = self.typeck_results().node_type(body.hir_id);
582                 let temp_lifetime = self.region_scope_tree.temporary_scope(body.hir_id.local_id);
583                 let block = self.mirror_block(body);
584                 let body = Box::new(Expr {
585                     ty: block_ty,
586                     temp_lifetime,
587                     span: block.span,
588                     kind: ExprKind::Block { body: block },
589                 });
590                 ExprKind::Loop { body }
591             }
592             hir::ExprKind::Field(ref source, ..) => ExprKind::Field {
593                 lhs: self.mirror_expr_boxed(source),
594                 name: Field::new(self.tcx.field_index(expr.hir_id, self.typeck_results)),
595             },
596             hir::ExprKind::Cast(ref source, ref cast_ty) => {
597                 // Check for a user-given type annotation on this `cast`
598                 let user_provided_types = self.typeck_results.user_provided_types();
599                 let user_ty = user_provided_types.get(cast_ty.hir_id);
600
601                 debug!(
602                     "cast({:?}) has ty w/ hir_id {:?} and user provided ty {:?}",
603                     expr, cast_ty.hir_id, user_ty,
604                 );
605
606                 // Check to see if this cast is a "coercion cast", where the cast is actually done
607                 // using a coercion (or is a no-op).
608                 let cast = if self.typeck_results().is_coercion_cast(source.hir_id) {
609                     // Convert the lexpr to a vexpr.
610                     ExprKind::Use { source: self.mirror_expr_boxed(source) }
611                 } else if self.typeck_results().expr_ty(source).is_region_ptr() {
612                     // Special cased so that we can type check that the element
613                     // type of the source matches the pointed to type of the
614                     // destination.
615                     ExprKind::Pointer {
616                         source: self.mirror_expr_boxed(source),
617                         cast: PointerCast::ArrayToPointer,
618                     }
619                 } else {
620                     // check whether this is casting an enum variant discriminant
621                     // to prevent cycles, we refer to the discriminant initializer
622                     // which is always an integer and thus doesn't need to know the
623                     // enum's layout (or its tag type) to compute it during const eval
624                     // Example:
625                     // enum Foo {
626                     //     A,
627                     //     B = A as isize + 4,
628                     // }
629                     // The correct solution would be to add symbolic computations to miri,
630                     // so we wouldn't have to compute and store the actual value
631                     let var = if let hir::ExprKind::Path(ref qpath) = source.kind {
632                         let res = self.typeck_results().qpath_res(qpath, source.hir_id);
633                         self.typeck_results().node_type(source.hir_id).ty_adt_def().and_then(
634                             |adt_def| match res {
635                                 Res::Def(
636                                     DefKind::Ctor(CtorOf::Variant, CtorKind::Const),
637                                     variant_ctor_id,
638                                 ) => {
639                                     let idx = adt_def.variant_index_with_ctor_id(variant_ctor_id);
640                                     let (d, o) = adt_def.discriminant_def_for_variant(idx);
641                                     use rustc_middle::ty::util::IntTypeExt;
642                                     let ty = adt_def.repr.discr_type();
643                                     let ty = ty.to_ty(self.tcx());
644                                     Some((d, o, ty))
645                                 }
646                                 _ => None,
647                             },
648                         )
649                     } else {
650                         None
651                     };
652
653                     let source = if let Some((did, offset, var_ty)) = var {
654                         let mk_const = |literal| Expr {
655                             temp_lifetime,
656                             ty: var_ty,
657                             span: expr.span,
658                             kind: ExprKind::Literal { literal, user_ty: None, const_id: None },
659                         };
660                         let offset = mk_const(ty::Const::from_bits(
661                             self.tcx,
662                             offset as u128,
663                             self.param_env.and(var_ty),
664                         ));
665                         match did {
666                             Some(did) => {
667                                 // in case we are offsetting from a computed discriminant
668                                 // and not the beginning of discriminants (which is always `0`)
669                                 let substs = InternalSubsts::identity_for_item(self.tcx(), did);
670                                 let lhs = mk_const(self.tcx().mk_const(ty::Const {
671                                     val: ty::ConstKind::Unevaluated(
672                                         ty::WithOptConstParam::unknown(did),
673                                         substs,
674                                         None,
675                                     ),
676                                     ty: var_ty,
677                                 }));
678                                 let bin = ExprKind::Binary {
679                                     op: BinOp::Add,
680                                     lhs: Box::new(lhs),
681                                     rhs: Box::new(offset),
682                                 };
683                                 Expr { temp_lifetime, ty: var_ty, span: expr.span, kind: bin }
684                             }
685                             None => offset,
686                         }
687                     } else {
688                         self.mirror_expr(source)
689                     };
690
691                     ExprKind::Cast { source: Box::new(source) }
692                 };
693
694                 if let Some(user_ty) = user_ty {
695                     // NOTE: Creating a new Expr and wrapping a Cast inside of it may be
696                     //       inefficient, revisit this when performance becomes an issue.
697                     let cast_expr =
698                         Box::new(Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind: cast });
699                     debug!("make_mirror_unadjusted: (cast) user_ty={:?}", user_ty);
700
701                     ExprKind::ValueTypeAscription { source: cast_expr, user_ty: Some(*user_ty) }
702                 } else {
703                     cast
704                 }
705             }
706             hir::ExprKind::Type(ref source, ref ty) => {
707                 let user_provided_types = self.typeck_results.user_provided_types();
708                 let user_ty = user_provided_types.get(ty.hir_id).copied();
709                 debug!("make_mirror_unadjusted: (type) user_ty={:?}", user_ty);
710                 let mirrored = self.mirror_expr_boxed(source);
711                 if source.is_syntactic_place_expr() {
712                     ExprKind::PlaceTypeAscription { source: mirrored, user_ty }
713                 } else {
714                     ExprKind::ValueTypeAscription { source: mirrored, user_ty }
715                 }
716             }
717             hir::ExprKind::DropTemps(ref source) => {
718                 ExprKind::Use { source: self.mirror_expr_boxed(source) }
719             }
720             hir::ExprKind::Box(ref value) => ExprKind::Box { value: self.mirror_expr_boxed(value) },
721             hir::ExprKind::Array(ref fields) => ExprKind::Array {
722                 fields: fields.iter().map(|field| self.mirror_expr(field)).collect(),
723             },
724             hir::ExprKind::Tup(ref fields) => ExprKind::Tuple {
725                 fields: fields.iter().map(|field| self.mirror_expr(field)).collect(),
726             },
727
728             hir::ExprKind::Yield(ref v, _) => ExprKind::Yield { value: self.mirror_expr_boxed(v) },
729             hir::ExprKind::Err => unreachable!(),
730         };
731
732         Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind }
733     }
734
735     fn user_substs_applied_to_res(
736         &mut self,
737         hir_id: hir::HirId,
738         res: Res,
739     ) -> Option<ty::CanonicalUserType<'tcx>> {
740         debug!("user_substs_applied_to_res: res={:?}", res);
741         let user_provided_type = match res {
742             // A reference to something callable -- e.g., a fn, method, or
743             // a tuple-struct or tuple-variant. This has the type of a
744             // `Fn` but with the user-given substitutions.
745             Res::Def(DefKind::Fn, _)
746             | Res::Def(DefKind::AssocFn, _)
747             | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _)
748             | Res::Def(DefKind::Const, _)
749             | Res::Def(DefKind::AssocConst, _) => {
750                 self.typeck_results().user_provided_types().get(hir_id).copied()
751             }
752
753             // A unit struct/variant which is used as a value (e.g.,
754             // `None`). This has the type of the enum/struct that defines
755             // this variant -- but with the substitutions given by the
756             // user.
757             Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => {
758                 self.user_substs_applied_to_ty_of_hir_id(hir_id)
759             }
760
761             // `Self` is used in expression as a tuple struct constructor or an unit struct constructor
762             Res::SelfCtor(_) => self.user_substs_applied_to_ty_of_hir_id(hir_id),
763
764             _ => bug!("user_substs_applied_to_res: unexpected res {:?} at {:?}", res, hir_id),
765         };
766         debug!("user_substs_applied_to_res: user_provided_type={:?}", user_provided_type);
767         user_provided_type
768     }
769
770     fn method_callee(
771         &mut self,
772         expr: &hir::Expr<'_>,
773         span: Span,
774         overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>,
775     ) -> Expr<'tcx> {
776         let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id);
777         let (def_id, substs, user_ty) = match overloaded_callee {
778             Some((def_id, substs)) => (def_id, substs, None),
779             None => {
780                 let (kind, def_id) =
781                     self.typeck_results().type_dependent_def(expr.hir_id).unwrap_or_else(|| {
782                         span_bug!(expr.span, "no type-dependent def for method callee")
783                     });
784                 let user_ty = self.user_substs_applied_to_res(expr.hir_id, Res::Def(kind, def_id));
785                 debug!("method_callee: user_ty={:?}", user_ty);
786                 (def_id, self.typeck_results().node_substs(expr.hir_id), user_ty)
787             }
788         };
789         let ty = self.tcx().mk_fn_def(def_id, substs);
790         Expr {
791             temp_lifetime,
792             ty,
793             span,
794             kind: ExprKind::Literal {
795                 literal: ty::Const::zero_sized(self.tcx(), ty),
796                 user_ty,
797                 const_id: None,
798             },
799         }
800     }
801
802     fn convert_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) -> Arm<'tcx> {
803         Arm {
804             pattern: self.pattern_from_hir(&arm.pat),
805             guard: arm.guard.as_ref().map(|g| match g {
806                 hir::Guard::If(ref e) => Guard::If(self.mirror_expr_boxed(e)),
807                 hir::Guard::IfLet(ref pat, ref e) => {
808                     Guard::IfLet(self.pattern_from_hir(pat), self.mirror_expr_boxed(e))
809                 }
810             }),
811             body: self.mirror_expr(arm.body),
812             lint_level: LintLevel::Explicit(arm.hir_id),
813             scope: region::Scope { id: arm.hir_id.local_id, data: region::ScopeData::Node },
814             span: arm.span,
815         }
816     }
817
818     fn convert_path_expr(&mut self, expr: &'tcx hir::Expr<'tcx>, res: Res) -> ExprKind<'tcx> {
819         let substs = self.typeck_results().node_substs(expr.hir_id);
820         match res {
821             // A regular function, constructor function or a constant.
822             Res::Def(DefKind::Fn, _)
823             | Res::Def(DefKind::AssocFn, _)
824             | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _)
825             | Res::SelfCtor(..) => {
826                 let user_ty = self.user_substs_applied_to_res(expr.hir_id, res);
827                 debug!("convert_path_expr: user_ty={:?}", user_ty);
828                 ExprKind::Literal {
829                     literal: ty::Const::zero_sized(
830                         self.tcx,
831                         self.typeck_results().node_type(expr.hir_id),
832                     ),
833                     user_ty,
834                     const_id: None,
835                 }
836             }
837
838             Res::Def(DefKind::ConstParam, def_id) => {
839                 let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
840                 let item_id = self.tcx.hir().get_parent_node(hir_id);
841                 let item_def_id = self.tcx.hir().local_def_id(item_id);
842                 let generics = self.tcx.generics_of(item_def_id);
843                 let index = generics.param_def_id_to_index[&def_id];
844                 let name = self.tcx.hir().name(hir_id);
845                 let val = ty::ConstKind::Param(ty::ParamConst::new(index, name));
846                 ExprKind::Literal {
847                     literal: self.tcx.mk_const(ty::Const {
848                         val,
849                         ty: self.typeck_results().node_type(expr.hir_id),
850                     }),
851                     user_ty: None,
852                     const_id: Some(def_id),
853                 }
854             }
855
856             Res::Def(DefKind::Const, def_id) | Res::Def(DefKind::AssocConst, def_id) => {
857                 let user_ty = self.user_substs_applied_to_res(expr.hir_id, res);
858                 debug!("convert_path_expr: (const) user_ty={:?}", user_ty);
859                 ExprKind::Literal {
860                     literal: self.tcx.mk_const(ty::Const {
861                         val: ty::ConstKind::Unevaluated(
862                             ty::WithOptConstParam::unknown(def_id),
863                             substs,
864                             None,
865                         ),
866                         ty: self.typeck_results().node_type(expr.hir_id),
867                     }),
868                     user_ty,
869                     const_id: Some(def_id),
870                 }
871             }
872
873             Res::Def(DefKind::Ctor(_, CtorKind::Const), def_id) => {
874                 let user_provided_types = self.typeck_results.user_provided_types();
875                 let user_provided_type = user_provided_types.get(expr.hir_id).copied();
876                 debug!("convert_path_expr: user_provided_type={:?}", user_provided_type);
877                 let ty = self.typeck_results().node_type(expr.hir_id);
878                 match ty.kind() {
879                     // A unit struct/variant which is used as a value.
880                     // We return a completely different ExprKind here to account for this special case.
881                     ty::Adt(adt_def, substs) => ExprKind::Adt {
882                         adt_def,
883                         variant_index: adt_def.variant_index_with_ctor_id(def_id),
884                         substs,
885                         user_ty: user_provided_type,
886                         fields: vec![],
887                         base: None,
888                     },
889                     _ => bug!("unexpected ty: {:?}", ty),
890                 }
891             }
892
893             // We encode uses of statics as a `*&STATIC` where the `&STATIC` part is
894             // a constant reference (or constant raw pointer for `static mut`) in MIR
895             Res::Def(DefKind::Static, id) => {
896                 let ty = self.tcx.static_ptr_ty(id);
897                 let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id);
898                 let kind = if self.tcx.is_thread_local_static(id) {
899                     ExprKind::ThreadLocalRef(id)
900                 } else {
901                     let ptr = self.tcx.create_static_alloc(id);
902                     ExprKind::StaticRef {
903                         literal: ty::Const::from_scalar(self.tcx, Scalar::Ptr(ptr.into()), ty),
904                         def_id: id,
905                     }
906                 };
907                 ExprKind::Deref { arg: Box::new(Expr { ty, temp_lifetime, span: expr.span, kind }) }
908             }
909
910             Res::Local(var_hir_id) => self.convert_var(var_hir_id),
911
912             _ => span_bug!(expr.span, "res `{:?}` not yet implemented", res),
913         }
914     }
915
916     fn convert_var(&mut self, var_hir_id: hir::HirId) -> ExprKind<'tcx> {
917         // We want upvars here not captures.
918         // Captures will be handled in MIR.
919         let is_upvar = self
920             .tcx
921             .upvars_mentioned(self.body_owner)
922             .map_or(false, |upvars| upvars.contains_key(&var_hir_id));
923
924         debug!(
925             "convert_var({:?}): is_upvar={}, body_owner={:?}",
926             var_hir_id, is_upvar, self.body_owner
927         );
928
929         if is_upvar {
930             ExprKind::UpvarRef { closure_def_id: self.body_owner, var_hir_id }
931         } else {
932             ExprKind::VarRef { id: var_hir_id }
933         }
934     }
935
936     fn overloaded_operator(
937         &mut self,
938         expr: &'tcx hir::Expr<'tcx>,
939         args: Vec<Expr<'tcx>>,
940     ) -> ExprKind<'tcx> {
941         let fun = Box::new(self.method_callee(expr, expr.span, None));
942         ExprKind::Call { ty: fun.ty, fun, args, from_hir_call: false, fn_span: expr.span }
943     }
944
945     fn overloaded_place(
946         &mut self,
947         expr: &'tcx hir::Expr<'tcx>,
948         place_ty: Ty<'tcx>,
949         overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>,
950         args: Vec<Expr<'tcx>>,
951         span: Span,
952     ) -> ExprKind<'tcx> {
953         // For an overloaded *x or x[y] expression of type T, the method
954         // call returns an &T and we must add the deref so that the types
955         // line up (this is because `*x` and `x[y]` represent places):
956
957         // Reconstruct the output assuming it's a reference with the
958         // same region and mutability as the receiver. This holds for
959         // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
960         let (region, mutbl) = match *args[0].ty.kind() {
961             ty::Ref(region, _, mutbl) => (region, mutbl),
962             _ => span_bug!(span, "overloaded_place: receiver is not a reference"),
963         };
964         let ref_ty = self.tcx.mk_ref(region, ty::TypeAndMut { ty: place_ty, mutbl });
965
966         // construct the complete expression `foo()` for the overloaded call,
967         // which will yield the &T type
968         let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id);
969         let fun = Box::new(self.method_callee(expr, span, overloaded_callee));
970         let ref_expr = Box::new(Expr {
971             temp_lifetime,
972             ty: ref_ty,
973             span,
974             kind: ExprKind::Call { ty: fun.ty, fun, args, from_hir_call: false, fn_span: span },
975         });
976
977         // construct and return a deref wrapper `*foo()`
978         ExprKind::Deref { arg: ref_expr }
979     }
980
981     fn capture_upvar(
982         &mut self,
983         closure_expr: &'tcx hir::Expr<'tcx>,
984         captured_place: &'tcx ty::CapturedPlace<'tcx>,
985         upvar_ty: Ty<'tcx>,
986     ) -> Expr<'tcx> {
987         let upvar_capture = captured_place.info.capture_kind;
988         let temp_lifetime = self.region_scope_tree.temporary_scope(closure_expr.hir_id.local_id);
989         let var_ty = captured_place.place.base_ty;
990
991         // The result of capture analysis in `rustc_typeck/check/upvar.rs`represents a captured path
992         // as it's seen for use within the closure and not at the time of closure creation.
993         //
994         // That is we see expect to see it start from a captured upvar and not something that is local
995         // to the closure's parent.
996         let var_hir_id = match captured_place.place.base {
997             HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
998             base => bug!("Expected an upvar, found {:?}", base),
999         };
1000
1001         let mut captured_place_expr = Expr {
1002             temp_lifetime,
1003             ty: var_ty,
1004             span: closure_expr.span,
1005             kind: self.convert_var(var_hir_id),
1006         };
1007
1008         for proj in captured_place.place.projections.iter() {
1009             let kind = match proj.kind {
1010                 HirProjectionKind::Deref => ExprKind::Deref { arg: Box::new(captured_place_expr) },
1011                 HirProjectionKind::Field(field, ..) => {
1012                     // Variant index will always be 0, because for multi-variant
1013                     // enums, we capture the enum entirely.
1014                     ExprKind::Field {
1015                         lhs: Box::new(captured_place_expr),
1016                         name: Field::new(field as usize),
1017                     }
1018                 }
1019                 HirProjectionKind::Index | HirProjectionKind::Subslice => {
1020                     // We don't capture these projections, so we can ignore them here
1021                     continue;
1022                 }
1023             };
1024
1025             captured_place_expr =
1026                 Expr { temp_lifetime, ty: proj.ty, span: closure_expr.span, kind };
1027         }
1028
1029         match upvar_capture {
1030             ty::UpvarCapture::ByValue(_) => captured_place_expr,
1031             ty::UpvarCapture::ByRef(upvar_borrow) => {
1032                 let borrow_kind = match upvar_borrow.kind {
1033                     ty::BorrowKind::ImmBorrow => BorrowKind::Shared,
1034                     ty::BorrowKind::UniqueImmBorrow => BorrowKind::Unique,
1035                     ty::BorrowKind::MutBorrow => BorrowKind::Mut { allow_two_phase_borrow: false },
1036                 };
1037                 Expr {
1038                     temp_lifetime,
1039                     ty: upvar_ty,
1040                     span: closure_expr.span,
1041                     kind: ExprKind::Borrow { borrow_kind, arg: Box::new(captured_place_expr) },
1042                 }
1043             }
1044         }
1045     }
1046
1047     /// Converts a list of named fields (i.e., for struct-like struct/enum ADTs) into FieldExpr.
1048     fn field_refs(&mut self, fields: &'tcx [hir::Field<'tcx>]) -> Vec<FieldExpr<'tcx>> {
1049         fields
1050             .iter()
1051             .map(|field| FieldExpr {
1052                 name: Field::new(self.tcx.field_index(field.hir_id, self.typeck_results)),
1053                 expr: self.mirror_expr(field.expr),
1054             })
1055             .collect()
1056     }
1057 }
1058
1059 trait ToBorrowKind {
1060     fn to_borrow_kind(&self) -> BorrowKind;
1061 }
1062
1063 impl ToBorrowKind for AutoBorrowMutability {
1064     fn to_borrow_kind(&self) -> BorrowKind {
1065         use rustc_middle::ty::adjustment::AllowTwoPhase;
1066         match *self {
1067             AutoBorrowMutability::Mut { allow_two_phase_borrow } => BorrowKind::Mut {
1068                 allow_two_phase_borrow: match allow_two_phase_borrow {
1069                     AllowTwoPhase::Yes => true,
1070                     AllowTwoPhase::No => false,
1071                 },
1072             },
1073             AutoBorrowMutability::Not => BorrowKind::Shared,
1074         }
1075     }
1076 }
1077
1078 impl ToBorrowKind for hir::Mutability {
1079     fn to_borrow_kind(&self) -> BorrowKind {
1080         match *self {
1081             hir::Mutability::Mut => BorrowKind::Mut { allow_two_phase_borrow: false },
1082             hir::Mutability::Not => BorrowKind::Shared,
1083         }
1084     }
1085 }
1086
1087 fn bin_op(op: hir::BinOpKind) -> BinOp {
1088     match op {
1089         hir::BinOpKind::Add => BinOp::Add,
1090         hir::BinOpKind::Sub => BinOp::Sub,
1091         hir::BinOpKind::Mul => BinOp::Mul,
1092         hir::BinOpKind::Div => BinOp::Div,
1093         hir::BinOpKind::Rem => BinOp::Rem,
1094         hir::BinOpKind::BitXor => BinOp::BitXor,
1095         hir::BinOpKind::BitAnd => BinOp::BitAnd,
1096         hir::BinOpKind::BitOr => BinOp::BitOr,
1097         hir::BinOpKind::Shl => BinOp::Shl,
1098         hir::BinOpKind::Shr => BinOp::Shr,
1099         hir::BinOpKind::Eq => BinOp::Eq,
1100         hir::BinOpKind::Lt => BinOp::Lt,
1101         hir::BinOpKind::Le => BinOp::Le,
1102         hir::BinOpKind::Ne => BinOp::Ne,
1103         hir::BinOpKind::Ge => BinOp::Ge,
1104         hir::BinOpKind::Gt => BinOp::Gt,
1105         _ => bug!("no equivalent for ast binop {:?}", op),
1106     }
1107 }