summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2013-12-20 17:36:07 -0800
committerPatrick Walton <pcwalton@mimiga.net>2013-12-26 15:54:28 -0800
commit2fb33285e6169552e58d10197c11cd2f8702291f (patch)
treea0aa83d25cda1b73187584732255aebe6f02727a /src
parent82f5a380a48262e10e2d7c53e679351c5aedbf5a (diff)
downloadrust-2fb33285e6169552e58d10197c11cd2f8702291f.tar.gz
rust-2fb33285e6169552e58d10197c11cd2f8702291f.zip
libextra: Stop using `@mut MemWriter` in the EBML module
Diffstat (limited to 'src')
-rw-r--r--src/libextra/ebml.rs84
-rw-r--r--src/librustc/metadata/encoder.rs102
-rw-r--r--src/librustc/metadata/tyencode.rs50
-rw-r--r--src/librustc/middle/astencode.rs35
4 files changed, 148 insertions, 123 deletions
diff --git a/src/libextra/ebml.rs b/src/libextra/ebml.rs
index 16a43276401..27d7a1dee99 100644
--- a/src/libextra/ebml.rs
+++ b/src/libextra/ebml.rs
@@ -593,22 +593,13 @@ pub mod writer {
     use std::io::extensions::u64_to_be_bytes;
 
     // ebml writing
-    pub struct Encoder {
+    pub struct Encoder<'a> {
         // FIXME(#5665): this should take a trait object
-        writer: @mut MemWriter,
+        writer: &'a mut MemWriter,
         priv size_positions: ~[uint],
     }
 
-    impl Clone for Encoder {
-        fn clone(&self) -> Encoder {
-            Encoder {
-                writer: self.writer,
-                size_positions: self.size_positions.clone(),
-            }
-        }
-    }
-
-    fn write_sized_vuint(w: @mut MemWriter, n: uint, size: uint) {
+    fn write_sized_vuint(w: &mut MemWriter, n: uint, size: uint) {
         match size {
             1u => w.write(&[0x80u8 | (n as u8)]),
             2u => w.write(&[0x40u8 | ((n >> 8_u) as u8), n as u8]),
@@ -620,7 +611,7 @@ pub mod writer {
         };
     }
 
-    fn write_vuint(w: @mut MemWriter, n: uint) {
+    fn write_vuint(w: &mut MemWriter, n: uint) {
         if n < 0x7f_u { write_sized_vuint(w, n, 1u); return; }
         if n < 0x4000_u { write_sized_vuint(w, n, 2u); return; }
         if n < 0x200000_u { write_sized_vuint(w, n, 3u); return; }
@@ -628,7 +619,7 @@ pub mod writer {
         fail!("vint to write too big: {}", n);
     }
 
-    pub fn Encoder(w: @mut MemWriter) -> Encoder {
+    pub fn Encoder<'a>(w: &'a mut MemWriter) -> Encoder<'a> {
         let size_positions: ~[uint] = ~[];
         Encoder {
             writer: w,
@@ -637,7 +628,15 @@ pub mod writer {
     }
 
     // FIXME (#2741): Provide a function to write the standard ebml header.
-    impl Encoder {
+    impl<'a> Encoder<'a> {
+        /// XXX(pcwalton): Workaround for badness in trans. DO NOT USE ME.
+        pub unsafe fn unsafe_clone(&self) -> Encoder<'a> {
+            Encoder {
+                writer: cast::transmute_copy(&self.writer),
+                size_positions: self.size_positions.clone(),
+            }
+        }
+
         pub fn start_tag(&mut self, tag_id: uint) {
             debug!("Start tag {}", tag_id);
 
@@ -739,7 +738,7 @@ pub mod writer {
     // Totally lame approach.
     static DEBUG: bool = true;
 
-    impl Encoder {
+    impl<'a> Encoder<'a> {
         // used internally to emit things like the vector length and so on
         fn _emit_tagged_uint(&mut self, t: EbmlEncoderTag, v: uint) {
             assert!(v <= 0xFFFF_FFFF_u);
@@ -755,9 +754,7 @@ pub mod writer {
             // try and check failures more quickly.
             if DEBUG { self.wr_tagged_str(EsLabel as uint, label) }
         }
-    }
 
-    impl Encoder {
         pub fn emit_opaque(&mut self, f: |&mut Encoder|) {
             self.start_tag(EsOpaque as uint);
             f(self);
@@ -765,7 +762,7 @@ pub mod writer {
         }
     }
 
-    impl ::serialize::Encoder for Encoder {
+    impl<'a> ::serialize::Encoder for Encoder<'a> {
         fn emit_nil(&mut self) {}
 
         fn emit_uint(&mut self, v: uint) {
@@ -820,7 +817,7 @@ pub mod writer {
             self.wr_tagged_str(EsStr as uint, v)
         }
 
-        fn emit_enum(&mut self, name: &str, f: |&mut Encoder|) {
+        fn emit_enum(&mut self, name: &str, f: |&mut Encoder<'a>|) {
             self._emit_label(name);
             self.start_tag(EsEnum as uint);
             f(self);
@@ -831,14 +828,14 @@ pub mod writer {
                              _: &str,
                              v_id: uint,
                              _: uint,
-                             f: |&mut Encoder|) {
+                             f: |&mut Encoder<'a>|) {
             self._emit_tagged_uint(EsEnumVid, v_id);
             self.start_tag(EsEnumBody as uint);
             f(self);
             self.end_tag();
         }
 
-        fn emit_enum_variant_arg(&mut self, _: uint, f: |&mut Encoder|) {
+        fn emit_enum_variant_arg(&mut self, _: uint, f: |&mut Encoder<'a>|) {
             f(self)
         }
 
@@ -846,83 +843,88 @@ pub mod writer {
                                     v_name: &str,
                                     v_id: uint,
                                     cnt: uint,
-                                    f: |&mut Encoder|) {
+                                    f: |&mut Encoder<'a>|) {
             self.emit_enum_variant(v_name, v_id, cnt, f)
         }
 
         fn emit_enum_struct_variant_field(&mut self,
                                           _: &str,
                                           idx: uint,
-                                          f: |&mut Encoder|) {
+                                          f: |&mut Encoder<'a>|) {
             self.emit_enum_variant_arg(idx, f)
         }
 
-        fn emit_struct(&mut self, _: &str, _len: uint, f: |&mut Encoder|) {
+        fn emit_struct(&mut self,
+                       _: &str,
+                       _len: uint,
+                       f: |&mut Encoder<'a>|) {
             f(self)
         }
 
         fn emit_struct_field(&mut self,
                              name: &str,
                              _: uint,
-                             f: |&mut Encoder|) {
+                             f: |&mut Encoder<'a>|) {
             self._emit_label(name);
             f(self)
         }
 
-        fn emit_tuple(&mut self, len: uint, f: |&mut Encoder|) {
+        fn emit_tuple(&mut self, len: uint, f: |&mut Encoder<'a>|) {
             self.emit_seq(len, f)
         }
-        fn emit_tuple_arg(&mut self, idx: uint, f: |&mut Encoder|) {
+        fn emit_tuple_arg(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
             self.emit_seq_elt(idx, f)
         }
 
         fn emit_tuple_struct(&mut self,
                              _: &str,
                              len: uint,
-                             f: |&mut Encoder|) {
+                             f: |&mut Encoder<'a>|) {
             self.emit_seq(len, f)
         }
-        fn emit_tuple_struct_arg(&mut self, idx: uint, f: |&mut Encoder|) {
+        fn emit_tuple_struct_arg(&mut self,
+                                 idx: uint,
+                                 f: |&mut Encoder<'a>|) {
             self.emit_seq_elt(idx, f)
         }
 
-        fn emit_option(&mut self, f: |&mut Encoder|) {
+        fn emit_option(&mut self, f: |&mut Encoder<'a>|) {
             self.emit_enum("Option", f);
         }
         fn emit_option_none(&mut self) {
             self.emit_enum_variant("None", 0, 0, |_| ())
         }
-        fn emit_option_some(&mut self, f: |&mut Encoder|) {
+        fn emit_option_some(&mut self, f: |&mut Encoder<'a>|) {
             self.emit_enum_variant("Some", 1, 1, f)
         }
 
-        fn emit_seq(&mut self, len: uint, f: |&mut Encoder|) {
+        fn emit_seq(&mut self, len: uint, f: |&mut Encoder<'a>|) {
             self.start_tag(EsVec as uint);
             self._emit_tagged_uint(EsVecLen, len);
             f(self);
             self.end_tag();
         }
 
-        fn emit_seq_elt(&mut self, _idx: uint, f: |&mut Encoder|) {
+        fn emit_seq_elt(&mut self, _idx: uint, f: |&mut Encoder<'a>|) {
             self.start_tag(EsVecElt as uint);
             f(self);
             self.end_tag();
         }
 
-        fn emit_map(&mut self, len: uint, f: |&mut Encoder|) {
+        fn emit_map(&mut self, len: uint, f: |&mut Encoder<'a>|) {
             self.start_tag(EsMap as uint);
             self._emit_tagged_uint(EsMapLen, len);
             f(self);
             self.end_tag();
         }
 
-        fn emit_map_elt_key(&mut self, _idx: uint, f: |&mut Encoder|) {
+        fn emit_map_elt_key(&mut self, _idx: uint, f: |&mut Encoder<'a>|) {
             self.start_tag(EsMapKey as uint);
             f(self);
             self.end_tag();
         }
 
-        fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut Encoder|) {
+        fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut Encoder<'a>|) {
             self.start_tag(EsMapVal as uint);
             f(self);
             self.end_tag();
@@ -948,9 +950,11 @@ mod tests {
     fn test_option_int() {
         fn test_v(v: Option<int>) {
             debug!("v == {:?}", v);
-            let wr = @mut MemWriter::new();
-            let mut ebml_w = writer::Encoder(wr);
-            v.encode(&mut ebml_w);
+            let mut wr = MemWriter::new();
+            {
+                let mut ebml_w = writer::Encoder(&mut wr);
+                v.encode(&mut ebml_w);
+            }
             let ebml_doc = reader::Doc(*wr.inner_ref());
             let mut deser = reader::Decoder(ebml_doc);
             let v1 = serialize::Decodable::decode(&mut deser);
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 00ec1fd9fe6..214dc41bf2d 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -1293,11 +1293,16 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext,
 
 fn my_visit_expr(_e:@Expr) { }
 
-fn my_visit_item(i:@item, items: ast_map::map, ebml_w:&writer::Encoder,
-                 ecx_ptr:*int, index: @mut ~[entry<i64>]) {
+fn my_visit_item(i: @item,
+                 items: ast_map::map,
+                 ebml_w: &mut writer::Encoder,
+                 ecx_ptr: *int,
+                 index: @mut ~[entry<i64>]) {
     match items.get_copy(&i.id) {
         ast_map::node_item(_, pt) => {
-            let mut ebml_w = ebml_w.clone();
+            let mut ebml_w = unsafe {
+                ebml_w.unsafe_clone()
+            };
             // See above
             let ecx : &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
             encode_info_for_item(ecx, &mut ebml_w, i, index, *pt, i.vis);
@@ -1306,8 +1311,11 @@ fn my_visit_item(i:@item, items: ast_map::map, ebml_w:&writer::Encoder,
     }
 }
 
-fn my_visit_foreign_item(ni:@foreign_item, items: ast_map::map, ebml_w:&writer::Encoder,
-                         ecx_ptr:*int, index: @mut ~[entry<i64>]) {
+fn my_visit_foreign_item(ni: @foreign_item,
+                         items: ast_map::map,
+                         ebml_w: &mut writer::Encoder,
+                         ecx_ptr:*int,
+                         index: @mut ~[entry<i64>]) {
     match items.get_copy(&ni.id) {
         ast_map::node_foreign_item(_, abi, _, pt) => {
             debug!("writing foreign item {}::{}",
@@ -1316,9 +1324,11 @@ fn my_visit_foreign_item(ni:@foreign_item, items: ast_map::map, ebml_w:&writer::
                        token::get_ident_interner()),
                    token::ident_to_str(&ni.ident));
 
-            let mut ebml_w = ebml_w.clone();
+            let mut ebml_w = unsafe {
+                ebml_w.unsafe_clone()
+            };
             // See above
-            let ecx : &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
+            let ecx: &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
             encode_info_for_foreign_item(ecx,
                                          &mut ebml_w,
                                          ni,
@@ -1331,15 +1341,14 @@ fn my_visit_foreign_item(ni:@foreign_item, items: ast_map::map, ebml_w:&writer::
     }
 }
 
-struct EncodeVisitor {
-    ebml_w_for_visit_item: writer::Encoder,
-    ebml_w_for_visit_foreign_item: writer::Encoder,
+struct EncodeVisitor<'a,'b> {
+    ebml_w_for_visit_item: &'a mut writer::Encoder<'b>,
     ecx_ptr:*int,
     items: ast_map::map,
     index: @mut ~[entry<i64>],
 }
 
-impl visit::Visitor<()> for EncodeVisitor {
+impl<'a,'b> visit::Visitor<()> for EncodeVisitor<'a,'b> {
     fn visit_expr(&mut self, ex:@Expr, _:()) {
         visit::walk_expr(self, ex, ());
         my_visit_expr(ex);
@@ -1348,7 +1357,7 @@ impl visit::Visitor<()> for EncodeVisitor {
         visit::walk_item(self, i, ());
         my_visit_item(i,
                       self.items,
-                      &self.ebml_w_for_visit_item,
+                      self.ebml_w_for_visit_item,
                       self.ecx_ptr,
                       self.index);
     }
@@ -1356,7 +1365,7 @@ impl visit::Visitor<()> for EncodeVisitor {
         visit::walk_foreign_item(self, ni, ());
         my_visit_foreign_item(ni,
                               self.items,
-                              &self.ebml_w_for_visit_foreign_item,
+                              self.ebml_w_for_visit_item,
                               self.ecx_ptr,
                               self.index);
     }
@@ -1380,15 +1389,16 @@ fn encode_info_for_items(ecx: &EncodeContext,
 
     // See comment in `encode_side_tables_for_ii` in astencode
     let ecx_ptr : *int = unsafe { cast::transmute(ecx) };
-    let mut visitor = EncodeVisitor {
-        index: index,
-        items: items,
-        ecx_ptr: ecx_ptr,
-        ebml_w_for_visit_item: (*ebml_w).clone(),
-        ebml_w_for_visit_foreign_item: (*ebml_w).clone(),
-    };
+    {
+        let mut visitor = EncodeVisitor {
+            index: index,
+            items: items,
+            ecx_ptr: ecx_ptr,
+            ebml_w_for_visit_item: &mut *ebml_w,
+        };
 
-    visit::walk_crate(&mut visitor, crate, ());
+        visit::walk_crate(&mut visitor, crate, ());
+    }
 
     ebml_w.end_tag();
     return /*bad*/(*index).clone();
@@ -1417,7 +1427,7 @@ fn create_index<T:Clone + Hash + IterBytes + 'static>(
 fn encode_index<T:'static>(
                 ebml_w: &mut writer::Encoder,
                 buckets: ~[@~[entry<T>]],
-                write_fn: |@mut MemWriter, &T|) {
+                write_fn: |&mut MemWriter, &T|) {
     ebml_w.start_tag(tag_index);
     let mut bucket_locs = ~[];
     ebml_w.start_tag(tag_index_buckets);
@@ -1447,7 +1457,7 @@ fn encode_index<T:'static>(
     ebml_w.end_tag();
 }
 
-fn write_i64(writer: @mut MemWriter, &n: &i64) {
+fn write_i64(writer: &mut MemWriter, &n: &i64) {
     let wr: &mut MemWriter = writer;
     assert!(n < 0x7fff_ffff);
     wr.write_be_u32(n as u32);
@@ -1623,12 +1633,12 @@ fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
     ebml_w.end_tag();
 }
 
-struct ImplVisitor<'a> {
+struct ImplVisitor<'a,'b> {
     ecx: &'a EncodeContext<'a>,
-    ebml_w: &'a mut writer::Encoder,
+    ebml_w: &'a mut writer::Encoder<'b>,
 }
 
-impl<'a> Visitor<()> for ImplVisitor<'a> {
+impl<'a,'b> Visitor<()> for ImplVisitor<'a,'b> {
     fn visit_item(&mut self, item: @item, _: ()) {
         match item.node {
             item_impl(_, Some(ref trait_ref), _, _) => {
@@ -1781,51 +1791,51 @@ pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] {
 
     encode_hash(&mut ebml_w, ecx.link_meta.crate_hash);
 
-    let mut i = wr.tell();
+    let mut i = ebml_w.writer.tell();
     let crate_attrs = synthesize_crate_attrs(&ecx, crate);
     encode_attributes(&mut ebml_w, crate_attrs);
-    ecx.stats.attr_bytes = wr.tell() - i;
+    ecx.stats.attr_bytes = ebml_w.writer.tell() - i;
 
-    i = wr.tell();
+    i = ebml_w.writer.tell();
     encode_crate_deps(&ecx, &mut ebml_w, ecx.cstore);
-    ecx.stats.dep_bytes = wr.tell() - i;
+    ecx.stats.dep_bytes = ebml_w.writer.tell() - i;
 
     // Encode the language items.
-    i = wr.tell();
+    i = ebml_w.writer.tell();
     encode_lang_items(&ecx, &mut ebml_w);
-    ecx.stats.lang_item_bytes = wr.tell() - i;
+    ecx.stats.lang_item_bytes = ebml_w.writer.tell() - i;
 
     // Encode the native libraries used
-    i = wr.tell();
+    i = ebml_w.writer.tell();
     encode_native_libraries(&ecx, &mut ebml_w);
-    ecx.stats.native_lib_bytes = wr.tell() - i;
+    ecx.stats.native_lib_bytes = ebml_w.writer.tell() - i;
 
     // Encode the def IDs of impls, for coherence checking.
-    i = wr.tell();
+    i = ebml_w.writer.tell();
     encode_impls(&ecx, crate, &mut ebml_w);
-    ecx.stats.impl_bytes = wr.tell() - i;
+    ecx.stats.impl_bytes = ebml_w.writer.tell() - i;
 
     // Encode miscellaneous info.
-    i = wr.tell();
+    i = ebml_w.writer.tell();
     encode_misc_info(&ecx, crate, &mut ebml_w);
-    ecx.stats.misc_bytes = wr.tell() - i;
+    ecx.stats.misc_bytes = ebml_w.writer.tell() - i;
 
     // Encode and index the items.
     ebml_w.start_tag(tag_items);
-    i = wr.tell();
+    i = ebml_w.writer.tell();
     let items_index = encode_info_for_items(&ecx, &mut ebml_w, crate);
-    ecx.stats.item_bytes = wr.tell() - i;
+    ecx.stats.item_bytes = ebml_w.writer.tell() - i;
 
-    i = wr.tell();
+    i = ebml_w.writer.tell();
     let items_buckets = create_index(items_index);
     encode_index(&mut ebml_w, items_buckets, write_i64);
-    ecx.stats.index_bytes = wr.tell() - i;
+    ecx.stats.index_bytes = ebml_w.writer.tell() - i;
     ebml_w.end_tag();
 
-    ecx.stats.total_bytes = wr.tell();
+    ecx.stats.total_bytes = ebml_w.writer.tell();
 
     if (tcx.sess.meta_stats()) {
-        for e in wr.inner_ref().iter() {
+        for e in ebml_w.writer.inner_ref().iter() {
             if *e == 0 {
                 ecx.stats.zero_bytes += 1;
             }
@@ -1847,11 +1857,11 @@ pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] {
 
     // Pad this, since something (LLVM, presumably) is cutting off the
     // remaining % 4 bytes.
-    wr.write(&[0u8, 0u8, 0u8, 0u8]);
+    ebml_w.writer.write(&[0u8, 0u8, 0u8, 0u8]);
 
     // This is a horrible thing to do to the outer MemWriter, but thankfully we
     // don't use it again so... it's ok right?
-    return util::replace(wr.inner_mut_ref(), ~[]);
+    return util::replace(ebml_w.writer.inner_mut_ref(), ~[]);
 }
 
 // Get the encoded string for a type
diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs
index 877ae28a2ce..8ad9784df1b 100644
--- a/src/librustc/metadata/tyencode.rs
+++ b/src/librustc/metadata/tyencode.rs
@@ -53,11 +53,11 @@ pub enum abbrev_ctxt {
     ac_use_abbrevs(@mut HashMap<ty::t, ty_abbrev>),
 }
 
-fn mywrite(w: @mut MemWriter, fmt: &fmt::Arguments) {
+fn mywrite(w: &mut MemWriter, fmt: &fmt::Arguments) {
     fmt::write(&mut *w as &mut io::Writer, fmt);
 }
 
-pub fn enc_ty(w: @mut MemWriter, cx: @ctxt, t: ty::t) {
+pub fn enc_ty(w: &mut MemWriter, cx: @ctxt, t: ty::t) {
     match cx.abbrevs {
       ac_no_abbrevs => {
           let result_str_opt;
@@ -70,7 +70,7 @@ pub fn enc_ty(w: @mut MemWriter, cx: @ctxt, t: ty::t) {
           let result_str = match result_str_opt {
             Some(s) => s,
             None => {
-                let wr = @mut MemWriter::new();
+                let wr = &mut MemWriter::new();
                 enc_sty(wr, cx, &ty::get(t).sty);
                 let s = str::from_utf8(*wr.inner_ref()).to_managed();
                 let mut short_names_cache = cx.tcx
@@ -111,37 +111,37 @@ pub fn enc_ty(w: @mut MemWriter, cx: @ctxt, t: ty::t) {
     }
 }
 
-fn enc_mutability(w: @mut MemWriter, mt: ast::Mutability) {
+fn enc_mutability(w: &mut MemWriter, mt: ast::Mutability) {
     match mt {
         MutImmutable => (),
         MutMutable => mywrite!(w, "m"),
     }
 }
 
-fn enc_mt(w: @mut MemWriter, cx: @ctxt, mt: ty::mt) {
+fn enc_mt(w: &mut MemWriter, cx: @ctxt, mt: ty::mt) {
     enc_mutability(w, mt.mutbl);
     enc_ty(w, cx, mt.ty);
 }
 
-fn enc_opt<T>(w: @mut MemWriter, t: Option<T>, enc_f: |T|) {
+fn enc_opt<T>(w: &mut MemWriter, t: Option<T>, enc_f: |&mut MemWriter, T|) {
     match t {
         None => mywrite!(w, "n"),
         Some(v) => {
             mywrite!(w, "s");
-            enc_f(v);
+            enc_f(w, v);
         }
     }
 }
 
-fn enc_substs(w: @mut MemWriter, cx: @ctxt, substs: &ty::substs) {
+fn enc_substs(w: &mut MemWriter, cx: @ctxt, substs: &ty::substs) {
     enc_region_substs(w, cx, &substs.regions);
-    enc_opt(w, substs.self_ty, |t| enc_ty(w, cx, t));
+    enc_opt(w, substs.self_ty, |w, t| enc_ty(w, cx, t));
     mywrite!(w, "[");
     for t in substs.tps.iter() { enc_ty(w, cx, *t); }
     mywrite!(w, "]");
 }
 
-fn enc_region_substs(w: @mut MemWriter, cx: @ctxt, substs: &ty::RegionSubsts) {
+fn enc_region_substs(w: &mut MemWriter, cx: @ctxt, substs: &ty::RegionSubsts) {
     match *substs {
         ty::ErasedRegions => {
             mywrite!(w, "e");
@@ -156,7 +156,7 @@ fn enc_region_substs(w: @mut MemWriter, cx: @ctxt, substs: &ty::RegionSubsts) {
     }
 }
 
-fn enc_region(w: @mut MemWriter, cx: @ctxt, r: ty::Region) {
+fn enc_region(w: &mut MemWriter, cx: @ctxt, r: ty::Region) {
     match r {
         ty::ReLateBound(id, br) => {
             mywrite!(w, "b[{}|", id);
@@ -190,7 +190,7 @@ fn enc_region(w: @mut MemWriter, cx: @ctxt, r: ty::Region) {
     }
 }
 
-fn enc_bound_region(w: @mut MemWriter, cx: @ctxt, br: ty::BoundRegion) {
+fn enc_bound_region(w: &mut MemWriter, cx: @ctxt, br: ty::BoundRegion) {
     match br {
         ty::BrAnon(idx) => {
             mywrite!(w, "a{}|", idx);
@@ -206,7 +206,7 @@ fn enc_bound_region(w: @mut MemWriter, cx: @ctxt, br: ty::BoundRegion) {
     }
 }
 
-pub fn enc_vstore(w: @mut MemWriter, cx: @ctxt, v: ty::vstore) {
+pub fn enc_vstore(w: &mut MemWriter, cx: @ctxt, v: ty::vstore) {
     mywrite!(w, "/");
     match v {
         ty::vstore_fixed(u) => mywrite!(w, "{}|", u),
@@ -219,12 +219,12 @@ pub fn enc_vstore(w: @mut MemWriter, cx: @ctxt, v: ty::vstore) {
     }
 }
 
-pub fn enc_trait_ref(w: @mut MemWriter, cx: @ctxt, s: &ty::TraitRef) {
+pub fn enc_trait_ref(w: &mut MemWriter, cx: @ctxt, s: &ty::TraitRef) {
     mywrite!(w, "{}|", (cx.ds)(s.def_id));
     enc_substs(w, cx, &s.substs);
 }
 
-pub fn enc_trait_store(w: @mut MemWriter, cx: @ctxt, s: ty::TraitStore) {
+pub fn enc_trait_store(w: &mut MemWriter, cx: @ctxt, s: ty::TraitStore) {
     match s {
         ty::UniqTraitStore => mywrite!(w, "~"),
         ty::BoxTraitStore => mywrite!(w, "@"),
@@ -235,7 +235,7 @@ pub fn enc_trait_store(w: @mut MemWriter, cx: @ctxt, s: ty::TraitStore) {
     }
 }
 
-fn enc_sty(w: @mut MemWriter, cx: @ctxt, st: &ty::sty) {
+fn enc_sty(w: &mut MemWriter, cx: @ctxt, st: &ty::sty) {
     match *st {
         ty::ty_nil => mywrite!(w, "n"),
         ty::ty_bot => mywrite!(w, "z"),
@@ -335,7 +335,7 @@ fn enc_sty(w: @mut MemWriter, cx: @ctxt, st: &ty::sty) {
     }
 }
 
-fn enc_sigil(w: @mut MemWriter, sigil: Sigil) {
+fn enc_sigil(w: &mut MemWriter, sigil: Sigil) {
     match sigil {
         ManagedSigil => mywrite!(w, "@"),
         OwnedSigil => mywrite!(w, "~"),
@@ -343,7 +343,7 @@ fn enc_sigil(w: @mut MemWriter, sigil: Sigil) {
     }
 }
 
-fn enc_purity(w: @mut MemWriter, p: purity) {
+fn enc_purity(w: &mut MemWriter, p: purity) {
     match p {
         impure_fn => mywrite!(w, "i"),
         unsafe_fn => mywrite!(w, "u"),
@@ -351,7 +351,7 @@ fn enc_purity(w: @mut MemWriter, p: purity) {
     }
 }
 
-fn enc_abi_set(w: @mut MemWriter, abis: AbiSet) {
+fn enc_abi_set(w: &mut MemWriter, abis: AbiSet) {
     mywrite!(w, "[");
     abis.each(|abi| {
         mywrite!(w, "{},", abi.name());
@@ -360,20 +360,20 @@ fn enc_abi_set(w: @mut MemWriter, abis: AbiSet) {
     mywrite!(w, "]")
 }
 
-fn enc_onceness(w: @mut MemWriter, o: Onceness) {
+fn enc_onceness(w: &mut MemWriter, o: Onceness) {
     match o {
         Once => mywrite!(w, "o"),
         Many => mywrite!(w, "m")
     }
 }
 
-pub fn enc_bare_fn_ty(w: @mut MemWriter, cx: @ctxt, ft: &ty::BareFnTy) {
+pub fn enc_bare_fn_ty(w: &mut MemWriter, cx: @ctxt, ft: &ty::BareFnTy) {
     enc_purity(w, ft.purity);
     enc_abi_set(w, ft.abis);
     enc_fn_sig(w, cx, &ft.sig);
 }
 
-fn enc_closure_ty(w: @mut MemWriter, cx: @ctxt, ft: &ty::ClosureTy) {
+fn enc_closure_ty(w: &mut MemWriter, cx: @ctxt, ft: &ty::ClosureTy) {
     enc_sigil(w, ft.sigil);
     enc_purity(w, ft.purity);
     enc_onceness(w, ft.onceness);
@@ -384,7 +384,7 @@ fn enc_closure_ty(w: @mut MemWriter, cx: @ctxt, ft: &ty::ClosureTy) {
     enc_fn_sig(w, cx, &ft.sig);
 }
 
-fn enc_fn_sig(w: @mut MemWriter, cx: @ctxt, fsig: &ty::FnSig) {
+fn enc_fn_sig(w: &mut MemWriter, cx: @ctxt, fsig: &ty::FnSig) {
     mywrite!(w, "[{}|", fsig.binder_id);
     for ty in fsig.inputs.iter() {
         enc_ty(w, cx, *ty);
@@ -398,7 +398,7 @@ fn enc_fn_sig(w: @mut MemWriter, cx: @ctxt, fsig: &ty::FnSig) {
     enc_ty(w, cx, fsig.output);
 }
 
-fn enc_bounds(w: @mut MemWriter, cx: @ctxt, bs: &ty::ParamBounds) {
+fn enc_bounds(w: &mut MemWriter, cx: @ctxt, bs: &ty::ParamBounds) {
     for bound in bs.builtin_bounds.iter() {
         match bound {
             ty::BoundSend => mywrite!(w, "S"),
@@ -417,7 +417,7 @@ fn enc_bounds(w: @mut MemWriter, cx: @ctxt, bs: &ty::ParamBounds) {
     mywrite!(w, ".");
 }
 
-pub fn enc_type_param_def(w: @mut MemWriter, cx: @ctxt, v: &ty::TypeParameterDef) {
+pub fn enc_type_param_def(w: &mut MemWriter, cx: @ctxt, v: &ty::TypeParameterDef) {
     mywrite!(w, "{}:{}|", cx.tcx.sess.str_of(v.ident), (cx.ds)(v.def_id));
     enc_bounds(w, cx, v.bounds);
 }
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index 6ce30fbe01b..eefd99824e6 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -788,7 +788,7 @@ trait ebml_writer_helpers {
                  tpbt: ty::ty_param_bounds_and_ty);
 }
 
-impl ebml_writer_helpers for writer::Encoder {
+impl<'a> ebml_writer_helpers for writer::Encoder<'a> {
     fn emit_ty(&mut self, ecx: &e::EncodeContext, ty: ty::t) {
         self.emit_opaque(|this| e::write_type(ecx, this, ty))
     }
@@ -840,8 +840,10 @@ trait write_tag_and_id {
     fn id(&mut self, id: ast::NodeId);
 }
 
-impl write_tag_and_id for writer::Encoder {
-    fn tag(&mut self, tag_id: c::astencode_tag, f: |&mut writer::Encoder|) {
+impl<'a> write_tag_and_id for writer::Encoder<'a> {
+    fn tag(&mut self,
+           tag_id: c::astencode_tag,
+           f: |&mut writer::Encoder<'a>|) {
         self.start_tag(tag_id as uint);
         f(self);
         self.end_tag();
@@ -852,18 +854,23 @@ impl write_tag_and_id for writer::Encoder {
     }
 }
 
-struct SideTableEncodingIdVisitor {
+struct SideTableEncodingIdVisitor<'a,'b> {
     ecx_ptr: *libc::c_void,
-    new_ebml_w: writer::Encoder,
+    new_ebml_w: &'a mut writer::Encoder<'b>,
     maps: Maps,
 }
 
-impl ast_util::IdVisitingOperation for SideTableEncodingIdVisitor {
+impl<'a,'b> ast_util::IdVisitingOperation for
+        SideTableEncodingIdVisitor<'a,'b> {
     fn visit_id(&self, id: ast::NodeId) {
         // Note: this will cause a copy of ebml_w, which is bad as
         // it is mutable. But I believe it's harmless since we generate
         // balanced EBML.
-        let mut new_ebml_w = self.new_ebml_w.clone();
+        //
+        // XXX(pcwalton): Don't copy this way.
+        let mut new_ebml_w = unsafe {
+            self.new_ebml_w.unsafe_clone()
+        };
         // See above
         let ecx: &e::EncodeContext = unsafe {
             cast::transmute(self.ecx_ptr)
@@ -877,7 +884,9 @@ fn encode_side_tables_for_ii(ecx: &e::EncodeContext,
                              ebml_w: &mut writer::Encoder,
                              ii: &ast::inlined_item) {
     ebml_w.start_tag(c::tag_table as uint);
-    let new_ebml_w = (*ebml_w).clone();
+    let mut new_ebml_w = unsafe {
+        ebml_w.unsafe_clone()
+    };
 
     // Because the ast visitor uses @IdVisitingOperation, I can't pass in
     // ecx directly, but /I/ know that it'll be fine since the lifetime is
@@ -886,7 +895,7 @@ fn encode_side_tables_for_ii(ecx: &e::EncodeContext,
         ecx_ptr: unsafe {
             cast::transmute(ecx)
         },
-        new_ebml_w: new_ebml_w,
+        new_ebml_w: &mut new_ebml_w,
         maps: maps,
     });
     ebml_w.end_tag();
@@ -1360,9 +1369,11 @@ fn roundtrip(in_item: Option<@ast::item>) {
     use std::io::mem::MemWriter;
 
     let in_item = in_item.unwrap();
-    let wr = @mut MemWriter::new();
-    let mut ebml_w = writer::Encoder(wr);
-    encode_item_ast(&mut ebml_w, in_item);
+    let mut wr = MemWriter::new();
+    {
+        let mut ebml_w = writer::Encoder(&mut wr);
+        encode_item_ast(&mut ebml_w, in_item);
+    }
     let ebml_doc = reader::Doc(wr.inner_ref().as_slice());
     let out_item = decode_item_ast(ebml_doc);