From abab9efbdb82b76f418115462311f8852600c9a2 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Wed, 3 Apr 2019 21:13:51 +0100 Subject: [PATCH] Schedule storage-dead of temporaries sooner This ensures that we will correctly generate a storage-dead if the initializing expression diverges. --- src/librustc_mir/build/expr/as_temp.rs | 40 +++++++++++++------ src/test/mir-opt/issue-49232.rs | 1 - src/test/mir-opt/match_false_edges.rs | 6 +-- .../mir-opt/storage_live_dead_in_statics.rs | 2 +- 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index c60e19701006..ac70bf30e457 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -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(), + }, ); } diff --git a/src/test/mir-opt/issue-49232.rs b/src/test/mir-opt/issue-49232.rs index 3910183dee78..bf22f00b5055 100644 --- a/src/test/mir-opt/issue-49232.rs +++ b/src/test/mir-opt/issue-49232.rs @@ -86,7 +86,6 @@ fn main() { // unreachable; // } // bb17: { -// StorageDead(_4); // goto -> bb18; // } // bb18: { diff --git a/src/test/mir-opt/match_false_edges.rs b/src/test/mir-opt/match_false_edges.rs index 0850c552536c..6979924c8cd9 100644 --- a/src/test/mir-opt/match_false_edges.rs +++ b/src/test/mir-opt/match_false_edges.rs @@ -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; // } diff --git a/src/test/mir-opt/storage_live_dead_in_statics.rs b/src/test/mir-opt/storage_live_dead_in_statics.rs index 10f00cf8b0c3..2ed34ecfad2c 100644 --- a/src/test/mir-opt/storage_live_dead_in_statics.rs +++ b/src/test/mir-opt/storage_live_dead_in_statics.rs @@ -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; // } //}