1 //! See docs in build/expr/mod.rs
3 use crate::build::{BlockAnd, BlockAndExtension, Builder};
4 use crate::build::scope::DropKind;
7 use rustc::middle::region;
10 impl<'a, 'tcx> Builder<'a, 'tcx> {
11 /// Compile `expr` into a fresh temporary. This is used when building
12 /// up rvalues so as to freeze the value that will be consumed.
16 temp_lifetime: Option<region::Scope>,
18 mutability: Mutability,
21 M: Mirror<'tcx, Output = Expr<'tcx>>,
23 let expr = self.hir.mirror(expr);
24 self.expr_as_temp(block, temp_lifetime, expr, mutability)
29 mut block: BasicBlock,
30 temp_lifetime: Option<region::Scope>,
32 mutability: Mutability,
33 ) -> BlockAnd<Local> {
35 "expr_as_temp(block={:?}, temp_lifetime={:?}, expr={:?}, mutability={:?})",
36 block, temp_lifetime, expr, mutability
40 let expr_span = expr.span;
41 let source_info = this.source_info(expr_span);
42 if let ExprKind::Scope {
48 return this.in_scope((region_scope, source_info), lint_level, |this| {
49 this.as_temp(block, temp_lifetime, value, mutability)
53 let expr_ty = expr.ty;
55 let mut local_decl = LocalDecl::new_temp(expr_ty, expr_span);
56 if mutability == Mutability::Not {
57 local_decl = local_decl.immutable();
60 debug!("creating temp {:?} with block_context: {:?}", local_decl, this.block_context);
61 // Find out whether this temp is being created within the
62 // tail expression of a block whose result is ignored.
63 if let Some(tail_info) = this.block_context.currently_in_block_tail() {
64 local_decl = local_decl.block_tail(tail_info);
66 this.local_decls.push(local_decl)
68 let temp_place = &Place::from(temp);
71 // Don't bother with StorageLive and Dead for these temporaries,
72 // they are never assigned.
73 ExprKind::Break { .. } |
74 ExprKind::Continue { .. } |
75 ExprKind::Return { .. } => (),
77 body: hir::Block { expr: None, targeted_by_break: false, .. }
78 } if expr_ty.is_never() => (),
84 kind: StatementKind::StorageLive(temp),
88 // In constants, `temp_lifetime` is `None` for temporaries that
89 // live for the `'static` lifetime. Thus we do not drop these
90 // temporaries and simply leak them.
91 // This is equivalent to what `let x = &foo();` does in
92 // functions. The temporary is lifted to their surrounding
93 // scope. In a function that means the temporary lives until
94 // just before the function returns. In constants that means it
95 // outlives the constant's initialization value computation.
96 // Anything outliving a constant must have the `'static`
97 // lifetime and live forever.
98 // Anything with a shorter lifetime (e.g the `&foo()` in
99 // `bar(&foo())` or anything within a block will keep the
100 // regular drops just like runtime code.
101 if let Some(temp_lifetime) = temp_lifetime {
112 unpack!(block = this.into(temp_place, block, expr));
114 if let Some(temp_lifetime) = temp_lifetime {