about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2013-12-27 14:11:01 -0800
committerPatrick Walton <pcwalton@mimiga.net>2014-01-03 14:01:58 -0800
commitb26018cc89681d979555f3405df71e370941ffd5 (patch)
tree0a37c52d02d783598ce9528b00ba00e8da4c3219 /src/libsyntax
parent4d66af2698fd2ff2d19d68cda4eb804b5d319e5b (diff)
downloadrust-b26018cc89681d979555f3405df71e370941ffd5.tar.gz
rust-b26018cc89681d979555f3405df71e370941ffd5.zip
librustc: De-`@mut` (and de-`@`) the pretty printer
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/print/pp.rs30
-rw-r--r--src/libsyntax/print/pprust.rs782
2 files changed, 418 insertions, 394 deletions
diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs
index 5138115746e..ad55d64494b 100644
--- a/src/libsyntax/print/pp.rs
+++ b/src/libsyntax/print/pp.rs
@@ -148,7 +148,7 @@ pub struct print_stack_elt {
 
 pub static size_infinity: int = 0xffff;
 
-pub fn mk_printer(out: @mut io::Writer, linewidth: uint) -> @mut Printer {
+pub fn mk_printer(out: @mut io::Writer, linewidth: uint) -> Printer {
     // Yes 3, it makes the ring buffers big enough to never
     // fall behind.
     let n: uint = 3 * linewidth;
@@ -156,7 +156,7 @@ pub fn mk_printer(out: @mut io::Writer, linewidth: uint) -> @mut Printer {
     let token: ~[token] = vec::from_elem(n, EOF);
     let size: ~[int] = vec::from_elem(n, 0);
     let scan_stack: ~[uint] = vec::from_elem(n, 0u);
-    @mut Printer {
+    Printer {
         out: out,
         buf_len: n,
         margin: linewidth as int,
@@ -557,47 +557,47 @@ impl Printer {
 // Convenience functions to talk to the printer.
 //
 // "raw box"
-pub fn rbox(p: @mut Printer, indent: uint, b: breaks) {
+pub fn rbox(p: &mut Printer, indent: uint, b: breaks) {
     p.pretty_print(BEGIN(begin_t {
         offset: indent as int,
         breaks: b
     }));
 }
 
-pub fn ibox(p: @mut Printer, indent: uint) { rbox(p, indent, inconsistent); }
+pub fn ibox(p: &mut Printer, indent: uint) { rbox(p, indent, inconsistent); }
 
-pub fn cbox(p: @mut Printer, indent: uint) { rbox(p, indent, consistent); }
+pub fn cbox(p: &mut Printer, indent: uint) { rbox(p, indent, consistent); }
 
-pub fn break_offset(p: @mut Printer, n: uint, off: int) {
+pub fn break_offset(p: &mut Printer, n: uint, off: int) {
     p.pretty_print(BREAK(break_t {
         offset: off,
         blank_space: n as int
     }));
 }
 
-pub fn end(p: @mut Printer) { p.pretty_print(END); }
+pub fn end(p: &mut Printer) { p.pretty_print(END); }
 
-pub fn eof(p: @mut Printer) { p.pretty_print(EOF); }
+pub fn eof(p: &mut Printer) { p.pretty_print(EOF); }
 
-pub fn word(p: @mut Printer, wrd: &str) {
+pub fn word(p: &mut Printer, wrd: &str) {
     p.pretty_print(STRING(/* bad */ wrd.to_managed(), wrd.len() as int));
 }
 
-pub fn huge_word(p: @mut Printer, wrd: &str) {
+pub fn huge_word(p: &mut Printer, wrd: &str) {
     p.pretty_print(STRING(/* bad */ wrd.to_managed(), size_infinity));
 }
 
-pub fn zero_word(p: @mut Printer, wrd: &str) {
+pub fn zero_word(p: &mut Printer, wrd: &str) {
     p.pretty_print(STRING(/* bad */ wrd.to_managed(), 0));
 }
 
-pub fn spaces(p: @mut Printer, n: uint) { break_offset(p, n, 0); }
+pub fn spaces(p: &mut Printer, n: uint) { break_offset(p, n, 0); }
 
-pub fn zerobreak(p: @mut Printer) { spaces(p, 0u); }
+pub fn zerobreak(p: &mut Printer) { spaces(p, 0u); }
 
-pub fn space(p: @mut Printer) { spaces(p, 1u); }
+pub fn space(p: &mut Printer) { spaces(p, 1u); }
 
-pub fn hardbreak(p: @mut Printer) { spaces(p, size_infinity as uint); }
+pub fn hardbreak(p: &mut Printer) { spaces(p, size_infinity as uint); }
 
 pub fn hardbreak_tok_offset(off: int) -> token {
     BREAK(break_t {offset: off, blank_space: size_infinity})
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index c13bae777c6..7cf47cc1fd4 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -33,12 +33,12 @@ use std::io;
 use std::io::Decorator;
 use std::io::mem::MemWriter;
 
-// The @ps is stored here to prevent recursive type.
-pub enum ann_node<'a> {
-    node_block(@ps, &'a ast::Block),
-    node_item(@ps, &'a ast::item),
-    node_expr(@ps, &'a ast::Expr),
-    node_pat(@ps, &'a ast::Pat),
+// The &mut ps is stored here to prevent recursive type.
+pub enum ann_node<'a,'b> {
+    node_block(&'b mut ps, &'a ast::Block),
+    node_item(&'b mut ps, &'a ast::item),
+    node_expr(&'b mut ps, &'a ast::Expr),
+    node_pat(&'b mut ps, &'a ast::Pat),
 }
 
 pub trait pp_ann {
@@ -66,7 +66,7 @@ pub struct CurrentCommentAndLiteral {
 }
 
 pub struct ps {
-    s: @mut pp::Printer,
+    s: pp::Printer,
     cm: Option<@CodeMap>,
     intr: @token::ident_interner,
     comments: Option<~[comments::cmnt]>,
@@ -76,25 +76,25 @@ pub struct ps {
     ann: @pp_ann
 }
 
-pub fn ibox(s: @ps, u: uint) {
+pub fn ibox(s: &mut ps, u: uint) {
     s.boxes.push(pp::inconsistent);
-    pp::ibox(s.s, u);
+    pp::ibox(&mut s.s, u);
 }
 
-pub fn end(s: @ps) {
+pub fn end(s: &mut ps) {
     s.boxes.pop();
-    pp::end(s.s);
+    pp::end(&mut s.s);
 }
 
-pub fn rust_printer(writer: @mut io::Writer, intr: @ident_interner) -> @ps {
+pub fn rust_printer(writer: @mut io::Writer, intr: @ident_interner) -> ps {
     return rust_printer_annotated(writer, intr, @no_ann::new() as @pp_ann);
 }
 
 pub fn rust_printer_annotated(writer: @mut io::Writer,
                               intr: @ident_interner,
                               ann: @pp_ann)
-                              -> @ps {
-    return @ps {
+                              -> ps {
+    return ps {
         s: pp::mk_printer(writer, default_columns),
         cm: None::<@CodeMap>,
         intr: intr,
@@ -130,7 +130,7 @@ pub fn print_crate(cm: @CodeMap,
         filename,
         input
     );
-    let s = @ps {
+    let mut s = ps {
         s: pp::mk_printer(out, default_columns),
         cm: Some(cm),
         intr: intr,
@@ -150,13 +150,13 @@ pub fn print_crate(cm: @CodeMap,
         boxes: @mut ~[],
         ann: ann
     };
-    print_crate_(s, crate);
+    print_crate_(&mut s, crate);
 }
 
-pub fn print_crate_(s: @ps, crate: &ast::Crate) {
+pub fn print_crate_(s: &mut ps, crate: &ast::Crate) {
     print_mod(s, &crate.module, crate.attrs);
     print_remaining_comments(s);
-    eof(s.s);
+    eof(&mut s.s);
 }
 
 pub fn ty_to_str(ty: &ast::Ty, intr: @ident_interner) -> ~str {
@@ -204,24 +204,24 @@ pub fn fun_to_str(decl: &ast::fn_decl, purity: ast::purity, name: ast::Ident,
                   opt_explicit_self: Option<ast::explicit_self_>,
                   generics: &ast::Generics, intr: @ident_interner) -> ~str {
     let wr = @mut MemWriter::new();
-    let s = rust_printer(wr as @mut io::Writer, intr);
-    print_fn(s, decl, Some(purity), AbiSet::Rust(),
+    let mut s = rust_printer(wr as @mut io::Writer, intr);
+    print_fn(&mut s, decl, Some(purity), AbiSet::Rust(),
              name, generics, opt_explicit_self, ast::inherited);
-    end(s); // Close the head box
-    end(s); // Close the outer box
-    eof(s.s);
+    end(&mut s); // Close the head box
+    end(&mut s); // Close the outer box
+    eof(&mut s.s);
     str::from_utf8_owned(wr.inner_ref().to_owned())
 }
 
 pub fn block_to_str(blk: &ast::Block, intr: @ident_interner) -> ~str {
     let wr = @mut MemWriter::new();
-    let s = rust_printer(wr as @mut io::Writer, intr);
+    let mut s = rust_printer(wr as @mut io::Writer, intr);
     // containing cbox, will be closed by print-block at }
-    cbox(s, indent_unit);
+    cbox(&mut s, indent_unit);
     // head-ibox, will be closed by print-block after {
-    ibox(s, 0u);
-    print_block(s, blk);
-    eof(s.s);
+    ibox(&mut s, 0u);
+    print_block(&mut s, blk);
+    eof(&mut s.s);
     str::from_utf8_owned(wr.inner_ref().to_owned())
 }
 
@@ -237,28 +237,28 @@ pub fn variant_to_str(var: &ast::variant, intr: @ident_interner) -> ~str {
     to_str(var, print_variant, intr)
 }
 
-pub fn cbox(s: @ps, u: uint) {
+pub fn cbox(s: &mut ps, u: uint) {
     s.boxes.push(pp::consistent);
-    pp::cbox(s.s, u);
+    pp::cbox(&mut s.s, u);
 }
 
 // "raw box"
-pub fn rbox(s: @ps, u: uint, b: pp::breaks) {
+pub fn rbox(s: &mut ps, u: uint, b: pp::breaks) {
     s.boxes.push(b);
-    pp::rbox(s.s, u, b);
+    pp::rbox(&mut s.s, u, b);
 }
 
-pub fn nbsp(s: @ps) { word(s.s, " "); }
+pub fn nbsp(s: &mut ps) { word(&mut s.s, " "); }
 
-pub fn word_nbsp(s: @ps, w: &str) { word(s.s, w); nbsp(s); }
+pub fn word_nbsp(s: &mut ps, w: &str) { word(&mut s.s, w); nbsp(s); }
 
-pub fn word_space(s: @ps, w: &str) { word(s.s, w); space(s.s); }
+pub fn word_space(s: &mut ps, w: &str) { word(&mut s.s, w); space(&mut s.s); }
 
-pub fn popen(s: @ps) { word(s.s, "("); }
+pub fn popen(s: &mut ps) { word(&mut s.s, "("); }
 
-pub fn pclose(s: @ps) { word(s.s, ")"); }
+pub fn pclose(s: &mut ps) { word(&mut s.s, ")"); }
 
-pub fn head(s: @ps, w: &str) {
+pub fn head(s: &mut ps, w: &str) {
     // outer-box is consistent
     cbox(s, indent_unit);
     // head-box is inconsistent
@@ -269,49 +269,53 @@ pub fn head(s: @ps, w: &str) {
     }
 }
 
-pub fn bopen(s: @ps) {
-    word(s.s, "{");
+pub fn bopen(s: &mut ps) {
+    word(&mut s.s, "{");
     end(s); // close the head-box
 }
 
-pub fn bclose_(s: @ps, span: codemap::Span, indented: uint) {
+pub fn bclose_(s: &mut ps, span: codemap::Span, indented: uint) {
     bclose_maybe_open(s, span, indented, true);
 }
-pub fn bclose_maybe_open (s: @ps, span: codemap::Span, indented: uint,
+pub fn bclose_maybe_open (s: &mut ps, span: codemap::Span, indented: uint,
                           close_box: bool) {
     maybe_print_comment(s, span.hi);
     break_offset_if_not_bol(s, 1u, -(indented as int));
-    word(s.s, "}");
+    word(&mut s.s, "}");
     if close_box {
         end(s); // close the outer-box
     }
 }
-pub fn bclose(s: @ps, span: codemap::Span) { bclose_(s, span, indent_unit); }
+pub fn bclose(s: &mut ps, span: codemap::Span) { bclose_(s, span, indent_unit); }
 
-pub fn is_begin(s: @ps) -> bool {
+pub fn is_begin(s: &mut ps) -> bool {
     match s.s.last_token() { pp::BEGIN(_) => true, _ => false }
 }
 
-pub fn is_end(s: @ps) -> bool {
+pub fn is_end(s: &mut ps) -> bool {
     match s.s.last_token() { pp::END => true, _ => false }
 }
 
-pub fn is_bol(s: @ps) -> bool {
+pub fn is_bol(s: &mut ps) -> bool {
     return s.s.last_token().is_eof() || s.s.last_token().is_hardbreak_tok();
 }
 
-pub fn in_cbox(s: @ps) -> bool {
+pub fn in_cbox(s: &mut ps) -> bool {
     let boxes = &*s.boxes;
     let len = boxes.len();
     if len == 0u { return false; }
     return boxes[len - 1u] == pp::consistent;
 }
 
-pub fn hardbreak_if_not_bol(s: @ps) { if !is_bol(s) { hardbreak(s.s); } }
-pub fn space_if_not_bol(s: @ps) { if !is_bol(s) { space(s.s); } }
-pub fn break_offset_if_not_bol(s: @ps, n: uint, off: int) {
+pub fn hardbreak_if_not_bol(s: &mut ps) {
     if !is_bol(s) {
-        break_offset(s.s, n, off);
+        hardbreak(&mut s.s)
+    }
+}
+pub fn space_if_not_bol(s: &mut ps) { if !is_bol(s) { space(&mut s.s); } }
+pub fn break_offset_if_not_bol(s: &mut ps, n: uint, off: int) {
+    if !is_bol(s) {
+        break_offset(&mut s.s, n, off);
     } else {
         if off != 0 && s.s.last_token().is_hardbreak_tok() {
             // We do something pretty sketchy here: tuck the nonzero
@@ -324,15 +328,15 @@ pub fn break_offset_if_not_bol(s: @ps, n: uint, off: int) {
 
 // Synthesizes a comment that was not textually present in the original source
 // file.
-pub fn synth_comment(s: @ps, text: ~str) {
-    word(s.s, "/*");
-    space(s.s);
-    word(s.s, text);
-    space(s.s);
-    word(s.s, "*/");
+pub fn synth_comment(s: &mut ps, text: ~str) {
+    word(&mut s.s, "/*");
+    space(&mut s.s);
+    word(&mut s.s, text);
+    space(&mut s.s);
+    word(&mut s.s, "*/");
 }
 
-pub fn commasep<T>(s: @ps, b: breaks, elts: &[T], op: |@ps, &T|) {
+pub fn commasep<T>(s: &mut ps, b: breaks, elts: &[T], op: |&mut ps, &T|) {
     rbox(s, 0u, b);
     let mut first = true;
     for elt in elts.iter() {
@@ -344,10 +348,10 @@ pub fn commasep<T>(s: @ps, b: breaks, elts: &[T], op: |@ps, &T|) {
 
 
 pub fn commasep_cmnt<T>(
-                     s: @ps,
+                     s: &mut ps,
                      b: breaks,
                      elts: &[T],
-                     op: |@ps, &T|,
+                     op: |&mut ps, &T|,
                      get_span: |&T| -> codemap::Span) {
     rbox(s, 0u, b);
     let len = elts.len();
@@ -357,7 +361,7 @@ pub fn commasep_cmnt<T>(
         op(s, elt);
         i += 1u;
         if i < len {
-            word(s.s, ",");
+            word(&mut s.s, ",");
             maybe_print_trailing_comment(s, get_span(elt),
                                          Some(get_span(&elts[i]).hi));
             space_if_not_bol(s);
@@ -366,11 +370,11 @@ pub fn commasep_cmnt<T>(
     end(s);
 }
 
-pub fn commasep_exprs(s: @ps, b: breaks, exprs: &[@ast::Expr]) {
+pub fn commasep_exprs(s: &mut ps, b: breaks, exprs: &[@ast::Expr]) {
     commasep_cmnt(s, b, exprs, |p, &e| print_expr(p, e), |e| e.span);
 }
 
-pub fn print_mod(s: @ps, _mod: &ast::_mod, attrs: &[ast::Attribute]) {
+pub fn print_mod(s: &mut ps, _mod: &ast::_mod, attrs: &[ast::Attribute]) {
     print_inner_attributes(s, attrs);
     for vitem in _mod.view_items.iter() {
         print_view_item(s, vitem);
@@ -378,7 +382,7 @@ pub fn print_mod(s: @ps, _mod: &ast::_mod, attrs: &[ast::Attribute]) {
     for item in _mod.items.iter() { print_item(s, *item); }
 }
 
-pub fn print_foreign_mod(s: @ps, nmod: &ast::foreign_mod,
+pub fn print_foreign_mod(s: &mut ps, nmod: &ast::foreign_mod,
                          attrs: &[ast::Attribute]) {
     print_inner_attributes(s, attrs);
     for vitem in nmod.view_items.iter() {
@@ -387,29 +391,29 @@ pub fn print_foreign_mod(s: @ps, nmod: &ast::foreign_mod,
     for item in nmod.items.iter() { print_foreign_item(s, *item); }
 }
 
-pub fn print_opt_lifetime(s: @ps, lifetime: &Option<ast::Lifetime>) {
+pub fn print_opt_lifetime(s: &mut ps, lifetime: &Option<ast::Lifetime>) {
     for l in lifetime.iter() {
         print_lifetime(s, l);
         nbsp(s);
     }
 }
 
-pub fn print_type(s: @ps, ty: &ast::Ty) {
+pub fn print_type(s: &mut ps, ty: &ast::Ty) {
     maybe_print_comment(s, ty.span.lo);
     ibox(s, 0u);
     match ty.node {
-      ast::ty_nil => word(s.s, "()"),
-      ast::ty_bot => word(s.s, "!"),
-      ast::ty_box(ref mt) => { word(s.s, "@"); print_mt(s, mt); }
-      ast::ty_uniq(ty) => { word(s.s, "~"); print_type(s, ty); }
+      ast::ty_nil => word(&mut s.s, "()"),
+      ast::ty_bot => word(&mut s.s, "!"),
+      ast::ty_box(ref mt) => { word(&mut s.s, "@"); print_mt(s, mt); }
+      ast::ty_uniq(ty) => { word(&mut s.s, "~"); print_type(s, ty); }
       ast::ty_vec(ty) => {
-        word(s.s, "[");
+        word(&mut s.s, "[");
         print_type(s, ty);
-        word(s.s, "]");
+        word(&mut s.s, "]");
       }
-      ast::ty_ptr(ref mt) => { word(s.s, "*"); print_mt(s, mt); }
+      ast::ty_ptr(ref mt) => { word(&mut s.s, "*"); print_mt(s, mt); }
       ast::ty_rptr(ref lifetime, ref mt) => {
-          word(s.s, "&");
+          word(&mut s.s, "&");
           print_opt_lifetime(s, lifetime);
           print_mt(s, mt);
       }
@@ -417,7 +421,7 @@ pub fn print_type(s: @ps, ty: &ast::Ty) {
         popen(s);
         commasep(s, inconsistent, *elts, print_type_ref);
         if elts.len() == 1 {
-            word(s.s, ",");
+            word(&mut s.s, ",");
         }
         pclose(s);
       }
@@ -441,16 +445,16 @@ pub fn print_type(s: @ps, ty: &ast::Ty) {
       }
       ast::ty_path(ref path, ref bounds, _) => print_bounded_path(s, path, bounds),
       ast::ty_fixed_length_vec(ty, v) => {
-        word(s.s, "[");
+        word(&mut s.s, "[");
         print_type(s, ty);
-        word(s.s, ", ..");
+        word(&mut s.s, ", ..");
         print_expr(s, v);
-        word(s.s, "]");
+        word(&mut s.s, "]");
       }
       ast::ty_typeof(e) => {
-          word(s.s, "typeof(");
+          word(&mut s.s, "typeof(");
           print_expr(s, e);
-          word(s.s, ")");
+          word(&mut s.s, ")");
       }
       ast::ty_infer => {
           fail!("print_type shouldn't see a ty_infer");
@@ -460,11 +464,11 @@ pub fn print_type(s: @ps, ty: &ast::Ty) {
     end(s);
 }
 
-pub fn print_type_ref(s: @ps, ty: &P<ast::Ty>) {
+pub fn print_type_ref(s: &mut ps, ty: &P<ast::Ty>) {
     print_type(s, *ty);
 }
 
-pub fn print_foreign_item(s: @ps, item: &ast::foreign_item) {
+pub fn print_foreign_item(s: &mut ps, item: &ast::foreign_item) {
     hardbreak_if_not_bol(s);
     maybe_print_comment(s, item.span.lo);
     print_outer_attributes(s, item.attrs);
@@ -473,7 +477,7 @@ pub fn print_foreign_item(s: @ps, item: &ast::foreign_item) {
         print_fn(s, decl, None, AbiSet::Rust(), item.ident, generics, None,
                  item.vis);
         end(s); // end head-ibox
-        word(s.s, ";");
+        word(&mut s.s, ";");
         end(s); // end the outer fn box
       }
       ast::foreign_item_static(t, m) => {
@@ -484,19 +488,21 @@ pub fn print_foreign_item(s: @ps, item: &ast::foreign_item) {
         print_ident(s, item.ident);
         word_space(s, ":");
         print_type(s, t);
-        word(s.s, ";");
+        word(&mut s.s, ";");
         end(s); // end the head-ibox
         end(s); // end the outer cbox
       }
     }
 }
 
-pub fn print_item(s: @ps, item: &ast::item) {
+pub fn print_item(s: &mut ps, item: &ast::item) {
     hardbreak_if_not_bol(s);
     maybe_print_comment(s, item.span.lo);
     print_outer_attributes(s, item.attrs);
-    let ann_node = node_item(s, item);
-    s.ann.pre(ann_node);
+    {
+        let ann_node = node_item(s, item);
+        s.ann.pre(ann_node);
+    }
     match item.node {
       ast::item_static(ty, m, expr) => {
         head(s, visibility_qualified(item.vis, "static"));
@@ -506,12 +512,12 @@ pub fn print_item(s: @ps, item: &ast::item) {
         print_ident(s, item.ident);
         word_space(s, ":");
         print_type(s, ty);
-        space(s.s);
+        space(&mut s.s);
         end(s); // end the head-ibox
 
         word_space(s, "=");
         print_expr(s, expr);
-        word(s.s, ";");
+        word(&mut s.s, ";");
         end(s); // end the outer cbox
 
       }
@@ -526,7 +532,7 @@ pub fn print_item(s: @ps, item: &ast::item) {
             None,
             item.vis
         );
-        word(s.s, " ");
+        word(&mut s.s, " ");
         print_block_with_attrs(s, body, item.attrs);
       }
       ast::item_mod(ref _mod) => {
@@ -552,10 +558,10 @@ pub fn print_item(s: @ps, item: &ast::item) {
         print_generics(s, params);
         end(s); // end the inner ibox
 
-        space(s.s);
+        space(&mut s.s);
         word_space(s, "=");
         print_type(s, ty);
-        word(s.s, ";");
+        word(&mut s.s, ";");
         end(s); // end the outer ibox
       }
       ast::item_enum(ref enum_definition, ref params) => {
@@ -577,13 +583,13 @@ pub fn print_item(s: @ps, item: &ast::item) {
         head(s, visibility_qualified(item.vis, "impl"));
         if generics.is_parameterized() {
             print_generics(s, generics);
-            space(s.s);
+            space(&mut s.s);
         }
 
         match opt_trait {
             &Some(ref t) => {
                 print_trait_ref(s, t);
-                space(s.s);
+                space(&mut s.s);
                 word_space(s, "for");
             }
             &None => ()
@@ -591,7 +597,7 @@ pub fn print_item(s: @ps, item: &ast::item) {
 
         print_type(s, ty);
 
-        space(s.s);
+        space(&mut s.s);
         bopen(s);
         print_inner_attributes(s, item.attrs);
         for meth in methods.iter() {
@@ -604,7 +610,7 @@ pub fn print_item(s: @ps, item: &ast::item) {
         print_ident(s, item.ident);
         print_generics(s, generics);
         if traits.len() != 0u {
-            word(s.s, ":");
+            word(&mut s.s, ":");
             for (i, trait_) in traits.iter().enumerate() {
                 nbsp(s);
                 if i != 0 {
@@ -613,7 +619,7 @@ pub fn print_item(s: @ps, item: &ast::item) {
                 print_path(s, &trait_.path, false);
             }
         }
-        word(s.s, " ");
+        word(&mut s.s, " ");
         bopen(s);
         for meth in methods.iter() {
             print_trait_method(s, meth);
@@ -625,7 +631,7 @@ pub fn print_item(s: @ps, item: &ast::item) {
                                    ..}) => {
         print_visibility(s, item.vis);
         print_path(s, pth, false);
-        word(s.s, "! ");
+        word(&mut s.s, "! ");
         print_ident(s, item.ident);
         cbox(s, indent_unit);
         popen(s);
@@ -634,24 +640,27 @@ pub fn print_item(s: @ps, item: &ast::item) {
         end(s);
       }
     }
-    s.ann.post(ann_node);
+    {
+        let ann_node = node_item(s, item);
+        s.ann.post(ann_node);
+    }
 }
 
-fn print_trait_ref(s: @ps, t: &ast::trait_ref) {
+fn print_trait_ref(s: &mut ps, t: &ast::trait_ref) {
     print_path(s, &t.path, false);
 }
 
-pub fn print_enum_def(s: @ps, enum_definition: &ast::enum_def,
+pub fn print_enum_def(s: &mut ps, enum_definition: &ast::enum_def,
                       generics: &ast::Generics, ident: ast::Ident,
                       span: codemap::Span, visibility: ast::visibility) {
     head(s, visibility_qualified(visibility, "enum"));
     print_ident(s, ident);
     print_generics(s, generics);
-    space(s.s);
+    space(&mut s.s);
     print_variants(s, enum_definition.variants, span);
 }
 
-pub fn print_variants(s: @ps,
+pub fn print_variants(s: &mut ps,
                       variants: &[P<ast::variant>],
                       span: codemap::Span) {
     bopen(s);
@@ -661,7 +670,7 @@ pub fn print_variants(s: @ps,
         print_outer_attributes(s, v.node.attrs);
         ibox(s, indent_unit);
         print_variant(s, v);
-        word(s.s, ",");
+        word(&mut s.s, ",");
         end(s);
         maybe_print_trailing_comment(s, v.span, None);
     }
@@ -683,7 +692,7 @@ pub fn visibility_qualified(vis: ast::visibility, s: &str) -> ~str {
     }
 }
 
-pub fn print_visibility(s: @ps, vis: ast::visibility) {
+pub fn print_visibility(s: &mut ps, vis: ast::visibility) {
     match vis {
         ast::private | ast::public =>
         word_nbsp(s, visibility_to_str(vis)),
@@ -691,7 +700,7 @@ pub fn print_visibility(s: @ps, vis: ast::visibility) {
     }
 }
 
-pub fn print_struct(s: @ps,
+pub fn print_struct(s: &mut ps,
                     struct_def: &ast::struct_def,
                     generics: &ast::Generics,
                     ident: ast::Ident,
@@ -712,7 +721,7 @@ pub fn print_struct(s: @ps,
             });
             pclose(s);
         }
-        word(s.s, ";");
+        word(&mut s.s, ";");
         end(s);
         end(s); // close the outer-box
     } else {
@@ -731,7 +740,7 @@ pub fn print_struct(s: @ps,
                     print_ident(s, ident);
                     word_nbsp(s, ":");
                     print_type(s, field.node.ty);
-                    word(s.s, ",");
+                    word(&mut s.s, ",");
                 }
             }
         }
@@ -747,48 +756,48 @@ pub fn print_struct(s: @ps,
 /// appropriate macro, transcribe back into the grammar we just parsed from,
 /// and then pretty-print the resulting AST nodes (so, e.g., we print
 /// expression arguments as expressions). It can be done! I think.
-pub fn print_tt(s: @ps, tt: &ast::token_tree) {
+pub fn print_tt(s: &mut ps, tt: &ast::token_tree) {
     match *tt {
       ast::tt_delim(ref tts) => print_tts(s, &(tts.as_slice())),
       ast::tt_tok(_, ref tk) => {
-          word(s.s, parse::token::to_str(s.intr, tk));
+          word(&mut s.s, parse::token::to_str(s.intr, tk));
       }
       ast::tt_seq(_, ref tts, ref sep, zerok) => {
-        word(s.s, "$(");
+        word(&mut s.s, "$(");
         for tt_elt in (*tts).iter() { print_tt(s, tt_elt); }
-        word(s.s, ")");
+        word(&mut s.s, ")");
         match (*sep) {
-          Some(ref tk) => word(s.s, parse::token::to_str(s.intr, tk)),
+          Some(ref tk) => word(&mut s.s, parse::token::to_str(s.intr, tk)),
           None => ()
         }
-        word(s.s, if zerok { "*" } else { "+" });
+        word(&mut s.s, if zerok { "*" } else { "+" });
       }
       ast::tt_nonterminal(_, name) => {
-        word(s.s, "$");
+        word(&mut s.s, "$");
         print_ident(s, name);
       }
     }
 }
 
-pub fn print_tts(s: @ps, tts: & &[ast::token_tree]) {
+pub fn print_tts(s: &mut ps, tts: & &[ast::token_tree]) {
     ibox(s, 0);
     for (i, tt) in tts.iter().enumerate() {
         if i != 0 {
-            space(s.s);
+            space(&mut s.s);
         }
         print_tt(s, tt);
     }
     end(s);
 }
 
-pub fn print_variant(s: @ps, v: &ast::variant) {
+pub fn print_variant(s: &mut ps, v: &ast::variant) {
     print_visibility(s, v.node.vis);
     match v.node.kind {
         ast::tuple_variant_kind(ref args) => {
             print_ident(s, v.node.name);
             if !args.is_empty() {
                 popen(s);
-                fn print_variant_arg(s: @ps, arg: &ast::variant_arg) {
+                fn print_variant_arg(s: &mut ps, arg: &ast::variant_arg) {
                     print_type(s, arg.ty);
                 }
                 commasep(s, consistent, *args, print_variant_arg);
@@ -803,7 +812,7 @@ pub fn print_variant(s: @ps, v: &ast::variant) {
     }
     match v.node.disr_expr {
       Some(d) => {
-        space(s.s);
+        space(&mut s.s);
         word_space(s, "=");
         print_expr(s, d);
       }
@@ -811,7 +820,7 @@ pub fn print_variant(s: @ps, v: &ast::variant) {
     }
 }
 
-pub fn print_ty_method(s: @ps, m: &ast::TypeMethod) {
+pub fn print_ty_method(s: &mut ps, m: &ast::TypeMethod) {
     hardbreak_if_not_bol(s);
     maybe_print_comment(s, m.span.lo);
     print_outer_attributes(s, m.attrs);
@@ -826,28 +835,28 @@ pub fn print_ty_method(s: @ps, m: &ast::TypeMethod) {
                 &None,
                 Some(&m.generics),
                 Some(m.explicit_self.node));
-    word(s.s, ";");
+    word(&mut s.s, ";");
 }
 
-pub fn print_trait_method(s: @ps, m: &ast::trait_method) {
+pub fn print_trait_method(s: &mut ps, m: &ast::trait_method) {
     match *m {
         required(ref ty_m) => print_ty_method(s, ty_m),
         provided(m) => print_method(s, m)
     }
 }
 
-pub fn print_method(s: @ps, meth: &ast::method) {
+pub fn print_method(s: &mut ps, meth: &ast::method) {
     hardbreak_if_not_bol(s);
     maybe_print_comment(s, meth.span.lo);
     print_outer_attributes(s, meth.attrs);
     print_fn(s, meth.decl, Some(meth.purity), AbiSet::Rust(),
              meth.ident, &meth.generics, Some(meth.explicit_self.node),
              meth.vis);
-    word(s.s, " ");
+    word(&mut s.s, " ");
     print_block_with_attrs(s, meth.body, meth.attrs);
 }
 
-pub fn print_outer_attributes(s: @ps, attrs: &[ast::Attribute]) {
+pub fn print_outer_attributes(s: &mut ps, attrs: &[ast::Attribute]) {
     let mut count = 0;
     for attr in attrs.iter() {
         match attr.node.style {
@@ -858,14 +867,14 @@ pub fn print_outer_attributes(s: @ps, attrs: &[ast::Attribute]) {
     if count > 0 { hardbreak_if_not_bol(s); }
 }
 
-pub fn print_inner_attributes(s: @ps, attrs: &[ast::Attribute]) {
+pub fn print_inner_attributes(s: &mut ps, attrs: &[ast::Attribute]) {
     let mut count = 0;
     for attr in attrs.iter() {
         match attr.node.style {
           ast::AttrInner => {
             print_attribute(s, attr);
             if !attr.node.is_sugared_doc {
-                word(s.s, ";");
+                word(&mut s.s, ";");
             }
             count += 1;
           }
@@ -875,21 +884,21 @@ pub fn print_inner_attributes(s: @ps, attrs: &[ast::Attribute]) {
     if count > 0 { hardbreak_if_not_bol(s); }
 }
 
-pub fn print_attribute(s: @ps, attr: &ast::Attribute) {
+pub fn print_attribute(s: &mut ps, attr: &ast::Attribute) {
     hardbreak_if_not_bol(s);
     maybe_print_comment(s, attr.span.lo);
     if attr.node.is_sugared_doc {
         let comment = attr.value_str().unwrap();
-        word(s.s, comment);
+        word(&mut s.s, comment);
     } else {
-        word(s.s, "#[");
+        word(&mut s.s, "#[");
         print_meta_item(s, attr.meta());
-        word(s.s, "]");
+        word(&mut s.s, "]");
     }
 }
 
 
-pub fn print_stmt(s: @ps, st: &ast::Stmt) {
+pub fn print_stmt(s: &mut ps, st: &ast::Stmt) {
     maybe_print_comment(s, st.span.lo);
     match st.node {
       ast::StmtDecl(decl, _) => {
@@ -902,33 +911,33 @@ pub fn print_stmt(s: @ps, st: &ast::Stmt) {
       ast::StmtSemi(expr, _) => {
         space_if_not_bol(s);
         print_expr(s, expr);
-        word(s.s, ";");
+        word(&mut s.s, ";");
       }
       ast::StmtMac(ref mac, semi) => {
         space_if_not_bol(s);
         print_mac(s, mac);
-        if semi { word(s.s, ";"); }
+        if semi { word(&mut s.s, ";"); }
       }
     }
-    if parse::classify::stmt_ends_with_semi(st) { word(s.s, ";"); }
+    if parse::classify::stmt_ends_with_semi(st) { word(&mut s.s, ";"); }
     maybe_print_trailing_comment(s, st.span, None);
 }
 
-pub fn print_block(s: @ps, blk: &ast::Block) {
+pub fn print_block(s: &mut ps, blk: &ast::Block) {
     print_possibly_embedded_block(s, blk, block_normal, indent_unit);
 }
 
-pub fn print_block_unclosed(s: @ps, blk: &ast::Block) {
+pub fn print_block_unclosed(s: &mut ps, blk: &ast::Block) {
     print_possibly_embedded_block_(s, blk, block_normal, indent_unit, &[],
                                  false);
 }
 
-pub fn print_block_unclosed_indent(s: @ps, blk: &ast::Block, indented: uint) {
+pub fn print_block_unclosed_indent(s: &mut ps, blk: &ast::Block, indented: uint) {
     print_possibly_embedded_block_(s, blk, block_normal, indented, &[],
                                    false);
 }
 
-pub fn print_block_with_attrs(s: @ps,
+pub fn print_block_with_attrs(s: &mut ps,
                               blk: &ast::Block,
                               attrs: &[ast::Attribute]) {
     print_possibly_embedded_block_(s, blk, block_normal, indent_unit, attrs,
@@ -937,7 +946,7 @@ pub fn print_block_with_attrs(s: @ps,
 
 pub enum embed_type { block_block_fn, block_normal, }
 
-pub fn print_possibly_embedded_block(s: @ps,
+pub fn print_possibly_embedded_block(s: &mut ps,
                                      blk: &ast::Block,
                                      embedded: embed_type,
                                      indented: uint) {
@@ -945,7 +954,7 @@ pub fn print_possibly_embedded_block(s: @ps,
         s, blk, embedded, indented, &[], true);
 }
 
-pub fn print_possibly_embedded_block_(s: @ps,
+pub fn print_possibly_embedded_block_(s: &mut ps,
                                       blk: &ast::Block,
                                       embedded: embed_type,
                                       indented: uint,
@@ -956,8 +965,10 @@ pub fn print_possibly_embedded_block_(s: @ps,
       ast::DefaultBlock => ()
     }
     maybe_print_comment(s, blk.span.lo);
-    let ann_node = node_block(s, blk);
-    s.ann.pre(ann_node);
+    {
+        let ann_node = node_block(s, blk);
+        s.ann.pre(ann_node);
+    }
     match embedded {
       block_block_fn => end(s),
       block_normal => bopen(s)
@@ -978,17 +989,20 @@ pub fn print_possibly_embedded_block_(s: @ps,
       _ => ()
     }
     bclose_maybe_open(s, blk.span, indented, close_box);
-    s.ann.post(ann_node);
+    {
+        let ann_node = node_block(s, blk);
+        s.ann.post(ann_node);
+    }
 }
 
-pub fn print_if(s: @ps, test: &ast::Expr, blk: &ast::Block,
+pub fn print_if(s: &mut ps, test: &ast::Expr, blk: &ast::Block,
                 elseopt: Option<@ast::Expr>, chk: bool) {
     head(s, "if");
     if chk { word_nbsp(s, "check"); }
     print_expr(s, test);
-    space(s.s);
+    space(&mut s.s);
     print_block(s, blk);
-    fn do_else(s: @ps, els: Option<@ast::Expr>) {
+    fn do_else(s: &mut ps, els: Option<@ast::Expr>) {
         match els {
           Some(_else) => {
             match _else.node {
@@ -996,9 +1010,9 @@ pub fn print_if(s: @ps, test: &ast::Expr, blk: &ast::Block,
               ast::ExprIf(i, t, e) => {
                 cbox(s, indent_unit - 1u);
                 ibox(s, 0u);
-                word(s.s, " else if ");
+                word(&mut s.s, " else if ");
                 print_expr(s, i);
-                space(s.s);
+                space(&mut s.s);
                 print_block(s, t);
                 do_else(s, e);
               }
@@ -1006,7 +1020,7 @@ pub fn print_if(s: @ps, test: &ast::Expr, blk: &ast::Block,
               ast::ExprBlock(b) => {
                 cbox(s, indent_unit - 1u);
                 ibox(s, 0u);
-                word(s.s, " else ");
+                word(&mut s.s, " else ");
                 print_block(s, b);
               }
               // BLEAH, constraints would be great here
@@ -1021,12 +1035,12 @@ pub fn print_if(s: @ps, test: &ast::Expr, blk: &ast::Block,
     do_else(s, elseopt);
 }
 
-pub fn print_mac(s: @ps, m: &ast::mac) {
+pub fn print_mac(s: &mut ps, m: &ast::mac) {
     match m.node {
       // I think it's reasonable to hide the ctxt here:
       ast::mac_invoc_tt(ref pth, ref tts, _) => {
         print_path(s, pth, false);
-        word(s.s, "!");
+        word(&mut s.s, "!");
         popen(s);
         print_tts(s, &tts.as_slice());
         pclose(s);
@@ -1034,36 +1048,36 @@ pub fn print_mac(s: @ps, m: &ast::mac) {
     }
 }
 
-pub fn print_vstore(s: @ps, t: ast::Vstore) {
+pub fn print_vstore(s: &mut ps, t: ast::Vstore) {
     match t {
-        ast::VstoreFixed(Some(i)) => word(s.s, format!("{}", i)),
-        ast::VstoreFixed(None) => word(s.s, "_"),
-        ast::VstoreUniq => word(s.s, "~"),
-        ast::VstoreBox => word(s.s, "@"),
+        ast::VstoreFixed(Some(i)) => word(&mut s.s, format!("{}", i)),
+        ast::VstoreFixed(None) => word(&mut s.s, "_"),
+        ast::VstoreUniq => word(&mut s.s, "~"),
+        ast::VstoreBox => word(&mut s.s, "@"),
         ast::VstoreSlice(ref r) => {
-            word(s.s, "&");
+            word(&mut s.s, "&");
             print_opt_lifetime(s, r);
         }
     }
 }
 
-pub fn print_expr_vstore(s: @ps, t: ast::ExprVstore) {
+pub fn print_expr_vstore(s: &mut ps, t: ast::ExprVstore) {
     match t {
-      ast::ExprVstoreUniq => word(s.s, "~"),
-      ast::ExprVstoreBox => word(s.s, "@"),
+      ast::ExprVstoreUniq => word(&mut s.s, "~"),
+      ast::ExprVstoreBox => word(&mut s.s, "@"),
       ast::ExprVstoreMutBox => {
-        word(s.s, "@");
-        word(s.s, "mut");
+        word(&mut s.s, "@");
+        word(&mut s.s, "mut");
       }
-      ast::ExprVstoreSlice => word(s.s, "&"),
+      ast::ExprVstoreSlice => word(&mut s.s, "&"),
       ast::ExprVstoreMutSlice => {
-        word(s.s, "&");
-        word(s.s, "mut");
+        word(&mut s.s, "&");
+        word(&mut s.s, "mut");
       }
     }
 }
 
-pub fn print_call_pre(s: @ps,
+pub fn print_call_pre(s: &mut ps,
                       sugar: ast::CallSugar,
                       base_args: &mut ~[@ast::Expr])
                    -> Option<@ast::Expr> {
@@ -1080,7 +1094,7 @@ pub fn print_call_pre(s: @ps,
     }
 }
 
-pub fn print_call_post(s: @ps,
+pub fn print_call_post(s: &mut ps,
                        sugar: ast::CallSugar,
                        blk: &Option<@ast::Expr>,
                        base_args: &mut ~[@ast::Expr]) {
@@ -1107,8 +1121,8 @@ pub fn print_call_post(s: @ps,
     }
 }
 
-pub fn print_expr(s: @ps, expr: &ast::Expr) {
-    fn print_field(s: @ps, field: &ast::Field) {
+pub fn print_expr(s: &mut ps, expr: &ast::Expr) {
+    fn print_field(s: &mut ps, field: &ast::Field) {
         ibox(s, indent_unit);
         print_ident(s, field.ident.node);
         word_space(s, ":");
@@ -1119,8 +1133,10 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
 
     maybe_print_comment(s, expr.span.lo);
     ibox(s, indent_unit);
-    let ann_node = node_expr(s, expr);
-    s.ann.pre(ann_node);
+    {
+        let ann_node = node_expr(s, expr);
+        s.ann.pre(ann_node);
+    }
     match expr.node {
         ast::ExprVstore(e, v) => {
             print_expr_vstore(s, v);
@@ -1128,53 +1144,53 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
         },
       ast::ExprVec(ref exprs, mutbl) => {
         ibox(s, indent_unit);
-        word(s.s, "[");
+        word(&mut s.s, "[");
         if mutbl == ast::MutMutable {
-            word(s.s, "mut");
+            word(&mut s.s, "mut");
             if exprs.len() > 0u { nbsp(s); }
         }
         commasep_exprs(s, inconsistent, *exprs);
-        word(s.s, "]");
+        word(&mut s.s, "]");
         end(s);
       }
 
       ast::ExprRepeat(element, count, mutbl) => {
         ibox(s, indent_unit);
-        word(s.s, "[");
+        word(&mut s.s, "[");
         if mutbl == ast::MutMutable {
-            word(s.s, "mut");
+            word(&mut s.s, "mut");
             nbsp(s);
         }
         print_expr(s, element);
-        word(s.s, ",");
-        word(s.s, "..");
+        word(&mut s.s, ",");
+        word(&mut s.s, "..");
         print_expr(s, count);
-        word(s.s, "]");
+        word(&mut s.s, "]");
         end(s);
       }
 
       ast::ExprStruct(ref path, ref fields, wth) => {
         print_path(s, path, true);
-        word(s.s, "{");
+        word(&mut s.s, "{");
         commasep_cmnt(s, consistent, (*fields), print_field, get_span);
         match wth {
             Some(expr) => {
                 ibox(s, indent_unit);
-                word(s.s, ",");
-                space(s.s);
-                word(s.s, "..");
+                word(&mut s.s, ",");
+                space(&mut s.s);
+                word(&mut s.s, "..");
                 print_expr(s, expr);
                 end(s);
             }
-            _ => (word(s.s, ","))
+            _ => (word(&mut s.s, ","))
         }
-        word(s.s, "}");
+        word(&mut s.s, "}");
       }
       ast::ExprTup(ref exprs) => {
         popen(s);
         commasep_exprs(s, inconsistent, *exprs);
         if exprs.len() == 1 {
-            word(s.s, ",");
+            word(&mut s.s, ",");
         }
         pclose(s);
       }
@@ -1188,31 +1204,31 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
         let mut base_args = (*args).clone();
         let blk = print_call_pre(s, sugar, &mut base_args);
         print_expr(s, func);
-        word(s.s, ".");
+        word(&mut s.s, ".");
         print_ident(s, ident);
         if tys.len() > 0u {
-            word(s.s, "::<");
+            word(&mut s.s, "::<");
             commasep(s, inconsistent, *tys, print_type_ref);
-            word(s.s, ">");
+            word(&mut s.s, ">");
         }
         print_call_post(s, sugar, &blk, &mut base_args);
       }
       ast::ExprBinary(_, op, lhs, rhs) => {
         print_expr(s, lhs);
-        space(s.s);
+        space(&mut s.s);
         word_space(s, ast_util::binop_to_str(op));
         print_expr(s, rhs);
       }
       ast::ExprUnary(_, op, expr) => {
-        word(s.s, ast_util::unop_to_str(op));
+        word(&mut s.s, ast_util::unop_to_str(op));
         print_expr(s, expr);
       }
       ast::ExprAddrOf(m, expr) => {
-        word(s.s, "&");
+        word(&mut s.s, "&");
         print_mutability(s, m);
         // Avoid `& &e` => `&&e`.
         match (m, &expr.node) {
-            (ast::MutImmutable, &ast::ExprAddrOf(..)) => space(s.s),
+            (ast::MutImmutable, &ast::ExprAddrOf(..)) => space(&mut s.s),
             _ => { }
         }
         print_expr(s, expr);
@@ -1220,7 +1236,7 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
       ast::ExprLit(lit) => print_literal(s, lit),
       ast::ExprCast(expr, ty) => {
         print_expr(s, expr);
-        space(s.s);
+        space(&mut s.s);
         word_space(s, "as");
         print_type(s, ty);
       }
@@ -1230,31 +1246,31 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
       ast::ExprWhile(test, blk) => {
         head(s, "while");
         print_expr(s, test);
-        space(s.s);
+        space(&mut s.s);
         print_block(s, blk);
       }
       ast::ExprForLoop(pat, iter, blk, opt_ident) => {
         for ident in opt_ident.iter() {
-            word(s.s, "'");
+            word(&mut s.s, "'");
             print_ident(s, *ident);
             word_space(s, ":");
         }
         head(s, "for");
         print_pat(s, pat);
-        space(s.s);
+        space(&mut s.s);
         word_space(s, "in");
         print_expr(s, iter);
-        space(s.s);
+        space(&mut s.s);
         print_block(s, blk);
       }
       ast::ExprLoop(blk, opt_ident) => {
         for ident in opt_ident.iter() {
-            word(s.s, "'");
+            word(&mut s.s, "'");
             print_ident(s, *ident);
             word_space(s, ":");
         }
         head(s, "loop");
-        space(s.s);
+        space(&mut s.s);
         print_block(s, blk);
       }
       ast::ExprMatch(expr, ref arms) => {
@@ -1262,26 +1278,26 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
         ibox(s, 4);
         word_nbsp(s, "match");
         print_expr(s, expr);
-        space(s.s);
+        space(&mut s.s);
         bopen(s);
         let len = arms.len();
         for (i, arm) in arms.iter().enumerate() {
-            space(s.s);
+            space(&mut s.s);
             cbox(s, indent_unit);
             ibox(s, 0u);
             let mut first = true;
             for p in arm.pats.iter() {
                 if first {
                     first = false;
-                } else { space(s.s); word_space(s, "|"); }
+                } else { space(&mut s.s); word_space(s, "|"); }
                 print_pat(s, *p);
             }
-            space(s.s);
+            space(&mut s.s);
             match arm.guard {
               Some(e) => {
                 word_space(s, "if");
                 print_expr(s, e);
-                space(s.s);
+                space(&mut s.s);
               }
               None => ()
             }
@@ -1309,7 +1325,7 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
                         }
                         if !expr_is_simple_block(expr)
                             && i < len - 1 {
-                            word(s.s, ",");
+                            word(&mut s.s, ",");
                         }
                         end(s); // close enclosing cbox
                     }
@@ -1329,7 +1345,7 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
         //
         // if !decl.inputs.is_empty() {
         print_fn_block_args(s, decl);
-        space(s.s);
+        space(&mut s.s);
         // }
         assert!(body.stmts.is_empty());
         assert!(body.expr.is_some());
@@ -1356,7 +1372,7 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
         //
         // if !decl.inputs.is_empty() {
         print_proc_args(s, decl);
-        space(s.s);
+        space(&mut s.s);
         // }
         assert!(body.stmts.is_empty());
         assert!(body.expr.is_some());
@@ -1388,70 +1404,70 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
       }
       ast::ExprAssign(lhs, rhs) => {
         print_expr(s, lhs);
-        space(s.s);
+        space(&mut s.s);
         word_space(s, "=");
         print_expr(s, rhs);
       }
       ast::ExprAssignOp(_, op, lhs, rhs) => {
         print_expr(s, lhs);
-        space(s.s);
-        word(s.s, ast_util::binop_to_str(op));
+        space(&mut s.s);
+        word(&mut s.s, ast_util::binop_to_str(op));
         word_space(s, "=");
         print_expr(s, rhs);
       }
       ast::ExprField(expr, id, ref tys) => {
         print_expr(s, expr);
-        word(s.s, ".");
+        word(&mut s.s, ".");
         print_ident(s, id);
         if tys.len() > 0u {
-            word(s.s, "::<");
+            word(&mut s.s, "::<");
             commasep(s, inconsistent, *tys, print_type_ref);
-            word(s.s, ">");
+            word(&mut s.s, ">");
         }
       }
       ast::ExprIndex(_, expr, index) => {
         print_expr(s, expr);
-        word(s.s, "[");
+        word(&mut s.s, "[");
         print_expr(s, index);
-        word(s.s, "]");
+        word(&mut s.s, "]");
       }
       ast::ExprPath(ref path) => print_path(s, path, true),
-      ast::ExprSelf => word(s.s, "self"),
+      ast::ExprSelf => word(&mut s.s, "self"),
       ast::ExprBreak(opt_ident) => {
-        word(s.s, "break");
-        space(s.s);
+        word(&mut s.s, "break");
+        space(&mut s.s);
         for ident in opt_ident.iter() {
-            word(s.s, "'");
+            word(&mut s.s, "'");
             print_name(s, *ident);
-            space(s.s);
+            space(&mut s.s);
         }
       }
       ast::ExprAgain(opt_ident) => {
-        word(s.s, "continue");
-        space(s.s);
+        word(&mut s.s, "continue");
+        space(&mut s.s);
         for ident in opt_ident.iter() {
-            word(s.s, "'");
+            word(&mut s.s, "'");
             print_name(s, *ident);
-            space(s.s)
+            space(&mut s.s)
         }
       }
       ast::ExprRet(result) => {
-        word(s.s, "return");
+        word(&mut s.s, "return");
         match result {
-          Some(expr) => { word(s.s, " "); print_expr(s, expr); }
+          Some(expr) => { word(&mut s.s, " "); print_expr(s, expr); }
           _ => ()
         }
       }
       ast::ExprLogLevel => {
-        word(s.s, "__log_level");
+        word(&mut s.s, "__log_level");
         popen(s);
         pclose(s);
       }
       ast::ExprInlineAsm(ref a) => {
         if a.volatile {
-            word(s.s, "__volatile__ asm!");
+            word(&mut s.s, "__volatile__ asm!");
         } else {
-            word(s.s, "asm!");
+            word(&mut s.s, "asm!");
         }
         popen(s);
         print_string(s, a.asm, a.asm_str_style);
@@ -1482,11 +1498,14 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
           pclose(s);
       }
     }
-    s.ann.post(ann_node);
+    {
+        let ann_node = node_expr(s, expr);
+        s.ann.post(ann_node);
+    }
     end(s);
 }
 
-pub fn print_local_decl(s: @ps, loc: &ast::Local) {
+pub fn print_local_decl(s: &mut ps, loc: &ast::Local) {
     print_pat(s, loc.pat);
     match loc.ty.node {
       ast::ty_infer => (),
@@ -1494,7 +1513,7 @@ pub fn print_local_decl(s: @ps, loc: &ast::Local) {
     }
 }
 
-pub fn print_decl(s: @ps, decl: &ast::Decl) {
+pub fn print_decl(s: &mut ps, decl: &ast::Decl) {
     maybe_print_comment(s, decl.span.lo);
     match decl.node {
       ast::DeclLocal(ref loc) => {
@@ -1502,7 +1521,7 @@ pub fn print_decl(s: @ps, decl: &ast::Decl) {
         ibox(s, indent_unit);
         word_nbsp(s, "let");
 
-        fn print_local(s: @ps, loc: &ast::Local) {
+        fn print_local(s: &mut ps, loc: &ast::Local) {
             ibox(s, indent_unit);
             print_local_decl(s, loc);
             end(s);
@@ -1523,28 +1542,28 @@ pub fn print_decl(s: @ps, decl: &ast::Decl) {
     }
 }
 
-pub fn print_ident(s: @ps, ident: ast::Ident) {
-    word(s.s, ident_to_str(&ident));
+pub fn print_ident(s: &mut ps, ident: ast::Ident) {
+    word(&mut s.s, ident_to_str(&ident));
 }
 
-pub fn print_name(s: @ps, name: ast::Name) {
-    word(s.s, interner_get(name));
+pub fn print_name(s: &mut ps, name: ast::Name) {
+    word(&mut s.s, interner_get(name));
 }
 
-pub fn print_for_decl(s: @ps, loc: &ast::Local, coll: &ast::Expr) {
+pub fn print_for_decl(s: &mut ps, loc: &ast::Local, coll: &ast::Expr) {
     print_local_decl(s, loc);
-    space(s.s);
+    space(&mut s.s);
     word_space(s, "in");
     print_expr(s, coll);
 }
 
-fn print_path_(s: @ps,
+fn print_path_(s: &mut ps,
                path: &ast::Path,
                colons_before_params: bool,
                opt_bounds: &Option<OptVec<ast::TyParamBound>>) {
     maybe_print_comment(s, path.span.lo);
     if path.global {
-        word(s.s, "::");
+        word(&mut s.s, "::");
     }
 
     let mut first = true;
@@ -1552,7 +1571,7 @@ fn print_path_(s: @ps,
         if first {
             first = false
         } else {
-            word(s.s, "::")
+            word(&mut s.s, "::")
         }
 
         print_ident(s, segment.identifier);
@@ -1567,9 +1586,9 @@ fn print_path_(s: @ps,
 
         if !segment.lifetimes.is_empty() || !segment.types.is_empty() {
             if colons_before_params {
-                word(s.s, "::")
+                word(&mut s.s, "::")
             }
-            word(s.s, "<");
+            word(&mut s.s, "<");
 
             let mut comma = false;
             for lifetime in segment.lifetimes.iter() {
@@ -1590,29 +1609,31 @@ fn print_path_(s: @ps,
                          print_type_ref);
             }
 
-            word(s.s, ">")
+            word(&mut s.s, ">")
         }
     }
 }
 
-pub fn print_path(s: @ps, path: &ast::Path, colons_before_params: bool) {
+pub fn print_path(s: &mut ps, path: &ast::Path, colons_before_params: bool) {
     print_path_(s, path, colons_before_params, &None)
 }
 
-pub fn print_bounded_path(s: @ps, path: &ast::Path,
+pub fn print_bounded_path(s: &mut ps, path: &ast::Path,
                           bounds: &Option<OptVec<ast::TyParamBound>>) {
     print_path_(s, path, false, bounds)
 }
 
-pub fn print_pat(s: @ps, pat: &ast::Pat) {
+pub fn print_pat(s: &mut ps, pat: &ast::Pat) {
     maybe_print_comment(s, pat.span.lo);
-    let ann_node = node_pat(s, pat);
-    s.ann.pre(ann_node);
+    {
+        let ann_node = node_pat(s, pat);
+        s.ann.pre(ann_node);
+    }
     /* Pat isn't normalized, but the beauty of it
      is that it doesn't matter */
     match pat.node {
-      ast::PatWild => word(s.s, "_"),
-      ast::PatWildMulti => word(s.s, ".."),
+      ast::PatWild => word(&mut s.s, "_"),
+      ast::PatWildMulti => word(&mut s.s, ".."),
       ast::PatIdent(binding_mode, ref path, sub) => {
           match binding_mode {
               ast::BindByRef(mutbl) => {
@@ -1627,7 +1648,7 @@ pub fn print_pat(s: @ps, pat: &ast::Pat) {
           print_path(s, path, true);
           match sub {
               Some(p) => {
-                  word(s.s, "@");
+                  word(&mut s.s, "@");
                   print_pat(s, p);
               }
               None => ()
@@ -1636,7 +1657,7 @@ pub fn print_pat(s: @ps, pat: &ast::Pat) {
       ast::PatEnum(ref path, ref args_) => {
         print_path(s, path, true);
         match *args_ {
-          None => word(s.s, "(..)"),
+          None => word(&mut s.s, "(..)"),
           Some(ref args) => {
             if !args.is_empty() {
               popen(s);
@@ -1649,8 +1670,8 @@ pub fn print_pat(s: @ps, pat: &ast::Pat) {
       }
       ast::PatStruct(ref path, ref fields, etc) => {
         print_path(s, path, true);
-        word(s.s, "{");
-        fn print_field(s: @ps, f: &ast::FieldPat) {
+        word(&mut s.s, "{");
+        fn print_field(s: &mut ps, f: &ast::FieldPat) {
             cbox(s, indent_unit);
             print_ident(s, f.ident);
             word_space(s, ":");
@@ -1663,39 +1684,39 @@ pub fn print_pat(s: @ps, pat: &ast::Pat) {
                       get_span);
         if etc {
             if fields.len() != 0u { word_space(s, ","); }
-            word(s.s, "..");
+            word(&mut s.s, "..");
         }
-        word(s.s, "}");
+        word(&mut s.s, "}");
       }
       ast::PatTup(ref elts) => {
         popen(s);
         commasep(s, inconsistent, *elts, |s, &p| print_pat(s, p));
         if elts.len() == 1 {
-            word(s.s, ",");
+            word(&mut s.s, ",");
         }
         pclose(s);
       }
       ast::PatBox(inner) => {
-          word(s.s, "@");
+          word(&mut s.s, "@");
           print_pat(s, inner);
       }
       ast::PatUniq(inner) => {
-          word(s.s, "~");
+          word(&mut s.s, "~");
           print_pat(s, inner);
       }
       ast::PatRegion(inner) => {
-          word(s.s, "&");
+          word(&mut s.s, "&");
           print_pat(s, inner);
       }
       ast::PatLit(e) => print_expr(s, e),
       ast::PatRange(begin, end) => {
         print_expr(s, begin);
-        space(s.s);
-        word(s.s, "..");
+        space(&mut s.s);
+        word(&mut s.s, "..");
         print_expr(s, end);
       }
       ast::PatVec(ref before, slice, ref after) => {
-        word(s.s, "[");
+        word(&mut s.s, "[");
         commasep(s, inconsistent, *before, |s, &p| print_pat(s, p));
         for &p in slice.iter() {
             if !before.is_empty() { word_space(s, ","); }
@@ -1703,16 +1724,19 @@ pub fn print_pat(s: @ps, pat: &ast::Pat) {
                 @ast::Pat { node: ast::PatWildMulti, .. } => {
                     // this case is handled by print_pat
                 }
-                _ => word(s.s, ".."),
+                _ => word(&mut s.s, ".."),
             }
             print_pat(s, p);
             if !after.is_empty() { word_space(s, ","); }
         }
         commasep(s, inconsistent, *after, |s, &p| print_pat(s, p));
-        word(s.s, "]");
+        word(&mut s.s, "]");
       }
     }
-    s.ann.post(ann_node);
+    {
+        let ann_node = node_pat(s, pat);
+        s.ann.post(ann_node);
+    }
 }
 
 pub fn explicit_self_to_str(explicit_self: &ast::explicit_self_, intr: @ident_interner) -> ~str {
@@ -1720,31 +1744,31 @@ pub fn explicit_self_to_str(explicit_self: &ast::explicit_self_, intr: @ident_in
 }
 
 // Returns whether it printed anything
-pub fn print_explicit_self(s: @ps, explicit_self: ast::explicit_self_) -> bool {
+pub fn print_explicit_self(s: &mut ps, explicit_self: ast::explicit_self_) -> bool {
     match explicit_self {
         ast::sty_static => { return false; }
         ast::sty_value(m) => {
             print_mutability(s, m);
-            word(s.s, "self");
+            word(&mut s.s, "self");
         }
         ast::sty_uniq(m) => {
             print_mutability(s, m);
-            word(s.s, "~self");
+            word(&mut s.s, "~self");
         }
         ast::sty_region(ref lt, m) => {
-            word(s.s, "&");
+            word(&mut s.s, "&");
             print_opt_lifetime(s, lt);
             print_mutability(s, m);
-            word(s.s, "self");
+            word(&mut s.s, "self");
         }
         ast::sty_box(m) => {
-            word(s.s, "@"); print_mutability(s, m); word(s.s, "self");
+            word(&mut s.s, "@"); print_mutability(s, m); word(&mut s.s, "self");
         }
     }
     return true;
 }
 
-pub fn print_fn(s: @ps,
+pub fn print_fn(s: &mut ps,
                 decl: &ast::fn_decl,
                 purity: Option<ast::purity>,
                 abis: AbiSet,
@@ -1760,7 +1784,7 @@ pub fn print_fn(s: @ps,
     print_fn_args_and_ret(s, decl, opt_explicit_self);
 }
 
-pub fn print_fn_args(s: @ps, decl: &ast::fn_decl,
+pub fn print_fn_args(s: &mut ps, decl: &ast::fn_decl,
                  opt_explicit_self: Option<ast::explicit_self_>) {
     // It is unfortunate to duplicate the commasep logic, but we want the
     // self type and the args all in the same box.
@@ -1778,12 +1802,12 @@ pub fn print_fn_args(s: @ps, decl: &ast::fn_decl,
     end(s);
 }
 
-pub fn print_fn_args_and_ret(s: @ps, decl: &ast::fn_decl,
+pub fn print_fn_args_and_ret(s: &mut ps, decl: &ast::fn_decl,
                              opt_explicit_self: Option<ast::explicit_self_>) {
     popen(s);
     print_fn_args(s, decl, opt_explicit_self);
     if decl.variadic {
-        word(s.s, ", ...");
+        word(&mut s.s, ", ...");
     }
     pclose(s);
 
@@ -1798,10 +1822,10 @@ pub fn print_fn_args_and_ret(s: @ps, decl: &ast::fn_decl,
     }
 }
 
-pub fn print_fn_block_args(s: @ps, decl: &ast::fn_decl) {
-    word(s.s, "|");
+pub fn print_fn_block_args(s: &mut ps, decl: &ast::fn_decl) {
+    word(&mut s.s, "|");
     print_fn_args(s, decl, None);
-    word(s.s, "|");
+    word(&mut s.s, "|");
 
     match decl.output.node {
         ast::ty_infer => {}
@@ -1815,11 +1839,11 @@ pub fn print_fn_block_args(s: @ps, decl: &ast::fn_decl) {
     maybe_print_comment(s, decl.output.span.lo);
 }
 
-pub fn print_proc_args(s: @ps, decl: &ast::fn_decl) {
-    word(s.s, "proc");
-    word(s.s, "(");
+pub fn print_proc_args(s: &mut ps, decl: &ast::fn_decl) {
+    word(&mut s.s, "proc");
+    word(&mut s.s, "(");
     print_fn_args(s, decl, None);
-    word(s.s, ")");
+    word(&mut s.s, ")");
 
     match decl.output.node {
         ast::ty_infer => {}
@@ -1833,10 +1857,10 @@ pub fn print_proc_args(s: @ps, decl: &ast::fn_decl) {
     maybe_print_comment(s, decl.output.span.lo);
 }
 
-pub fn print_bounds(s: @ps, bounds: &OptVec<ast::TyParamBound>,
+pub fn print_bounds(s: &mut ps, bounds: &OptVec<ast::TyParamBound>,
                     print_colon_anyway: bool) {
     if !bounds.is_empty() {
-        word(s.s, ":");
+        word(&mut s.s, ":");
         let mut first = true;
         for bound in bounds.iter() {
             nbsp(s);
@@ -1848,24 +1872,24 @@ pub fn print_bounds(s: @ps, bounds: &OptVec<ast::TyParamBound>,
 
             match *bound {
                 TraitTyParamBound(ref tref) => print_trait_ref(s, tref),
-                RegionTyParamBound => word(s.s, "'static"),
+                RegionTyParamBound => word(&mut s.s, "'static"),
             }
         }
     } else if print_colon_anyway {
-        word(s.s, ":");
+        word(&mut s.s, ":");
     }
 }
 
-pub fn print_lifetime(s: @ps, lifetime: &ast::Lifetime) {
-    word(s.s, "'");
+pub fn print_lifetime(s: &mut ps, lifetime: &ast::Lifetime) {
+    word(&mut s.s, "'");
     print_ident(s, lifetime.ident);
 }
 
-pub fn print_generics(s: @ps, generics: &ast::Generics) {
+pub fn print_generics(s: &mut ps, generics: &ast::Generics) {
     let total = generics.lifetimes.len() + generics.ty_params.len();
     if total > 0 {
-        word(s.s, "<");
-        fn print_item(s: @ps, generics: &ast::Generics, idx: uint) {
+        word(&mut s.s, "<");
+        fn print_item(s: &mut ps, generics: &ast::Generics, idx: uint) {
             if idx < generics.lifetimes.len() {
                 let lifetime = generics.lifetimes.get(idx);
                 print_lifetime(s, lifetime);
@@ -1884,21 +1908,21 @@ pub fn print_generics(s: @ps, generics: &ast::Generics) {
 
         commasep(s, inconsistent, ints,
                  |s, &i| print_item(s, generics, i));
-        word(s.s, ">");
+        word(&mut s.s, ">");
     }
 }
 
-pub fn print_meta_item(s: @ps, item: &ast::MetaItem) {
+pub fn print_meta_item(s: &mut ps, item: &ast::MetaItem) {
     ibox(s, indent_unit);
     match item.node {
-      ast::MetaWord(name) => word(s.s, name),
+      ast::MetaWord(name) => word(&mut s.s, name),
       ast::MetaNameValue(name, value) => {
         word_space(s, name);
         word_space(s, "=");
         print_literal(s, &value);
       }
       ast::MetaList(name, ref items) => {
-        word(s.s, name);
+        word(&mut s.s, name);
         popen(s);
         commasep(s,
                  consistent,
@@ -1910,13 +1934,13 @@ pub fn print_meta_item(s: @ps, item: &ast::MetaItem) {
     end(s);
 }
 
-pub fn print_view_path(s: @ps, vp: &ast::view_path) {
+pub fn print_view_path(s: &mut ps, vp: &ast::view_path) {
     match vp.node {
       ast::view_path_simple(ident, ref path, _) => {
         // FIXME(#6993) can't compare identifiers directly here
         if path.segments.last().identifier.name != ident.name {
             print_ident(s, ident);
-            space(s.s);
+            space(&mut s.s);
             word_space(s, "=");
         }
         print_path(s, path, false);
@@ -1924,29 +1948,29 @@ pub fn print_view_path(s: @ps, vp: &ast::view_path) {
 
       ast::view_path_glob(ref path, _) => {
         print_path(s, path, false);
-        word(s.s, "::*");
+        word(&mut s.s, "::*");
       }
 
       ast::view_path_list(ref path, ref idents, _) => {
         if path.segments.is_empty() {
-            word(s.s, "{");
+            word(&mut s.s, "{");
         } else {
             print_path(s, path, false);
-            word(s.s, "::{");
+            word(&mut s.s, "::{");
         }
         commasep(s, inconsistent, (*idents), |s, w| {
             print_ident(s, w.node.name);
         });
-        word(s.s, "}");
+        word(&mut s.s, "}");
       }
     }
 }
 
-pub fn print_view_paths(s: @ps, vps: &[@ast::view_path]) {
+pub fn print_view_paths(s: &mut ps, vps: &[@ast::view_path]) {
     commasep(s, inconsistent, vps, |p, &vp| print_view_path(p, vp));
 }
 
-pub fn print_view_item(s: @ps, item: &ast::view_item) {
+pub fn print_view_item(s: &mut ps, item: &ast::view_item) {
     hardbreak_if_not_bol(s);
     maybe_print_comment(s, item.span.lo);
     print_outer_attributes(s, item.attrs);
@@ -1956,9 +1980,9 @@ pub fn print_view_item(s: @ps, item: &ast::view_item) {
             head(s, "extern mod");
             print_ident(s, id);
             for &(ref p, style) in optional_path.iter() {
-                space(s.s);
-                word(s.s, "=");
-                space(s.s);
+                space(&mut s.s);
+                word(&mut s.s, "=");
+                space(&mut s.s);
                 print_string(s, *p, style);
             }
         }
@@ -1968,24 +1992,24 @@ pub fn print_view_item(s: @ps, item: &ast::view_item) {
             print_view_paths(s, *vps);
         }
     }
-    word(s.s, ";");
+    word(&mut s.s, ";");
     end(s); // end inner head-block
     end(s); // end outer head-block
 }
 
-pub fn print_mutability(s: @ps, mutbl: ast::Mutability) {
+pub fn print_mutability(s: &mut ps, mutbl: ast::Mutability) {
     match mutbl {
       ast::MutMutable => word_nbsp(s, "mut"),
       ast::MutImmutable => {/* nothing */ }
     }
 }
 
-pub fn print_mt(s: @ps, mt: &ast::mt) {
+pub fn print_mt(s: &mut ps, mt: &ast::mt) {
     print_mutability(s, mt.mutbl);
     print_type(s, mt.ty);
 }
 
-pub fn print_arg(s: @ps, input: &ast::arg) {
+pub fn print_arg(s: &mut ps, input: &ast::arg) {
     ibox(s, indent_unit);
     match input.ty.node {
       ast::ty_infer => print_pat(s, input.pat),
@@ -1999,8 +2023,8 @@ pub fn print_arg(s: @ps, input: &ast::arg) {
             }
             _ => {
                 print_pat(s, input.pat);
-                word(s.s, ":");
-                space(s.s);
+                word(&mut s.s, ":");
+                space(&mut s.s);
             }
         }
         print_type(s, input.ty);
@@ -2009,7 +2033,7 @@ pub fn print_arg(s: @ps, input: &ast::arg) {
     end(s);
 }
 
-pub fn print_ty_fn(s: @ps,
+pub fn print_ty_fn(s: &mut ps,
                    opt_abis: Option<AbiSet>,
                    opt_sigil: Option<ast::Sigil>,
                    opt_region: &Option<ast::Lifetime>,
@@ -2025,7 +2049,7 @@ pub fn print_ty_fn(s: @ps,
     // Duplicates the logic in `print_fn_header_info()`.  This is because that
     // function prints the sigil in the wrong place.  That should be fixed.
     if opt_sigil == Some(ast::OwnedSigil) && onceness == ast::Once {
-        word(s.s, "proc");
+        word(&mut s.s, "proc");
     } else if opt_sigil == Some(ast::BorrowedSigil) {
         print_extern_opt_abis(s, opt_abis);
         for lifetime in opt_region.iter() {
@@ -2039,20 +2063,20 @@ pub fn print_ty_fn(s: @ps,
         print_opt_lifetime(s, opt_region);
         print_purity(s, purity);
         print_onceness(s, onceness);
-        word(s.s, "fn");
+        word(&mut s.s, "fn");
     }
 
-    match id { Some(id) => { word(s.s, " "); print_ident(s, id); } _ => () }
+    match id { Some(id) => { word(&mut s.s, " "); print_ident(s, id); } _ => () }
 
     if opt_sigil != Some(ast::BorrowedSigil) {
         opt_bounds.as_ref().map(|bounds| print_bounds(s, bounds, true));
     }
 
     match generics { Some(g) => print_generics(s, g), _ => () }
-    zerobreak(s.s);
+    zerobreak(&mut s.s);
 
     if opt_sigil == Some(ast::BorrowedSigil) {
-        word(s.s, "|");
+        word(&mut s.s, "|");
     } else {
         popen(s);
     }
@@ -2071,12 +2095,12 @@ pub fn print_ty_fn(s: @ps,
     end(s);
 
     if opt_sigil == Some(ast::BorrowedSigil) {
-        word(s.s, "|");
+        word(&mut s.s, "|");
 
         opt_bounds.as_ref().map(|bounds| print_bounds(s, bounds, true));
     } else {
         if decl.variadic {
-            word(s.s, ", ...");
+            word(&mut s.s, ", ...");
         }
         pclose(s);
     }
@@ -2098,7 +2122,7 @@ pub fn print_ty_fn(s: @ps,
     end(s);
 }
 
-pub fn maybe_print_trailing_comment(s: @ps, span: codemap::Span,
+pub fn maybe_print_trailing_comment(s: &mut ps, span: codemap::Span,
                                     next_pos: Option<BytePos>) {
     let cm;
     match s.cm { Some(ccm) => cm = ccm, _ => return }
@@ -2119,10 +2143,10 @@ pub fn maybe_print_trailing_comment(s: @ps, span: codemap::Span,
     }
 }
 
-pub fn print_remaining_comments(s: @ps) {
+pub fn print_remaining_comments(s: &mut ps) {
     // If there aren't any remaining comments, then we need to manually
     // make sure there is a line break at the end.
-    if next_comment(s).is_none() { hardbreak(s.s); }
+    if next_comment(s).is_none() { hardbreak(&mut s.s); }
     loop {
         match next_comment(s) {
           Some(ref cmnt) => {
@@ -2134,11 +2158,11 @@ pub fn print_remaining_comments(s: @ps) {
     }
 }
 
-pub fn print_literal(s: @ps, lit: &ast::lit) {
+pub fn print_literal(s: &mut ps, lit: &ast::lit) {
     maybe_print_comment(s, lit.span.lo);
     match next_lit(s, lit.span.lo) {
       Some(ref ltrl) => {
-        word(s.s, (*ltrl).lit);
+        word(&mut s.s, (*ltrl).lit);
         return;
       }
       _ => ()
@@ -2149,45 +2173,45 @@ pub fn print_literal(s: @ps, lit: &ast::lit) {
           let mut res = ~"'";
           char::from_u32(ch).unwrap().escape_default(|c| res.push_char(c));
           res.push_char('\'');
-          word(s.s, res);
+          word(&mut s.s, res);
       }
       ast::lit_int(i, t) => {
         if i < 0_i64 {
-            word(s.s,
+            word(&mut s.s,
                  ~"-" + (-i as u64).to_str_radix(10u)
                  + ast_util::int_ty_to_str(t));
         } else {
-            word(s.s,
+            word(&mut s.s,
                  (i as u64).to_str_radix(10u)
                  + ast_util::int_ty_to_str(t));
         }
       }
       ast::lit_uint(u, t) => {
-        word(s.s,
+        word(&mut s.s,
              u.to_str_radix(10u)
              + ast_util::uint_ty_to_str(t));
       }
       ast::lit_int_unsuffixed(i) => {
         if i < 0_i64 {
-            word(s.s, ~"-" + (-i as u64).to_str_radix(10u));
+            word(&mut s.s, ~"-" + (-i as u64).to_str_radix(10u));
         } else {
-            word(s.s, (i as u64).to_str_radix(10u));
+            word(&mut s.s, (i as u64).to_str_radix(10u));
         }
       }
       ast::lit_float(f, t) => {
-        word(s.s, f.to_owned() + ast_util::float_ty_to_str(t));
+        word(&mut s.s, f.to_owned() + ast_util::float_ty_to_str(t));
       }
-      ast::lit_float_unsuffixed(f) => word(s.s, f),
-      ast::lit_nil => word(s.s, "()"),
+      ast::lit_float_unsuffixed(f) => word(&mut s.s, f),
+      ast::lit_nil => word(&mut s.s, "()"),
       ast::lit_bool(val) => {
-        if val { word(s.s, "true"); } else { word(s.s, "false"); }
+        if val { word(&mut s.s, "true"); } else { word(&mut s.s, "false"); }
       }
       ast::lit_binary(arr) => {
         ibox(s, indent_unit);
-        word(s.s, "[");
-        commasep_cmnt(s, inconsistent, arr, |s, u| word(s.s, format!("{}", *u)),
+        word(&mut s.s, "[");
+        commasep_cmnt(s, inconsistent, arr, |s, u| word(&mut s.s, format!("{}", *u)),
                       |_| lit.span);
-        word(s.s, "]");
+        word(&mut s.s, "]");
         end(s);
       }
     }
@@ -2197,7 +2221,7 @@ pub fn lit_to_str(l: &ast::lit) -> ~str {
     return to_str(l, print_literal, parse::token::mk_fake_ident_interner());
 }
 
-pub fn next_lit(s: @ps, pos: BytePos) -> Option<comments::lit> {
+pub fn next_lit(s: &mut ps, pos: BytePos) -> Option<comments::lit> {
     match s.literals {
       Some(ref lits) => {
         while s.cur_cmnt_and_lit.cur_lit < lits.len() {
@@ -2212,7 +2236,7 @@ pub fn next_lit(s: @ps, pos: BytePos) -> Option<comments::lit> {
     }
 }
 
-pub fn maybe_print_comment(s: @ps, pos: BytePos) {
+pub fn maybe_print_comment(s: &mut ps, pos: BytePos) {
     loop {
         match next_comment(s) {
           Some(ref cmnt) => {
@@ -2226,33 +2250,33 @@ pub fn maybe_print_comment(s: @ps, pos: BytePos) {
     }
 }
 
-pub fn print_comment(s: @ps, cmnt: &comments::cmnt) {
+pub fn print_comment(s: &mut ps, cmnt: &comments::cmnt) {
     match cmnt.style {
       comments::mixed => {
         assert_eq!(cmnt.lines.len(), 1u);
-        zerobreak(s.s);
-        word(s.s, cmnt.lines[0]);
-        zerobreak(s.s);
+        zerobreak(&mut s.s);
+        word(&mut s.s, cmnt.lines[0]);
+        zerobreak(&mut s.s);
       }
       comments::isolated => {
         pprust::hardbreak_if_not_bol(s);
         for line in cmnt.lines.iter() {
             // Don't print empty lines because they will end up as trailing
             // whitespace
-            if !line.is_empty() { word(s.s, *line); }
-            hardbreak(s.s);
+            if !line.is_empty() { word(&mut s.s, *line); }
+            hardbreak(&mut s.s);
         }
       }
       comments::trailing => {
-        word(s.s, " ");
+        word(&mut s.s, " ");
         if cmnt.lines.len() == 1u {
-            word(s.s, cmnt.lines[0]);
-            hardbreak(s.s);
+            word(&mut s.s, cmnt.lines[0]);
+            hardbreak(&mut s.s);
         } else {
             ibox(s, 0u);
             for line in cmnt.lines.iter() {
-                if !line.is_empty() { word(s.s, *line); }
-                hardbreak(s.s);
+                if !line.is_empty() { word(&mut s.s, *line); }
+                hardbreak(&mut s.s);
             }
             end(s);
         }
@@ -2264,30 +2288,30 @@ pub fn print_comment(s: @ps, cmnt: &comments::cmnt) {
               pp::STRING(s, _) => ";" == s,
               _ => false
             };
-        if is_semi || is_begin(s) || is_end(s) { hardbreak(s.s); }
-        hardbreak(s.s);
+        if is_semi || is_begin(s) || is_end(s) { hardbreak(&mut s.s); }
+        hardbreak(&mut s.s);
       }
     }
 }
 
-pub fn print_string(s: @ps, st: &str, style: ast::StrStyle) {
+pub fn print_string(s: &mut ps, st: &str, style: ast::StrStyle) {
     let st = match style {
         ast::CookedStr => format!("\"{}\"", st.escape_default()),
         ast::RawStr(n) => format!("r{delim}\"{string}\"{delim}",
                                   delim="#".repeat(n), string=st)
     };
-    word(s.s, st);
+    word(&mut s.s, st);
 }
 
-pub fn to_str<T>(t: &T, f: |@ps, &T|, intr: @ident_interner) -> ~str {
+pub fn to_str<T>(t: &T, f: |&mut ps, &T|, intr: @ident_interner) -> ~str {
     let wr = @mut MemWriter::new();
-    let s = rust_printer(wr as @mut io::Writer, intr);
-    f(s, t);
-    eof(s.s);
+    let mut s = rust_printer(wr as @mut io::Writer, intr);
+    f(&mut s, t);
+    eof(&mut s.s);
     str::from_utf8_owned(wr.inner_ref().to_owned())
 }
 
-pub fn next_comment(s: @ps) -> Option<comments::cmnt> {
+pub fn next_comment(s: &mut ps) -> Option<comments::cmnt> {
     match s.comments {
       Some(ref cmnts) => {
         if s.cur_cmnt_and_lit.cur_cmnt < cmnts.len() {
@@ -2300,7 +2324,7 @@ pub fn next_comment(s: @ps) -> Option<comments::cmnt> {
     }
 }
 
-pub fn print_opt_purity(s: @ps, opt_purity: Option<ast::purity>) {
+pub fn print_opt_purity(s: &mut ps, opt_purity: Option<ast::purity>) {
     match opt_purity {
         Some(ast::impure_fn) => { }
         Some(purity) => {
@@ -2310,7 +2334,7 @@ pub fn print_opt_purity(s: @ps, opt_purity: Option<ast::purity>) {
     }
 }
 
-pub fn print_opt_abis_and_extern_if_nondefault(s: @ps,
+pub fn print_opt_abis_and_extern_if_nondefault(s: &mut ps,
                                                opt_abis: Option<AbiSet>) {
     match opt_abis {
         Some(abis) if !abis.is_rust() => {
@@ -2321,7 +2345,7 @@ pub fn print_opt_abis_and_extern_if_nondefault(s: @ps,
     };
 }
 
-pub fn print_extern_opt_abis(s: @ps, opt_abis: Option<AbiSet>) {
+pub fn print_extern_opt_abis(s: &mut ps, opt_abis: Option<AbiSet>) {
     match opt_abis {
         Some(abis) => {
             word_nbsp(s, "extern");
@@ -2331,23 +2355,23 @@ pub fn print_extern_opt_abis(s: @ps, opt_abis: Option<AbiSet>) {
     };
 }
 
-pub fn print_opt_sigil(s: @ps, opt_sigil: Option<ast::Sigil>) {
+pub fn print_opt_sigil(s: &mut ps, opt_sigil: Option<ast::Sigil>) {
     match opt_sigil {
-        Some(ast::BorrowedSigil) => { word(s.s, "&"); }
-        Some(ast::OwnedSigil) => { word(s.s, "~"); }
-        Some(ast::ManagedSigil) => { word(s.s, "@"); }
+        Some(ast::BorrowedSigil) => { word(&mut s.s, "&"); }
+        Some(ast::OwnedSigil) => { word(&mut s.s, "~"); }
+        Some(ast::ManagedSigil) => { word(&mut s.s, "@"); }
         None => {}
     };
 }
 
-pub fn print_fn_header_info(s: @ps,
+pub fn print_fn_header_info(s: &mut ps,
                             _opt_explicit_self: Option<ast::explicit_self_>,
                             opt_purity: Option<ast::purity>,
                             abis: AbiSet,
                             onceness: ast::Onceness,
                             opt_sigil: Option<ast::Sigil>,
                             vis: ast::visibility) {
-    word(s.s, visibility_qualified(vis, ""));
+    word(&mut s.s, visibility_qualified(vis, ""));
 
     if abis != AbiSet::Rust() {
         word_nbsp(s, "extern");
@@ -2361,7 +2385,7 @@ pub fn print_fn_header_info(s: @ps,
     }
 
     print_onceness(s, onceness);
-    word(s.s, "fn");
+    word(&mut s.s, "fn");
     print_opt_sigil(s, opt_sigil);
 }
 
@@ -2380,14 +2404,14 @@ pub fn onceness_to_str(o: ast::Onceness) -> &'static str {
     }
 }
 
-pub fn print_purity(s: @ps, p: ast::purity) {
+pub fn print_purity(s: &mut ps, p: ast::purity) {
     match p {
       ast::impure_fn => (),
       _ => word_nbsp(s, purity_to_str(p))
     }
 }
 
-pub fn print_onceness(s: @ps, o: ast::Onceness) {
+pub fn print_onceness(s: &mut ps, o: ast::Onceness) {
     match o {
         ast::Once => { word_nbsp(s, "once"); }
         ast::Many => {}