]> git.proxmox.com Git - rustc.git/blame - src/librustc_mir/build/expr/as_temp.rs
Imported Upstream version 1.9.0+dfsg1
[rustc.git] / src / librustc_mir / build / expr / as_temp.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
11//! See docs in build/expr/mod.rs
12
92a42be0 13use build::{BlockAnd, BlockAndExtension, Builder};
e9174d1e
SL
14use build::expr::category::Category;
15use hair::*;
92a42be0 16use rustc::mir::repr::*;
e9174d1e 17
b039eaaf 18impl<'a,'tcx> Builder<'a,'tcx> {
e9174d1e
SL
19 /// Compile `expr` into a fresh temporary. This is used when building
20 /// up rvalues so as to freeze the value that will be consumed.
b039eaaf
SL
21 pub fn as_temp<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Lvalue<'tcx>>
22 where M: Mirror<'tcx, Output = Expr<'tcx>>
e9174d1e
SL
23 {
24 let expr = self.hir.mirror(expr);
25 self.expr_as_temp(block, expr)
26 }
27
b039eaaf
SL
28 fn expr_as_temp(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd<Lvalue<'tcx>> {
29 debug!("expr_as_temp(block={:?}, expr={:?})", block, expr);
e9174d1e
SL
30 let this = self;
31
b039eaaf 32 if let ExprKind::Scope { extent, value } = expr.kind {
54a0048b 33 return this.in_scope(extent, block, |this, _| this.as_temp(block, value));
e9174d1e
SL
34 }
35
36 let expr_ty = expr.ty.clone();
37 let temp = this.temp(expr_ty.clone());
38 let temp_lifetime = match expr.temp_lifetime {
39 Some(t) => t,
40 None => {
54a0048b 41 span_bug!(expr.span, "no temp_lifetime for expr");
e9174d1e
SL
42 }
43 };
7453a54e 44 this.schedule_drop(expr.span, temp_lifetime, &temp, expr_ty);
e9174d1e
SL
45
46 // Careful here not to cause an infinite cycle. If we always
47 // called `into`, then for lvalues like `x.f`, it would
48 // eventually fallback to us, and we'd loop. There's a reason
49 // for this: `as_temp` is the point where we bridge the "by
50 // reference" semantics of `as_lvalue` with the "by value"
51 // semantics of `into`, `as_operand`, `as_rvalue`, and (of
52 // course) `as_temp`.
53 match Category::of(&expr.kind).unwrap() {
54 Category::Lvalue => {
55 let expr_span = expr.span;
56 let lvalue = unpack!(block = this.as_lvalue(block, expr));
57 let rvalue = Rvalue::Use(Operand::Consume(lvalue));
54a0048b
SL
58 let scope_id = this.innermost_scope_id();
59 this.cfg.push_assign(block, scope_id, expr_span, &temp, rvalue);
e9174d1e
SL
60 }
61 _ => {
62 unpack!(block = this.into(&temp, block, expr));
63 }
64 }
65
66 block.and(temp)
67 }
68}