Schedule storage-dead of temporaries sooner
This ensures that we will correctly generate a storage-dead if the initializing expression diverges.
This commit is contained in:
parent
b5643f1a49
commit
abab9efbdb
4 changed files with 32 additions and 17 deletions
|
|
@ -1,6 +1,7 @@
|
|||
//! See docs in build/expr/mod.rs
|
||||
|
||||
use crate::build::{BlockAnd, BlockAndExtension, Builder};
|
||||
use crate::build::scope::{CachedBlock, DropKind};
|
||||
use crate::hair::*;
|
||||
use rustc::middle::region;
|
||||
use rustc::mir::*;
|
||||
|
|
@ -63,6 +64,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
this.local_decls.push(local_decl)
|
||||
};
|
||||
let temp_place = &Place::Base(PlaceBase::Local(temp));
|
||||
|
||||
if !expr_ty.is_never() {
|
||||
this.cfg.push(
|
||||
block,
|
||||
|
|
@ -71,25 +74,38 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
kind: StatementKind::StorageLive(temp),
|
||||
},
|
||||
);
|
||||
|
||||
// In constants, temp_lifetime is None for temporaries that live for the
|
||||
// 'static lifetime. Thus we do not drop these temporaries and simply leak them.
|
||||
// This is equivalent to what `let x = &foo();` does in functions. The temporary
|
||||
// is lifted to their surrounding scope. In a function that means the temporary lives
|
||||
// until just before the function returns. In constants that means it outlives the
|
||||
// constant's initialization value computation. Anything outliving a constant
|
||||
// must have the `'static` lifetime and live forever.
|
||||
// Anything with a shorter lifetime (e.g the `&foo()` in `bar(&foo())` or anything
|
||||
// within a block will keep the regular drops just like runtime code.
|
||||
if let Some(temp_lifetime) = temp_lifetime {
|
||||
this.schedule_drop(
|
||||
expr_span,
|
||||
temp_lifetime,
|
||||
temp_place,
|
||||
expr_ty,
|
||||
DropKind::Storage,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
unpack!(block = this.into(&Place::Base(PlaceBase::Local(temp)), block, expr));
|
||||
unpack!(block = this.into(temp_place, block, expr));
|
||||
|
||||
// In constants, temp_lifetime is None for temporaries that live for the
|
||||
// 'static lifetime. Thus we do not drop these temporaries and simply leak them.
|
||||
// This is equivalent to what `let x = &foo();` does in functions. The temporary
|
||||
// is lifted to their surrounding scope. In a function that means the temporary lives
|
||||
// until just before the function returns. In constants that means it outlives the
|
||||
// constant's initialization value computation. Anything outliving a constant
|
||||
// must have the `'static` lifetime and live forever.
|
||||
// Anything with a shorter lifetime (e.g the `&foo()` in `bar(&foo())` or anything
|
||||
// within a block will keep the regular drops just like runtime code.
|
||||
if let Some(temp_lifetime) = temp_lifetime {
|
||||
this.schedule_drop_storage_and_value(
|
||||
this.schedule_drop(
|
||||
expr_span,
|
||||
temp_lifetime,
|
||||
&Place::Base(PlaceBase::Local(temp)),
|
||||
temp_place,
|
||||
expr_ty,
|
||||
DropKind::Value {
|
||||
cached_block: CachedBlock::default(),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -86,7 +86,6 @@ fn main() {
|
|||
// unreachable;
|
||||
// }
|
||||
// bb17: {
|
||||
// StorageDead(_4);
|
||||
// goto -> bb18;
|
||||
// }
|
||||
// bb18: {
|
||||
|
|
|
|||
|
|
@ -109,8 +109,8 @@ fn main() {
|
|||
// goto -> bb13;
|
||||
// }
|
||||
// bb13: {
|
||||
// StorageDead(_1);
|
||||
// StorageDead(_2);
|
||||
// StorageDead(_1);
|
||||
// _0 = ();
|
||||
// return;
|
||||
// }
|
||||
|
|
@ -186,8 +186,8 @@ fn main() {
|
|||
// goto -> bb13;
|
||||
// }
|
||||
// bb13: {
|
||||
// StorageDead(_1);
|
||||
// StorageDead(_2);
|
||||
// StorageDead(_1);
|
||||
// _0 = ();
|
||||
// return;
|
||||
// }
|
||||
|
|
@ -289,8 +289,8 @@ fn main() {
|
|||
// goto -> bb17;
|
||||
// }
|
||||
// bb17: {
|
||||
// StorageDead(_1);
|
||||
// StorageDead(_2);
|
||||
// StorageDead(_1);
|
||||
// _0 = ();
|
||||
// return;
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -182,8 +182,8 @@ fn main() {
|
|||
// _2 = Foo { tup: const "hi", data: move _3 };
|
||||
// _1 = &_2;
|
||||
// _0 = &(*_1);
|
||||
// StorageDead(_1);
|
||||
// StorageDead(_5);
|
||||
// StorageDead(_1);
|
||||
// return;
|
||||
// }
|
||||
//}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue