about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/middle/trans/callee.rs7
-rw-r--r--src/librustc/middle/trans/cleanup.rs21
2 files changed, 26 insertions, 2 deletions
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<NodeInfo>)
@@ -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<NodeInfo>)
@@ -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<NodeInfo>)
@@ -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<NodeInfo>)
@@ -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<NodeInfo>)