about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/middle/trans/base.rs196
-rw-r--r--src/librustc/middle/trans/common.rs90
-rw-r--r--src/librustc/middle/trans/controlflow.rs74
-rw-r--r--src/librustc/middle/trans/write_guard.rs4
4 files changed, 203 insertions, 161 deletions
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index e6384ae4d0d..999fa000f88 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -863,10 +863,10 @@ pub fn need_invoke(bcx: block) -> bool {
 
     // Walk the scopes to look for cleanups
     let mut cur = bcx;
+    let mut cur_scope = cur.scope;
     loop {
-        match cur.kind {
-            block_scope(inf) => {
-                let inf = &mut *inf; // FIXME(#5074) workaround old borrowck
+        cur_scope = match cur_scope {
+            Some(inf) => {
                 for inf.cleanups.iter().advance |cleanup| {
                     match *cleanup {
                         clean(_, cleanup_type) | clean_temp(_, _, cleanup_type) => {
@@ -876,12 +876,15 @@ pub fn need_invoke(bcx: block) -> bool {
                         }
                     }
                 }
+                inf.parent
+            }
+            None => {
+                cur = match cur.parent {
+                    Some(next) => next,
+                    None => return false
+                };
+                cur.scope
             }
-            _ => ()
-        }
-        cur = match cur.parent {
-          Some(next) => next,
-          None => return false
         }
     }
 }
@@ -899,23 +902,21 @@ pub fn have_cached_lpad(bcx: block) -> bool {
 
 pub fn in_lpad_scope_cx(bcx: block, f: &fn(si: &mut scope_info)) {
     let mut bcx = bcx;
+    let mut cur_scope = bcx.scope;
     loop {
-        {
-            match bcx.kind {
-                block_scope(inf) => {
-                    let len = { // FIXME(#5074) workaround old borrowck
-                        let inf = &mut *inf;
-                        inf.cleanups.len()
-                    };
-                    if len > 0u || bcx.parent.is_none() {
-                        f(inf);
-                        return;
-                    }
+        cur_scope = match cur_scope {
+            Some(inf) => {
+                if !inf.empty_cleanups() || (inf.parent.is_none() && bcx.parent.is_none()) {
+                    f(inf);
+                    return;
                 }
-                _ => ()
+                inf.parent
+            }
+            None => {
+                bcx = block_parent(bcx);
+                bcx.scope
             }
         }
-        bcx = block_parent(bcx);
     }
 }
 
@@ -972,27 +973,31 @@ pub fn get_landing_pad(bcx: block) -> BasicBlockRef {
 
 pub fn find_bcx_for_scope(bcx: block, scope_id: ast::node_id) -> block {
     let mut bcx_sid = bcx;
+    let mut cur_scope = bcx_sid.scope;
     loop {
-        bcx_sid = match bcx_sid.node_info {
-            Some(NodeInfo { id, _ }) if id == scope_id => {
-                return bcx_sid
-              }
-
-                // FIXME(#6268, #6248) hacky cleanup for nested method calls
-                Some(NodeInfo { callee_id: Some(id), _ }) if id == scope_id => {
-                    return bcx_sid
-                }
-
-                _ => {
-                    match bcx_sid.parent {
-                        None => bcx.tcx().sess.bug(
-                            fmt!("no enclosing scope with id %d", scope_id)),
-                        Some(bcx_par) => bcx_par
+        cur_scope = match cur_scope {
+            Some(inf) => {
+                match inf.node_info {
+                    Some(NodeInfo { id, _ }) if id == scope_id => {
+                        return bcx_sid
                     }
+                    // FIXME(#6268, #6248) hacky cleanup for nested method calls
+                    Some(NodeInfo { callee_id: Some(id), _ }) if id == scope_id => {
+                        return bcx_sid
+                    }
+                    _ => inf.parent
                 }
             }
+            None => {
+                bcx_sid = match bcx_sid.parent {
+                    None => bcx.tcx().sess.bug(fmt!("no enclosing scope with id %d", scope_id)),
+                    Some(bcx_par) => bcx_par
+                };
+                bcx_sid.scope
+            }
         }
     }
+}
 
 
 pub fn do_spill(bcx: block, v: ValueRef, t: ty::t) -> ValueRef {
@@ -1145,7 +1150,7 @@ pub fn trans_stmt(cx: block, s: &ast::stmt) -> block {
 
 // You probably don't want to use this one. See the
 // next three functions instead.
-pub fn new_block(cx: fn_ctxt, parent: Option<block>, kind: block_kind,
+pub fn new_block(cx: fn_ctxt, parent: Option<block>, scope: Option<@mut scope_info>,
                  is_lpad: bool, name: &str, opt_node_info: Option<NodeInfo>)
     -> block {
 
@@ -1155,10 +1160,10 @@ pub fn new_block(cx: fn_ctxt, parent: Option<block>, kind: block_kind,
         };
         let bcx = mk_block(llbb,
                            parent,
-                           kind,
                            is_lpad,
                            opt_node_info,
                            cx);
+        bcx.scope = scope;
         for parent.iter().advance |cx| {
             if cx.unreachable {
                 Unreachable(bcx);
@@ -1169,27 +1174,30 @@ pub fn new_block(cx: fn_ctxt, parent: Option<block>, kind: block_kind,
     }
 }
 
-pub fn simple_block_scope() -> block_kind {
-    block_scope(@mut scope_info {
+pub fn simple_block_scope(parent: Option<@mut scope_info>,
+                          node_info: Option<NodeInfo>) -> @mut scope_info {
+    @mut scope_info {
+        parent: parent,
         loop_break: None,
         loop_label: None,
         cleanups: ~[],
         cleanup_paths: ~[],
-        landing_pad: None
-    })
+        landing_pad: None,
+        node_info: node_info,
+    }
 }
 
 // Use this when you're at the top block of a function or the like.
 pub fn top_scope_block(fcx: fn_ctxt, opt_node_info: Option<NodeInfo>)
                     -> block {
-    return new_block(fcx, None, simple_block_scope(), false,
+    return new_block(fcx, None, Some(simple_block_scope(None, opt_node_info)), false,
                   "function top level", opt_node_info);
 }
 
 pub fn scope_block(bcx: block,
                    opt_node_info: Option<NodeInfo>,
                    n: &str) -> block {
-    return new_block(bcx.fcx, Some(bcx), simple_block_scope(), bcx.is_lpad,
+    return new_block(bcx.fcx, Some(bcx), Some(simple_block_scope(None, opt_node_info)), bcx.is_lpad,
                   n, opt_node_info);
 }
 
@@ -1198,27 +1206,29 @@ pub fn loop_scope_block(bcx: block,
                         loop_label: Option<ident>,
                         n: &str,
                         opt_node_info: Option<NodeInfo>) -> block {
-    return new_block(bcx.fcx, Some(bcx), block_scope(@mut scope_info {
+    return new_block(bcx.fcx, Some(bcx), Some(@mut scope_info {
+        parent: None,
         loop_break: Some(loop_break),
         loop_label: loop_label,
         cleanups: ~[],
         cleanup_paths: ~[],
-        landing_pad: None
+        landing_pad: None,
+        node_info: opt_node_info,
     }), bcx.is_lpad, n, opt_node_info);
 }
 
 // Use this when creating a block for the inside of a landing pad.
 pub fn lpad_block(bcx: block, n: &str) -> block {
-    new_block(bcx.fcx, Some(bcx), block_non_scope, true, n, None)
+    new_block(bcx.fcx, Some(bcx), None, true, n, None)
 }
 
 // Use this when you're making a general CFG BB within a scope.
 pub fn sub_block(bcx: block, n: &str) -> block {
-    new_block(bcx.fcx, Some(bcx), block_non_scope, bcx.is_lpad, n, None)
+    new_block(bcx.fcx, Some(bcx), None, bcx.is_lpad, n, None)
 }
 
 pub fn raw_block(fcx: fn_ctxt, is_lpad: bool, llbb: BasicBlockRef) -> block {
-    mk_block(llbb, None, block_non_scope, is_lpad, None, fcx)
+    mk_block(llbb, None, is_lpad, None, fcx)
 }
 
 
@@ -1277,42 +1287,47 @@ pub fn cleanup_and_leave(bcx: block,
                 (fmt!("cleanup_and_leave(%s)", cur.to_str())).to_managed());
         }
 
-        match cur.kind {
-            block_scope(inf) if !inf.empty_cleanups() => {
-                let (sub_cx, dest, inf_cleanups) = {
-                    let inf = &mut *inf;
-                    let mut skip = 0;
-                    let mut dest = None;
-                    {
-                        let r = (*inf).cleanup_paths.rev_iter().find_(|cp| cp.target == leave);
-                        for r.iter().advance |cp| {
-                            if cp.size == inf.cleanups.len() {
-                                Br(bcx, cp.dest);
-                                return;
+        let mut cur_scope = cur.scope;
+        loop {
+            cur_scope = match cur_scope {
+                Some (inf) if !inf.empty_cleanups() => {
+                    let (sub_cx, dest, inf_cleanups) = {
+                        let inf = &mut *inf;
+                        let mut skip = 0;
+                        let mut dest = None;
+                        {
+                            let r = (*inf).cleanup_paths.rev_iter().find_(|cp| cp.target == leave);
+                            for r.iter().advance |cp| {
+                                if cp.size == inf.cleanups.len() {
+                                    Br(bcx, cp.dest);
+                                    return;
+                                }
+
+                                skip = cp.size;
+                                dest = Some(cp.dest);
                             }
-
-                            skip = cp.size;
-                            dest = Some(cp.dest);
                         }
+                        let sub_cx = sub_block(bcx, "cleanup");
+                        Br(bcx, sub_cx.llbb);
+                        inf.cleanup_paths.push(cleanup_path {
+                            target: leave,
+                            size: inf.cleanups.len(),
+                            dest: sub_cx.llbb
+                        });
+                        (sub_cx, dest, inf.cleanups.tailn(skip).to_owned())
+                    };
+                    bcx = trans_block_cleanups_(sub_cx,
+                                                inf_cleanups,
+                                                is_lpad);
+                    for dest.iter().advance |&dest| {
+                        Br(bcx, dest);
+                        return;
                     }
-                    let sub_cx = sub_block(bcx, "cleanup");
-                    Br(bcx, sub_cx.llbb);
-                    inf.cleanup_paths.push(cleanup_path {
-                        target: leave,
-                        size: inf.cleanups.len(),
-                        dest: sub_cx.llbb
-                    });
-                    (sub_cx, dest, inf.cleanups.tailn(skip).to_owned())
-                };
-                bcx = trans_block_cleanups_(sub_cx,
-                                            inf_cleanups,
-                                            is_lpad);
-                for dest.iter().advance |&dest| {
-                    Br(bcx, dest);
-                    return;
+                    inf.parent
                 }
+                Some(inf) => inf.parent,
+                None => break
             }
-            _ => ()
         }
 
         match upto {
@@ -1353,9 +1368,12 @@ pub fn with_scope(bcx: block,
            bcx.to_str(), opt_node_info, name);
     let _indenter = indenter();
 
-    let scope_cx = scope_block(bcx, opt_node_info, name);
-    Br(bcx, scope_cx.llbb);
-    leave_block(f(scope_cx), scope_cx)
+    let scope = simple_block_scope(bcx.scope, opt_node_info);
+    bcx.scope = Some(scope);
+    let ret = f(bcx);
+    let ret = trans_block_cleanups_(ret, /*bad*/copy scope.cleanups, false);
+    bcx.scope = scope.parent;
+    ret
 }
 
 pub fn with_scope_result(bcx: block,
@@ -1363,10 +1381,14 @@ pub fn with_scope_result(bcx: block,
                          name: &str,
                          f: &fn(block) -> Result) -> Result {
     let _icx = push_ctxt("with_scope_result");
-    let scope_cx = scope_block(bcx, opt_node_info, name);
-    Br(bcx, scope_cx.llbb);
-    let Result {bcx, val} = f(scope_cx);
-    rslt(leave_block(bcx, scope_cx), val)
+
+    let scope = simple_block_scope(bcx.scope, opt_node_info);
+    bcx.scope = Some(scope);
+    let Result { bcx: out_bcx, val } = f(bcx);
+    let out_bcx = trans_block_cleanups_(out_bcx, /*bad*/copy scope.cleanups, false);
+    bcx.scope = scope.parent;
+
+    rslt(out_bcx, val)
 }
 
 pub fn with_scope_datumblock(bcx: block, opt_node_info: Option<NodeInfo>,
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index 1030af97878..60165d317d1 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -318,7 +318,7 @@ pub fn add_clean(bcx: block, val: ValueRef, t: ty::t) {
     debug!("add_clean(%s, %s, %s)", bcx.to_str(), bcx.val_to_str(val), t.repr(bcx.tcx()));
 
     let cleanup_type = cleanup_type(bcx.tcx(), t);
-    do in_scope_cx(bcx) |scope_info| {
+    do in_scope_cx(bcx, None) |scope_info| {
         scope_info.cleanups.push(clean(|a| glue::drop_ty(a, val, t), cleanup_type));
         grow_scope_clean(scope_info);
     }
@@ -330,25 +330,36 @@ pub fn add_clean_temp_immediate(cx: block, val: ValueRef, ty: ty::t) {
            cx.to_str(), cx.val_to_str(val),
            ty.repr(cx.tcx()));
     let cleanup_type = cleanup_type(cx.tcx(), ty);
-    do in_scope_cx(cx) |scope_info| {
+    do in_scope_cx(cx, None) |scope_info| {
         scope_info.cleanups.push(
             clean_temp(val, |a| glue::drop_ty_immediate(a, val, ty),
                        cleanup_type));
         grow_scope_clean(scope_info);
     }
 }
+
 pub fn add_clean_temp_mem(bcx: block, val: ValueRef, t: ty::t) {
+    add_clean_temp_mem_in_scope_(bcx, None, val, t);
+}
+
+pub fn add_clean_temp_mem_in_scope(bcx: block, scope_id: ast::node_id, val: ValueRef, t: ty::t) {
+    add_clean_temp_mem_in_scope_(bcx, Some(scope_id), val, t);
+}
+
+pub fn add_clean_temp_mem_in_scope_(bcx: block, scope_id: Option<ast::node_id>,
+                                    val: ValueRef, t: ty::t) {
     if !ty::type_needs_drop(bcx.tcx(), t) { return; }
     debug!("add_clean_temp_mem(%s, %s, %s)",
            bcx.to_str(), bcx.val_to_str(val),
            t.repr(bcx.tcx()));
     let cleanup_type = cleanup_type(bcx.tcx(), t);
-    do in_scope_cx(bcx) |scope_info| {
+    do in_scope_cx(bcx, scope_id) |scope_info| {
         scope_info.cleanups.push(clean_temp(val, |a| glue::drop_ty(a, val, t), cleanup_type));
         grow_scope_clean(scope_info);
     }
 }
 pub fn add_clean_return_to_mut(bcx: block,
+                               scope_id: ast::node_id,
                                root_key: root_map_key,
                                frozen_val_ref: ValueRef,
                                bits_val_ref: ValueRef,
@@ -366,7 +377,7 @@ pub fn add_clean_return_to_mut(bcx: block,
            bcx.to_str(),
            bcx.val_to_str(frozen_val_ref),
            bcx.val_to_str(bits_val_ref));
-    do in_scope_cx(bcx) |scope_info| {
+    do in_scope_cx(bcx, Some(scope_id)) |scope_info| {
         scope_info.cleanups.push(
             clean_temp(
                 frozen_val_ref,
@@ -387,7 +398,7 @@ pub fn add_clean_free(cx: block, ptr: ValueRef, heap: heap) {
         f
       }
     };
-    do in_scope_cx(cx) |scope_info| {
+    do in_scope_cx(cx, None) |scope_info| {
         scope_info.cleanups.push(clean_temp(ptr, free_fn,
                                       normal_exit_and_unwind));
         grow_scope_clean(scope_info);
@@ -399,7 +410,7 @@ pub fn add_clean_free(cx: block, ptr: ValueRef, heap: heap) {
 // this will be more involved. For now, we simply zero out the local, and the
 // drop glue checks whether it is zero.
 pub fn revoke_clean(cx: block, val: ValueRef) {
-    do in_scope_cx(cx) |scope_info| {
+    do in_scope_cx(cx, None) |scope_info| {
         let cleanup_pos = scope_info.cleanups.iter().position_(
             |cu| match *cu {
                 clean_temp(v, _, _) if v == val => true,
@@ -416,27 +427,14 @@ pub fn revoke_clean(cx: block, val: ValueRef) {
 }
 
 pub fn block_cleanups(bcx: block) -> ~[cleanup] {
-    match bcx.kind {
-       block_non_scope  => ~[],
-       block_scope(inf) => /*bad*/copy inf.cleanups
+    match bcx.scope {
+       None  => ~[],
+       Some(inf) => /*bad*/copy inf.cleanups
     }
 }
 
-pub enum block_kind {
-    // A scope at the end of which temporary values created inside of it are
-    // cleaned up. May correspond to an actual block in the language, but also
-    // to an implicit scope, for example, calls introduce an implicit scope in
-    // which the arguments are evaluated and cleaned up.
-    block_scope(@mut scope_info),
-
-    // A non-scope block is a basic block created as a translation artifact
-    // from translating code that expresses conditional logic rather than by
-    // explicit { ... } block structure in the source language.  It's called a
-    // non-scope block because it doesn't introduce a new variable scope.
-    block_non_scope,
-}
-
 pub struct scope_info {
+    parent: Option<@mut scope_info>,
     loop_break: Option<block>,
     loop_label: Option<ident>,
     // A list of functions that must be run at when leaving this
@@ -448,6 +446,8 @@ pub struct scope_info {
     cleanup_paths: ~[cleanup_path],
     // Unwinding landing pad. Also cleared when cleanups change.
     landing_pad: Option<BasicBlockRef>,
+    // info about the AST node this scope originated from, if any
+    node_info: Option<NodeInfo>,
 }
 
 impl scope_info {
@@ -503,8 +503,8 @@ pub struct block_ {
     terminated: bool,
     unreachable: bool,
     parent: Option<block>,
-    // The 'kind' of basic block this is.
-    kind: block_kind,
+    // The current scope within this basic block
+    scope: Option<@mut scope_info>,
     // Is this block part of a landing pad?
     is_lpad: bool,
     // info about the AST node this block originated from, if any
@@ -514,7 +514,7 @@ pub struct block_ {
     fcx: fn_ctxt
 }
 
-pub fn block_(llbb: BasicBlockRef, parent: Option<block>, kind: block_kind,
+pub fn block_(llbb: BasicBlockRef, parent: Option<block>,
               is_lpad: bool, node_info: Option<NodeInfo>, fcx: fn_ctxt)
     -> block_ {
 
@@ -523,7 +523,7 @@ pub fn block_(llbb: BasicBlockRef, parent: Option<block>, kind: block_kind,
         terminated: false,
         unreachable: false,
         parent: parent,
-        kind: kind,
+        scope: None,
         is_lpad: is_lpad,
         node_info: node_info,
         fcx: fcx
@@ -532,10 +532,10 @@ pub fn block_(llbb: BasicBlockRef, parent: Option<block>, kind: block_kind,
 
 pub type block = @mut block_;
 
-pub fn mk_block(llbb: BasicBlockRef, parent: Option<block>, kind: block_kind,
+pub fn mk_block(llbb: BasicBlockRef, parent: Option<block>,
             is_lpad: bool, node_info: Option<NodeInfo>, fcx: fn_ctxt)
     -> block {
-    @mut block_(llbb, parent, kind, is_lpad, node_info, fcx)
+    @mut block_(llbb, parent, is_lpad, node_info, fcx)
 }
 
 pub struct Result {
@@ -560,19 +560,33 @@ pub fn val_ty(v: ValueRef) -> Type {
     }
 }
 
-pub fn in_scope_cx(cx: block, f: &fn(si: &mut scope_info)) {
+pub fn in_scope_cx(cx: block, scope_id: Option<ast::node_id>, f: &fn(si: &mut scope_info)) {
     let mut cur = cx;
+    let mut cur_scope = cur.scope;
     loop {
-        match cur.kind {
-            block_scope(inf) => {
-                debug!("in_scope_cx: selected cur=%s (cx=%s)",
-                       cur.to_str(), cx.to_str());
-                f(inf);
-                return;
+        cur_scope = match cur_scope {
+            Some(inf) => match scope_id {
+                Some(wanted) => match inf.node_info {
+                    Some(NodeInfo { id: actual, _ }) if wanted == actual => {
+                        debug!("in_scope_cx: selected cur=%s (cx=%s)",
+                               cur.to_str(), cx.to_str());
+                        f(inf);
+                        return;
+                    },
+                    _ => inf.parent,
+                },
+                None => {
+                    debug!("in_scope_cx: selected cur=%s (cx=%s)",
+                           cur.to_str(), cx.to_str());
+                    f(inf);
+                    return;
+                }
+            },
+            None => {
+                cur = block_parent(cur);
+                cur.scope
             }
-            _ => ()
         }
-        cur = block_parent(cur);
     }
 }
 
diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs
index 75b1830778b..db6a954ee91 100644
--- a/src/librustc/middle/trans/controlflow.rs
+++ b/src/librustc/middle/trans/controlflow.rs
@@ -249,42 +249,48 @@ pub fn trans_break_cont(bcx: block,
     let _icx = push_ctxt("trans_break_cont");
     // Locate closest loop block, outputting cleanup as we go.
     let mut unwind = bcx;
-    let mut target;
+    let mut cur_scope = unwind.scope;
+    let mut target = unwind;
+    let mut quit = false;
     loop {
-        match unwind.kind {
-          block_scope(@scope_info {
-            loop_break: Some(brk),
-            loop_label: l,
-            _
-          }) => {
-              // If we're looking for a labeled loop, check the label...
-              target = if to_end {
-                  brk
-              } else {
-                  unwind
-              };
-              match opt_label {
-                  Some(desired) => match l {
-                      Some(actual) if actual == desired => break,
-                      // If it doesn't match the one we want,
-                      // don't break
-                      _ => ()
-                  },
-                  None => break
-              }
-          }
-          _ => ()
+        cur_scope = match cur_scope {
+            Some(@scope_info {
+                loop_break: Some(brk),
+                loop_label: l,
+                parent,
+                _
+            }) => {
+                // If we're looking for a labeled loop, check the label...
+                target = if to_end {
+                    brk
+                } else {
+                    unwind
+                };
+                match opt_label {
+                    Some(desired) => match l {
+                        Some(actual) if actual == desired => break,
+                        // If it doesn't match the one we want,
+                        // don't break
+                        _ => parent,
+                    },
+                    None => break,
+                }
+            }
+            Some(inf) => inf.parent,
+            None => {
+                unwind = match unwind.parent {
+                    Some(bcx) => bcx,
+                        // This is a return from a loop body block
+                        None => {
+                            Store(bcx, C_bool(!to_end), bcx.fcx.llretptr.get());
+                            cleanup_and_leave(bcx, None, Some(bcx.fcx.llreturn));
+                            Unreachable(bcx);
+                            return bcx;
+                        }
+                };
+                unwind.scope
+            }
         }
-        unwind = match unwind.parent {
-          Some(bcx) => bcx,
-          // This is a return from a loop body block
-          None => {
-            Store(bcx, C_bool(!to_end), bcx.fcx.llretptr.get());
-            cleanup_and_leave(bcx, None, Some(bcx.fcx.llreturn));
-            Unreachable(bcx);
-            return bcx;
-          }
-        };
     }
     cleanup_and_Br(bcx, unwind, target.llbb);
     Unreachable(bcx);
diff --git a/src/librustc/middle/trans/write_guard.rs b/src/librustc/middle/trans/write_guard.rs
index 068ce4e2b33..0db770b6c8b 100644
--- a/src/librustc/middle/trans/write_guard.rs
+++ b/src/librustc/middle/trans/write_guard.rs
@@ -123,7 +123,7 @@ fn root(datum: &Datum,
     let scratch = scratch_datum(bcx, datum.ty, true);
     datum.copy_to_datum(bcx, INIT, scratch);
     let cleanup_bcx = find_bcx_for_scope(bcx, root_info.scope);
-    add_clean_temp_mem(cleanup_bcx, scratch.val, scratch.ty);
+    add_clean_temp_mem_in_scope(cleanup_bcx, root_info.scope, scratch.val, scratch.ty);
 
     // Now, consider also freezing it.
     match root_info.freeze {
@@ -168,7 +168,7 @@ fn root(datum: &Datum,
             }
 
             add_clean_return_to_mut(
-                cleanup_bcx, root_key, scratch.val, scratch_bits.val,
+                cleanup_bcx, root_info.scope, root_key, scratch.val, scratch_bits.val,
                 filename, line);
         }
     }