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
,'tcx
> Builder
<'a
,'tcx
> {
19 /// Compile `expr`, yielding an lvalue that we can move from etc.
20 pub fn as_lvalue
<M
>(&mut self,
23 -> BlockAnd
<Lvalue
<'tcx
>>
24 where M
: Mirror
<'tcx
, Output
=Expr
<'tcx
>>
26 let expr
= self.hir
.mirror(expr
);
27 self.expr_as_lvalue(block
, expr
)
30 fn expr_as_lvalue(&mut self,
31 mut block
: BasicBlock
,
33 -> BlockAnd
<Lvalue
<'tcx
>> {
34 debug
!("expr_as_lvalue(block={:?}, expr={:?})", block
, expr
);
37 let scope_id
= this
.innermost_scope_id();
38 let expr_span
= expr
.span
;
40 ExprKind
::Scope { extent, value }
=> {
41 this
.in_scope(extent
, block
, |this
, _
| this
.as_lvalue(block
, value
))
43 ExprKind
::Field { lhs, name }
=> {
44 let lvalue
= unpack
!(block
= this
.as_lvalue(block
, lhs
));
45 let lvalue
= lvalue
.field(name
, expr
.ty
);
48 ExprKind
::Deref { arg }
=> {
49 let lvalue
= unpack
!(block
= this
.as_lvalue(block
, arg
));
50 let lvalue
= lvalue
.deref();
53 ExprKind
::Index { lhs, index }
=> {
54 let (usize_ty
, bool_ty
) = (this
.hir
.usize_ty(), this
.hir
.bool_ty());
56 let slice
= unpack
!(block
= this
.as_lvalue(block
, lhs
));
58 let idx
= unpack
!(block
= this
.as_operand(block
, index
));
61 let (len
, lt
) = (this
.temp(usize_ty
.clone()), this
.temp(bool_ty
));
62 this
.cfg
.push_assign(block
, scope_id
, expr_span
, // len = len(slice)
63 &len
, Rvalue
::Len(slice
.clone()));
64 this
.cfg
.push_assign(block
, scope_id
, expr_span
, // lt = idx < len
65 <
, Rvalue
::BinaryOp(BinOp
::Lt
,
67 Operand
::Consume(len
.clone())));
69 let (success
, failure
) = (this
.cfg
.start_new_block(), this
.cfg
.start_new_block());
70 this
.cfg
.terminate(block
,
74 cond
: Operand
::Consume(lt
),
75 targets
: (success
, failure
),
77 this
.panic_bounds_check(failure
, idx
.clone(), Operand
::Consume(len
), expr_span
);
78 success
.and(slice
.index(idx
))
80 ExprKind
::SelfRef
=> {
81 block
.and(Lvalue
::Arg(0))
83 ExprKind
::VarRef { id }
=> {
84 let index
= this
.var_indices
[&id
];
85 block
.and(Lvalue
::Var(index
))
87 ExprKind
::StaticRef { id }
=> {
88 block
.and(Lvalue
::Static(id
))
91 ExprKind
::Vec { .. }
|
92 ExprKind
::Tuple { .. }
|
93 ExprKind
::Adt { .. }
|
94 ExprKind
::Closure { .. }
|
95 ExprKind
::Unary { .. }
|
96 ExprKind
::Binary { .. }
|
97 ExprKind
::LogicalOp { .. }
|
98 ExprKind
::Box { .. }
|
99 ExprKind
::Cast { .. }
|
100 ExprKind
::ReifyFnPointer { .. }
|
101 ExprKind
::UnsafeFnPointer { .. }
|
102 ExprKind
::Unsize { .. }
|
103 ExprKind
::Repeat { .. }
|
104 ExprKind
::Borrow { .. }
|
105 ExprKind
::If { .. }
|
106 ExprKind
::Match { .. }
|
107 ExprKind
::Loop { .. }
|
108 ExprKind
::Block { .. }
|
109 ExprKind
::Assign { .. }
|
110 ExprKind
::AssignOp { .. }
|
111 ExprKind
::Break { .. }
|
112 ExprKind
::Continue { .. }
|
113 ExprKind
::Return { .. }
|
114 ExprKind
::Literal { .. }
|
115 ExprKind
::InlineAsm { .. }
|
116 ExprKind
::Call { .. }
=> {
117 // these are not lvalues, so we need to make a temporary.
118 debug_assert
!(match Category
::of(&expr
.kind
) {
119 Some(Category
::Lvalue
) => false,
122 this
.as_temp(block
, expr
)