1 //! See docs in build/expr/mod.rs
3 use crate::build::{BlockAnd, BlockAndExtension, Builder};
4 use crate::build::scope::{CachedBlock, DropKind};
6 use rustc::middle::region;
9 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
10 /// Compile `expr` into a fresh temporary. This is used when building
11 /// up rvalues so as to freeze the value that will be consumed.
15 temp_lifetime: Option<region::Scope>,
17 mutability: Mutability,
20 M: Mirror<'tcx, Output = Expr<'tcx>>,
22 let expr = self.hir.mirror(expr);
23 self.expr_as_temp(block, temp_lifetime, expr, mutability)
28 mut block: BasicBlock,
29 temp_lifetime: Option<region::Scope>,
31 mutability: Mutability,
32 ) -> BlockAnd<Local> {
34 "expr_as_temp(block={:?}, temp_lifetime={:?}, expr={:?}, mutability={:?})",
35 block, temp_lifetime, expr, mutability
39 let expr_span = expr.span;
40 let source_info = this.source_info(expr_span);
41 if let ExprKind::Scope {
47 return this.in_scope((region_scope, source_info), lint_level, |this| {
48 this.as_temp(block, temp_lifetime, value, mutability)
52 let expr_ty = expr.ty;
54 let mut local_decl = LocalDecl::new_temp(expr_ty, expr_span);
55 if mutability == Mutability::Not {
56 local_decl = local_decl.immutable();
59 debug!("creating temp {:?} with block_context: {:?}", local_decl, this.block_context);
60 // Find out whether this temp is being created within the
61 // tail expression of a block whose result is ignored.
62 if let Some(tail_info) = this.block_context.currently_in_block_tail() {
63 local_decl = local_decl.block_tail(tail_info);
65 this.local_decls.push(local_decl)
67 let temp_place = &Place::Base(PlaceBase::Local(temp));
69 if !expr_ty.is_never() {
74 kind: StatementKind::StorageLive(temp),
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.
87 if let Some(temp_lifetime) = temp_lifetime {
98 unpack!(block = this.into(temp_place, block, expr));
100 if let Some(temp_lifetime) = temp_lifetime {
107 cached_block: CachedBlock::default(),