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.
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.
11 //! See docs in build/expr/mod.rs
13 use build
::{BlockAnd, BlockAndExtension, Builder}
;
14 use build
::expr
::category
::Category
;
16 use rustc
::mir
::repr
::*;
18 impl<'a
, 'gcx
, 'tcx
> Builder
<'a
, 'gcx
, 'tcx
> {
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.
21 pub fn as_temp
<M
>(&mut self, block
: BasicBlock
, expr
: M
) -> BlockAnd
<Lvalue
<'tcx
>>
22 where M
: Mirror
<'tcx
, Output
= Expr
<'tcx
>>
24 let expr
= self.hir
.mirror(expr
);
25 self.expr_as_temp(block
, expr
)
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
);
32 if let ExprKind
::Scope { extent, value }
= expr
.kind
{
33 return this
.in_scope(extent
, block
, |this
| this
.as_temp(block
, value
));
36 let expr_ty
= expr
.ty
.clone();
37 let temp
= this
.temp(expr_ty
.clone());
38 let temp_lifetime
= expr
.temp_lifetime
;
39 let expr_span
= expr
.span
;
40 let source_info
= this
.source_info(expr_span
);
42 if temp_lifetime
.is_some() {
43 this
.cfg
.push(block
, Statement
{
44 source_info
: source_info
,
45 kind
: StatementKind
::StorageLive(temp
.clone())
49 // Careful here not to cause an infinite cycle. If we always
50 // called `into`, then for lvalues like `x.f`, it would
51 // eventually fallback to us, and we'd loop. There's a reason
52 // for this: `as_temp` is the point where we bridge the "by
53 // reference" semantics of `as_lvalue` with the "by value"
54 // semantics of `into`, `as_operand`, `as_rvalue`, and (of
56 match Category
::of(&expr
.kind
).unwrap() {
58 let lvalue
= unpack
!(block
= this
.as_lvalue(block
, expr
));
59 let rvalue
= Rvalue
::Use(Operand
::Consume(lvalue
));
60 this
.cfg
.push_assign(block
, source_info
, &temp
, rvalue
);
63 unpack
!(block
= this
.into(&temp
, block
, expr
));
67 // In constants, temp_lifetime is None. We should not need to drop
68 // anything because no values with a destructor can be created in
69 // a constant at this time, even if the type may need dropping.
70 if let Some(temp_lifetime
) = temp_lifetime
{
71 this
.schedule_drop(expr_span
, temp_lifetime
, &temp
, expr_ty
);