]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/build/expr/as_operand.rs
Rollup merge of #41957 - llogiq:clippy-libsyntax, r=petrochenkov
[rust.git] / src / librustc_mir / build / expr / as_operand.rs
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
13 use build::{BlockAnd, BlockAndExtension, Builder};
14 use build::expr::category::Category;
15 use hair::*;
16 use rustc::middle::region::CodeExtent;
17 use rustc::mir::*;
18
19 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
20     /// Returns an operand suitable for use until the end of the current
21     /// scope expression.
22     ///
23     /// The operand returned from this function will *not be valid* after
24     /// an ExprKind::Scope is passed, so please do *not* return it from
25     /// functions to avoid bad miscompiles.
26     pub fn as_local_operand<M>(&mut self, block: BasicBlock, expr: M)
27                              -> BlockAnd<Operand<'tcx>>
28         where M: Mirror<'tcx, Output = Expr<'tcx>>
29     {
30         let topmost_scope = self.topmost_scope(); // FIXME(#6393)
31         self.as_operand(block, Some(topmost_scope), expr)
32     }
33
34     /// Compile `expr` into a value that can be used as an operand.
35     /// If `expr` is an lvalue like `x`, this will introduce a
36     /// temporary `tmp = x`, so that we capture the value of `x` at
37     /// this time.
38     ///
39     /// The operand is known to be live until the end of `scope`.
40     pub fn as_operand<M>(&mut self,
41                          block: BasicBlock,
42                          scope: Option<CodeExtent>,
43                          expr: M) -> BlockAnd<Operand<'tcx>>
44         where M: Mirror<'tcx, Output = Expr<'tcx>>
45     {
46         let expr = self.hir.mirror(expr);
47         self.expr_as_operand(block, scope, expr)
48     }
49
50     fn expr_as_operand(&mut self,
51                        mut block: BasicBlock,
52                        scope: Option<CodeExtent>,
53                        expr: Expr<'tcx>)
54                        -> BlockAnd<Operand<'tcx>> {
55         debug!("expr_as_operand(block={:?}, expr={:?})", block, expr);
56         let this = self;
57
58         if let ExprKind::Scope { extent, value } = expr.kind {
59             return this.in_scope(extent, block, |this| {
60                 this.as_operand(block, scope, value)
61             });
62         }
63
64         let category = Category::of(&expr.kind).unwrap();
65         debug!("expr_as_operand: category={:?} for={:?}", category, expr.kind);
66         match category {
67             Category::Constant => {
68                 let constant = this.as_constant(expr);
69                 block.and(Operand::Constant(box constant))
70             }
71             Category::Lvalue |
72             Category::Rvalue(..) => {
73                 let operand =
74                     unpack!(block = this.as_temp(block, scope, expr));
75                 block.and(Operand::Consume(operand))
76             }
77         }
78     }
79 }