diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs
index dbcfb4eebbffa..89dfa64511f82 100644
--- a/src/librustc/middle/trans/_match.rs
+++ b/src/librustc/middle/trans/_match.rs
@@ -1917,7 +1917,7 @@ fn trans_match_inner(scope_cx: @mut Block,
             Infallible
         }
     };
-    let lldiscr = discr_datum.to_zeroable_ref_llval(bcx);
+    let lldiscr = discr_datum.to_ref_llval(bcx);
     compile_submatch(bcx, matches, [lldiscr], chk);
 
     let mut arm_cxs = ~[];
@@ -1996,7 +1996,7 @@ pub fn store_local(bcx: @mut Block,
                 if bcx.sess().asm_comments() {
                     add_comment(bcx, "creating zeroable ref llval");
                 }
-                let llptr = init_datum.to_zeroable_ref_llval(bcx);
+                let llptr = init_datum.to_ref_llval(bcx);
                 return bind_irrefutable_pat(bcx, pat, llptr, BindLocal);
             }
         }
diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs
index 6411283b79d0e..294f3379f84f6 100644
--- a/src/librustc/middle/trans/datum.rs
+++ b/src/librustc/middle/trans/datum.rs
@@ -473,38 +473,25 @@ impl Datum {
                     C_null(type_of::type_of(bcx.ccx(), self.ty).ptr_to())
                 } else {
                     let slot = alloc_ty(bcx, self.ty, "");
+                    // The store created here can be modified through a reference, for example:
+                    //
+                    //     // free the old allocation, and change the pointer to a new allocation
+                    //     fn foo(x: &mut ~u8) {
+                    //         *x = ~5;
+                    //     }
+                    //
+                    //     foo(&mut ~5);
                     Store(bcx, self.val, slot);
+                    // The old cleanup needs to be cancelled, in order for the destructor to observe
+                    // any changes made through the reference.
+                    self.cancel_clean(bcx);
+                    add_clean_temp_mem(bcx, slot, self.ty);
                     slot
                 }
             }
         }
     }
 
-    pub fn to_zeroable_ref_llval(&self, bcx: @mut Block) -> ValueRef {
-        /*!
-         * Returns a by-ref llvalue that can be zeroed in order to
-         * cancel cleanup. This is a kind of hokey bridge used
-         * to adapt to the match code. Please don't use it for new code.
-         */
-
-        match self.mode {
-            // All by-ref datums are zeroable, even if we *could* just
-            // cancel the cleanup.
-            ByRef(_) => self.val,
-
-            // By value datums can't be zeroed (where would you store
-            // the zero?) so we have to spill them. Add a temp cleanup
-            // for this spilled value and cancel the cleanup on this
-            // current value.
-            ByValue => {
-                let slot = self.to_ref_llval(bcx);
-                self.cancel_clean(bcx);
-                add_clean_temp_mem(bcx, slot, self.ty);
-                slot
-            }
-        }
-    }
-
     pub fn appropriate_mode(&self, ccx: &mut CrateContext) -> DatumMode {
         /*! See the `appropriate_mode()` function */
 
diff --git a/src/test/run-pass/cancel-clean-via-immediate-rvalue-ref.rs b/src/test/run-pass/cancel-clean-via-immediate-rvalue-ref.rs
new file mode 100644
index 0000000000000..2b9e97be2c7ef
--- /dev/null
+++ b/src/test/run-pass/cancel-clean-via-immediate-rvalue-ref.rs
@@ -0,0 +1,17 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn foo(x: &mut ~u8) {
+    *x = ~5;
+}
+
+pub fn main() {
+    foo(&mut ~4);
+}