]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/build/expr/as_operand.rs
e354a2ee8160b47f1f17c40b8561df9eb14e82e4
[rust.git] / src / librustc_mir / build / expr / as_operand.rs
1 //! See docs in build/expr/mod.rs
2
3 use crate::build::expr::category::Category;
4 use crate::build::{BlockAnd, BlockAndExtension, Builder};
5 use crate::hair::*;
6 use rustc::middle::region;
7 use rustc::mir::*;
8
9 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
10     /// Returns an operand suitable for use until the end of the current
11     /// scope expression.
12     ///
13     /// The operand returned from this function will *not be valid* after
14     /// an ExprKind::Scope is passed, so please do *not* return it from
15     /// functions to avoid bad miscompiles.
16     pub fn as_local_operand<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Operand<'tcx>>
17     where
18         M: Mirror<'tcx, Output = Expr<'tcx>>,
19     {
20         let local_scope = self.local_scope();
21         self.as_operand(block, local_scope, expr)
22     }
23
24     /// Compile `expr` into a value that can be used as an operand.
25     /// If `expr` is a place like `x`, this will introduce a
26     /// temporary `tmp = x`, so that we capture the value of `x` at
27     /// this time.
28     ///
29     /// The operand is known to be live until the end of `scope`.
30     pub fn as_operand<M>(
31         &mut self,
32         block: BasicBlock,
33         scope: Option<region::Scope>,
34         expr: M,
35     ) -> BlockAnd<Operand<'tcx>>
36     where
37         M: Mirror<'tcx, Output = Expr<'tcx>>,
38     {
39         let expr = self.hir.mirror(expr);
40         self.expr_as_operand(block, scope, expr)
41     }
42
43     fn expr_as_operand(
44         &mut self,
45         mut block: BasicBlock,
46         scope: Option<region::Scope>,
47         expr: Expr<'tcx>,
48     ) -> BlockAnd<Operand<'tcx>> {
49         debug!("expr_as_operand(block={:?}, expr={:?})", block, expr);
50         let this = self;
51
52         if let ExprKind::Scope {
53             region_scope,
54             lint_level,
55             value,
56         } = expr.kind
57         {
58             let source_info = this.source_info(expr.span);
59             let region_scope = (region_scope, source_info);
60             return this.in_scope(region_scope, lint_level, block, |this| {
61                 this.as_operand(block, scope, value)
62             });
63         }
64
65         let category = Category::of(&expr.kind).unwrap();
66         debug!(
67             "expr_as_operand: category={:?} for={:?}",
68             category, expr.kind
69         );
70         match category {
71             Category::Constant => {
72                 let constant = this.as_constant(expr);
73                 block.and(Operand::Constant(box constant))
74             }
75             Category::Place | Category::Rvalue(..) => {
76                 let operand = unpack!(block = this.as_temp(block, scope, expr, Mutability::Mut));
77                 block.and(Operand::Move(Place::Base(PlaceBase::Local(operand))))
78             }
79         }
80     }
81 }