]> git.proxmox.com Git - rustc.git/blame - src/librustc_mir/build/expr/as_temp.rs
New upstream version 1.34.2+dfsg1
[rustc.git] / src / librustc_mir / build / expr / as_temp.rs
CommitLineData
e9174d1e
SL
1//! See docs in build/expr/mod.rs
2
9fa01778
XL
3use crate::build::{BlockAnd, BlockAndExtension, Builder};
4use crate::hair::*;
ea8adc8c 5use rustc::middle::region;
c30ab7b3 6use rustc::mir::*;
e9174d1e 7
a7813a04 8impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
e9174d1e
SL
9 /// Compile `expr` into a fresh temporary. This is used when building
10 /// up rvalues so as to freeze the value that will be consumed.
b7449926
XL
11 pub fn as_temp<M>(
12 &mut self,
13 block: BasicBlock,
14 temp_lifetime: Option<region::Scope>,
15 expr: M,
16 mutability: Mutability,
17 ) -> BlockAnd<Local>
18 where
19 M: Mirror<'tcx, Output = Expr<'tcx>>,
e9174d1e
SL
20 {
21 let expr = self.hir.mirror(expr);
b7449926 22 self.expr_as_temp(block, temp_lifetime, expr, mutability)
e9174d1e
SL
23 }
24
b7449926
XL
25 fn expr_as_temp(
26 &mut self,
27 mut block: BasicBlock,
28 temp_lifetime: Option<region::Scope>,
29 expr: Expr<'tcx>,
30 mutability: Mutability,
31 ) -> BlockAnd<Local> {
32 debug!(
33 "expr_as_temp(block={:?}, temp_lifetime={:?}, expr={:?}, mutability={:?})",
34 block, temp_lifetime, expr, mutability
35 );
e9174d1e
SL
36 let this = self;
37
041b39d2
XL
38 let expr_span = expr.span;
39 let source_info = this.source_info(expr_span);
b7449926
XL
40 if let ExprKind::Scope {
41 region_scope,
42 lint_level,
43 value,
44 } = expr.kind
45 {
ea8adc8c 46 return this.in_scope((region_scope, source_info), lint_level, block, |this| {
b7449926 47 this.as_temp(block, temp_lifetime, value, mutability)
cc61c64b 48 });
e9174d1e
SL
49 }
50
ea8adc8c 51 let expr_ty = expr.ty;
0bf4aa26
XL
52 let temp = {
53 let mut local_decl = LocalDecl::new_temp(expr_ty, expr_span);
54 if mutability == Mutability::Not {
55 local_decl = local_decl.immutable();
56 }
57
58 debug!("creating temp {:?} with block_context: {:?}", local_decl, this.block_context);
59 // Find out whether this temp is being created within the
60 // tail expression of a block whose result is ignored.
a1dfa0c6
XL
61 if let Some(tail_info) = this.block_context.currently_in_block_tail() {
62 local_decl = local_decl.block_tail(tail_info);
0bf4aa26 63 }
0bf4aa26
XL
64 this.local_decls.push(local_decl)
65 };
ea8adc8c 66 if !expr_ty.is_never() {
b7449926
XL
67 this.cfg.push(
68 block,
69 Statement {
70 source_info,
71 kind: StatementKind::StorageLive(temp),
72 },
73 );
5bcae85e 74 }
e9174d1e 75
8faf50e0 76 unpack!(block = this.into(&Place::Local(temp), block, expr));
e9174d1e 77
a1dfa0c6
XL
78 // In constants, temp_lifetime is None for temporaries that live for the
79 // 'static lifetime. Thus we do not drop these temporaries and simply leak them.
80 // This is equivalent to what `let x = &foo();` does in functions. The temporary
81 // is lifted to their surrounding scope. In a function that means the temporary lives
82 // until just before the function returns. In constants that means it outlives the
83 // constant's initialization value computation. Anything outliving a constant
84 // must have the `'static` lifetime and live forever.
85 // Anything with a shorter lifetime (e.g the `&foo()` in `bar(&foo())` or anything
86 // within a block will keep the regular drops just like runtime code.
a7813a04 87 if let Some(temp_lifetime) = temp_lifetime {
8faf50e0 88 this.schedule_drop_storage_and_value(
b7449926
XL
89 expr_span,
90 temp_lifetime,
91 &Place::Local(temp),
92 expr_ty,
8faf50e0 93 );
a7813a04
XL
94 }
95
e9174d1e
SL
96 block.and(temp)
97 }
98}