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