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