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
{
113 unpack
!(block
= this
.into(temp_place
, block
, expr
));
115 if let Some(temp_lifetime
) = temp_lifetime
{