diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index bc562b39c98..1b23841c913 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -788,7 +788,7 @@ pub fn trans_call_inner<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, llself.is_some(), abi); - fcx.pop_custom_cleanup_scope(arg_cleanup_scope); + fcx.scopes.borrow_mut().last_mut().unwrap().drop_non_lifetime_clean(); // Invoke the actual rust fn and update bcx/llresult. let (llret, b) = base::invoke(bcx, @@ -829,12 +829,15 @@ pub fn trans_call_inner<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, cleanup::CustomScope(arg_cleanup_scope), false, abi); - fcx.pop_custom_cleanup_scope(arg_cleanup_scope); + fcx.scopes.borrow_mut().last_mut().unwrap().drop_non_lifetime_clean(); + bcx = foreign::trans_native_call(bcx, callee_ty, llfn, opt_llretslot.unwrap(), llargs.as_slice(), arg_tys); } + fcx.pop_and_trans_custom_cleanup_scope(bcx, arg_cleanup_scope); + // If the caller doesn't care about the result of this fn call, // drop the temporary slot we made. match (dest, opt_llretslot) { diff --git a/src/librustc/middle/trans/cleanup.rs b/src/librustc/middle/trans/cleanup.rs index 392436d3a80..f3844a956fa 100644 --- a/src/librustc/middle/trans/cleanup.rs +++ b/src/librustc/middle/trans/cleanup.rs @@ -74,6 +74,7 @@ pub struct CachedEarlyExit { pub trait Cleanup { fn must_unwind(&self) -> bool; fn clean_on_unwind(&self) -> bool; + fn is_lifetime_end(&self) -> bool; fn trans<'blk, 'tcx>(&self, bcx: Block<'blk, 'tcx>, debug_loc: Option) @@ -875,6 +876,10 @@ impl<'blk, 'tcx> CleanupScope<'blk, 'tcx> { LoopScopeKind(id, _) => format!("{}_loop_{}_", prefix, id), } } + + pub fn drop_non_lifetime_clean(&mut self) { + self.cleanups.retain(|c| c.is_lifetime_end()); + } } impl<'blk, 'tcx> CleanupScopeKind<'blk, 'tcx> { @@ -943,6 +948,10 @@ impl Cleanup for DropValue { self.must_unwind } + fn is_lifetime_end(&self) -> bool { + false + } + fn trans<'blk, 'tcx>(&self, bcx: Block<'blk, 'tcx>, debug_loc: Option) @@ -978,6 +987,10 @@ impl Cleanup for FreeValue { true } + fn is_lifetime_end(&self) -> bool { + false + } + fn trans<'blk, 'tcx>(&self, bcx: Block<'blk, 'tcx>, debug_loc: Option) @@ -1008,6 +1021,10 @@ impl Cleanup for FreeSlice { true } + fn is_lifetime_end(&self) -> bool { + false + } + fn trans<'blk, 'tcx>(&self, bcx: Block<'blk, 'tcx>, debug_loc: Option) @@ -1035,6 +1052,10 @@ impl Cleanup for LifetimeEnd { true } + fn is_lifetime_end(&self) -> bool { + true + } + fn trans<'blk, 'tcx>(&self, bcx: Block<'blk, 'tcx>, debug_loc: Option)