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