]> git.lizzy.rs Git - rust.git/commitdiff
syntax: fold: use move semantics for efficient folding.
authorEduard Burtescu <edy.burt@gmail.com>
Sun, 7 Sep 2014 17:00:54 +0000 (20:00 +0300)
committerEduard Burtescu <edy.burt@gmail.com>
Sun, 14 Sep 2014 00:39:35 +0000 (03:39 +0300)
src/libsyntax/fold.rs
src/libsyntax/util/small_vector.rs

index 30b7317fa56f181df008ded97ff8f3e4540deeab..8e32191f22adb1e0433e6b3d4243a96cda8400af 100644 (file)
 use ast_util;
 use codemap::{respan, Span, Spanned};
 use parse::token;
+use ptr::P;
 use owned_slice::OwnedSlice;
 use util::small_vector::SmallVector;
 
 use std::rc::Rc;
-use std::gc::{Gc, GC};
+
+// This could have a better place to live.
+pub trait MoveMap<T> {
+    fn move_map(self, f: |T| -> T) -> Self;
+}
+
+impl<T> MoveMap<T> for Vec<T> {
+    fn move_map(self, f: |T| -> T) -> Vec<T> {
+        self.move_iter().map(f).collect()
+    }
+}
+
+impl<T> MoveMap<T> for OwnedSlice<T> {
+    fn move_map(self, f: |T| -> T) -> OwnedSlice<T> {
+        OwnedSlice::from_vec(self.into_vec().move_map(f))
+    }
+}
 
 pub trait Folder {
     // Any additions to this trait should happen in form
@@ -42,91 +59,91 @@ fn fold_crate(&mut self, c: Crate) -> Crate {
         noop_fold_crate(c, self)
     }
 
-    fn fold_meta_items(&mut self, meta_items: &[Gc<MetaItem>]) -> Vec<Gc<MetaItem>> {
+    fn fold_meta_items(&mut self, meta_items: Vec<P<MetaItem>>) -> Vec<P<MetaItem>> {
         noop_fold_meta_items(meta_items, self)
     }
 
-    fn fold_meta_item(&mut self, meta_item: &MetaItem) -> MetaItem {
+    fn fold_meta_item(&mut self, meta_item: P<MetaItem>) -> P<MetaItem> {
         noop_fold_meta_item(meta_item, self)
     }
 
-    fn fold_view_path(&mut self, view_path: Gc<ViewPath>) -> Gc<ViewPath> {
+    fn fold_view_path(&mut self, view_path: P<ViewPath>) -> P<ViewPath> {
         noop_fold_view_path(view_path, self)
     }
 
-    fn fold_view_item(&mut self, vi: &ViewItem) -> ViewItem {
+    fn fold_view_item(&mut self, vi: ViewItem) -> ViewItem {
         noop_fold_view_item(vi, self)
     }
 
-    fn fold_foreign_item(&mut self, ni: Gc<ForeignItem>) -> Gc<ForeignItem> {
-        noop_fold_foreign_item(&*ni, self)
+    fn fold_foreign_item(&mut self, ni: P<ForeignItem>) -> P<ForeignItem> {
+        noop_fold_foreign_item(ni, self)
     }
 
-    fn fold_item(&mut self, i: Gc<Item>) -> SmallVector<Gc<Item>> {
-        noop_fold_item(&*i, self)
+    fn fold_item(&mut self, i: P<Item>) -> SmallVector<P<Item>> {
+        noop_fold_item(i, self)
     }
 
-    fn fold_item_simple(&mut self, i: &Item) -> Item {
+    fn fold_item_simple(&mut self, i: Item) -> Item {
         noop_fold_item_simple(i, self)
     }
 
-    fn fold_struct_field(&mut self, sf: &StructField) -> StructField {
+    fn fold_struct_field(&mut self, sf: StructField) -> StructField {
         noop_fold_struct_field(sf, self)
     }
 
-    fn fold_item_underscore(&mut self, i: &Item_) -> Item_ {
+    fn fold_item_underscore(&mut self, i: Item_) -> Item_ {
         noop_fold_item_underscore(i, self)
     }
 
-    fn fold_fn_decl(&mut self, d: &FnDecl) -> P<FnDecl> {
+    fn fold_fn_decl(&mut self, d: P<FnDecl>) -> P<FnDecl> {
         noop_fold_fn_decl(d, self)
     }
 
-    fn fold_type_method(&mut self, m: &TypeMethod) -> TypeMethod {
+    fn fold_type_method(&mut self, m: TypeMethod) -> TypeMethod {
         noop_fold_type_method(m, self)
     }
 
-    fn fold_method(&mut self, m: Gc<Method>) -> SmallVector<Gc<Method>>  {
-        noop_fold_method(&*m, self)
+    fn fold_method(&mut self, m: P<Method>) -> SmallVector<P<Method>> {
+        noop_fold_method(m, self)
     }
 
     fn fold_block(&mut self, b: P<Block>) -> P<Block> {
         noop_fold_block(b, self)
     }
 
-    fn fold_stmt(&mut self, s: &Stmt) -> SmallVector<Gc<Stmt>> {
-        noop_fold_stmt(s, self)
+    fn fold_stmt(&mut self, s: P<Stmt>) -> SmallVector<P<Stmt>> {
+        s.and_then(|s| noop_fold_stmt(s, self))
     }
 
-    fn fold_arm(&mut self, a: &Arm) -> Arm {
+    fn fold_arm(&mut self, a: Arm) -> Arm {
         noop_fold_arm(a, self)
     }
 
-    fn fold_pat(&mut self, p: Gc<Pat>) -> Gc<Pat> {
+    fn fold_pat(&mut self, p: P<Pat>) -> P<Pat> {
         noop_fold_pat(p, self)
     }
 
-    fn fold_decl(&mut self, d: Gc<Decl>) -> SmallVector<Gc<Decl>> {
+    fn fold_decl(&mut self, d: P<Decl>) -> SmallVector<P<Decl>> {
         noop_fold_decl(d, self)
     }
 
-    fn fold_expr(&mut self, e: Gc<Expr>) -> Gc<Expr> {
-        noop_fold_expr(e, self)
+    fn fold_expr(&mut self, e: P<Expr>) -> P<Expr> {
+        e.map(|e| noop_fold_expr(e, self))
     }
 
     fn fold_ty(&mut self, t: P<Ty>) -> P<Ty> {
         noop_fold_ty(t, self)
     }
 
-    fn fold_mod(&mut self, m: &Mod) -> Mod {
+    fn fold_mod(&mut self, m: Mod) -> Mod {
         noop_fold_mod(m, self)
     }
 
-    fn fold_foreign_mod(&mut self, nm: &ForeignMod) -> ForeignMod {
+    fn fold_foreign_mod(&mut self, nm: ForeignMod) -> ForeignMod {
         noop_fold_foreign_mod(nm, self)
     }
 
-    fn fold_variant(&mut self, v: &Variant) -> P<Variant> {
+    fn fold_variant(&mut self, v: P<Variant>) -> P<Variant> {
         noop_fold_variant(v, self)
     }
 
@@ -138,15 +155,15 @@ fn fold_uint(&mut self, i: uint) -> uint {
         noop_fold_uint(i, self)
     }
 
-    fn fold_path(&mut self, p: &Path) -> Path {
+    fn fold_path(&mut self, p: Path) -> Path {
         noop_fold_path(p, self)
     }
 
-    fn fold_local(&mut self, l: Gc<Local>) -> Gc<Local> {
+    fn fold_local(&mut self, l: P<Local>) -> P<Local> {
         noop_fold_local(l, self)
     }
 
-    fn fold_mac(&mut self, _macro: &Mac) -> Mac {
+    fn fold_mac(&mut self, _macro: Mac) -> Mac {
         fail!("fold_mac disabled by default");
         // NB: see note about macros above.
         // if you really want a folder that
@@ -155,19 +172,19 @@ fn fold_mac(&mut self, _macro: &Mac) -> Mac {
         // fold::noop_fold_mac(_macro, self)
     }
 
-    fn fold_explicit_self(&mut self, es: &ExplicitSelf) -> ExplicitSelf {
+    fn fold_explicit_self(&mut self, es: ExplicitSelf) -> ExplicitSelf {
         noop_fold_explicit_self(es, self)
     }
 
-    fn fold_explicit_self_underscore(&mut self, es: &ExplicitSelf_) -> ExplicitSelf_ {
+    fn fold_explicit_self_underscore(&mut self, es: ExplicitSelf_) -> ExplicitSelf_ {
         noop_fold_explicit_self_underscore(es, self)
     }
 
-    fn fold_lifetime(&mut self, l: &Lifetime) -> Lifetime {
+    fn fold_lifetime(&mut self, l: Lifetime) -> Lifetime {
         noop_fold_lifetime(l, self)
     }
 
-    fn fold_lifetime_def(&mut self, l: &LifetimeDef) -> LifetimeDef {
+    fn fold_lifetime_def(&mut self, l: LifetimeDef) -> LifetimeDef {
         noop_fold_lifetime_def(l, self)
     }
 
@@ -175,35 +192,35 @@ fn fold_attribute(&mut self, at: Attribute) -> Attribute {
         noop_fold_attribute(at, self)
     }
 
-    fn fold_arg(&mut self, a: &Arg) -> Arg {
+    fn fold_arg(&mut self, a: Arg) -> Arg {
         noop_fold_arg(a, self)
     }
 
-    fn fold_generics(&mut self, generics: &Generics) -> Generics {
+    fn fold_generics(&mut self, generics: Generics) -> Generics {
         noop_fold_generics(generics, self)
     }
 
-    fn fold_trait_ref(&mut self, p: &TraitRef) -> TraitRef {
+    fn fold_trait_ref(&mut self, p: TraitRef) -> TraitRef {
         noop_fold_trait_ref(p, self)
     }
 
-    fn fold_struct_def(&mut self, struct_def: Gc<StructDef>) -> Gc<StructDef> {
+    fn fold_struct_def(&mut self, struct_def: P<StructDef>) -> P<StructDef> {
         noop_fold_struct_def(struct_def, self)
     }
 
-    fn fold_lifetimes(&mut self, lts: &[Lifetime]) -> Vec<Lifetime> {
+    fn fold_lifetimes(&mut self, lts: Vec<Lifetime>) -> Vec<Lifetime> {
         noop_fold_lifetimes(lts, self)
     }
 
-    fn fold_lifetime_defs(&mut self, lts: &[LifetimeDef]) -> Vec<LifetimeDef> {
+    fn fold_lifetime_defs(&mut self, lts: Vec<LifetimeDef>) -> Vec<LifetimeDef> {
         noop_fold_lifetime_defs(lts, self)
     }
 
-    fn fold_ty_param(&mut self, tp: &TyParam) -> TyParam {
+    fn fold_ty_param(&mut self, tp: TyParam) -> TyParam {
         noop_fold_ty_param(tp, self)
     }
 
-    fn fold_ty_params(&mut self, tps: &[TyParam]) -> OwnedSlice<TyParam> {
+    fn fold_ty_params(&mut self, tps: OwnedSlice<TyParam>) -> OwnedSlice<TyParam> {
         noop_fold_ty_params(tps, self)
     }
 
@@ -215,37 +232,37 @@ fn fold_tts(&mut self, tts: &[TokenTree]) -> Vec<TokenTree> {
         noop_fold_tts(tts, self)
     }
 
-    fn fold_token(&mut self, t: &token::Token) -> token::Token {
+    fn fold_token(&mut self, t: token::Token) -> token::Token {
         noop_fold_token(t, self)
     }
 
-    fn fold_interpolated(&mut self, nt : &token::Nonterminal) -> token::Nonterminal {
+    fn fold_interpolated(&mut self, nttoken::Nonterminal) -> token::Nonterminal {
         noop_fold_interpolated(nt, self)
     }
 
-    fn fold_opt_lifetime(&mut self, o_lt: &Option<Lifetime>) -> Option<Lifetime> {
+    fn fold_opt_lifetime(&mut self, o_lt: Option<Lifetime>) -> Option<Lifetime> {
         noop_fold_opt_lifetime(o_lt, self)
     }
 
-    fn fold_variant_arg(&mut self, va: &VariantArg) -> VariantArg {
+    fn fold_variant_arg(&mut self, va: VariantArg) -> VariantArg {
         noop_fold_variant_arg(va, self)
     }
 
-    fn fold_opt_bounds(&mut self, b: &Option<OwnedSlice<TyParamBound>>)
+    fn fold_opt_bounds(&mut self, b: Option<OwnedSlice<TyParamBound>>)
                        -> Option<OwnedSlice<TyParamBound>> {
         noop_fold_opt_bounds(b, self)
     }
 
-    fn fold_bounds(&mut self, b: &OwnedSlice<TyParamBound>)
+    fn fold_bounds(&mut self, b: OwnedSlice<TyParamBound>)
                        -> OwnedSlice<TyParamBound> {
         noop_fold_bounds(b, self)
     }
 
-    fn fold_ty_param_bound(&mut self, tpb: &TyParamBound) -> TyParamBound {
+    fn fold_ty_param_bound(&mut self, tpb: TyParamBound) -> TyParamBound {
         noop_fold_ty_param_bound(tpb, self)
     }
 
-    fn fold_mt(&mut self, mt: &MutTy) -> MutTy {
+    fn fold_mt(&mut self, mt: MutTy) -> MutTy {
         noop_fold_mt(mt, self)
     }
 
@@ -253,23 +270,16 @@ fn fold_field(&mut self, field: Field) -> Field {
         noop_fold_field(field, self)
     }
 
-    fn fold_where_clause(&mut self, where_clause: &WhereClause)
+    fn fold_where_clause(&mut self, where_clause: WhereClause)
                          -> WhereClause {
         noop_fold_where_clause(where_clause, self)
     }
 
-    fn fold_where_predicate(&mut self, where_predicate: &WherePredicate)
+    fn fold_where_predicate(&mut self, where_predicate: WherePredicate)
                             -> WherePredicate {
         noop_fold_where_predicate(where_predicate, self)
     }
 
-// Helper methods:
-
-    fn map_exprs(&self, f: |Gc<Expr>| -> Gc<Expr>,
-                 es: &[Gc<Expr>]) -> Vec<Gc<Expr>> {
-        es.iter().map(|x| f(*x)).collect()
-    }
-
     fn new_id(&mut self, i: NodeId) -> NodeId {
         i
     }
@@ -279,190 +289,161 @@ fn new_span(&mut self, sp: Span) -> Span {
     }
 }
 
-pub fn noop_fold_meta_items<T: Folder>(meta_items: &[Gc<MetaItem>], fld: &mut T)
-                                       -> Vec<Gc<MetaItem>> {
-    meta_items.iter().map(|x| box (GC) fld.fold_meta_item(&**x)).collect()
+pub fn noop_fold_meta_items<T: Folder>(meta_items: Vec<P<MetaItem>>, fld: &mut T)
+                                       -> Vec<P<MetaItem>> {
+    meta_items.move_map(|x| fld.fold_meta_item(x))
 }
 
-pub fn noop_fold_view_path<T: Folder>(view_path: Gc<ViewPath>, fld: &mut T) -> Gc<ViewPath> {
-    let inner_view_path = match view_path.node {
-        ViewPathSimple(ref ident, ref path, node_id) => {
-            let id = fld.new_id(node_id);
-            ViewPathSimple(ident.clone(),
-                        fld.fold_path(path),
-                        id)
-        }
-        ViewPathGlob(ref path, node_id) => {
-            let id = fld.new_id(node_id);
-            ViewPathGlob(fld.fold_path(path), id)
-        }
-        ViewPathList(ref path, ref path_list_idents, node_id) => {
-            let id = fld.new_id(node_id);
-            ViewPathList(fld.fold_path(path),
-                        path_list_idents.iter().map(|path_list_ident| {
-                            Spanned {
-                                node: match path_list_ident.node {
-                                    PathListIdent { id, name } =>
-                                        PathListIdent {
-                                            id: fld.new_id(id),
-                                            name: name.clone()
-                                        },
-                                    PathListMod { id } =>
-                                        PathListMod { id: fld.new_id(id) }
-                                },
-                                span: fld.new_span(path_list_ident.span)
-                            }
-                        }).collect(),
-                        id)
-        }
-    };
-    box(GC) Spanned {
-        node: inner_view_path,
-        span: fld.new_span(view_path.span),
-    }
+pub fn noop_fold_view_path<T: Folder>(view_path: P<ViewPath>, fld: &mut T) -> P<ViewPath> {
+    view_path.map(|Spanned {node, span}| Spanned {
+        node: match node {
+            ViewPathSimple(ident, path, node_id) => {
+                let id = fld.new_id(node_id);
+                ViewPathSimple(ident, fld.fold_path(path), id)
+            }
+            ViewPathGlob(path, node_id) => {
+                let id = fld.new_id(node_id);
+                ViewPathGlob(fld.fold_path(path), id)
+            }
+            ViewPathList(path, path_list_idents, node_id) => {
+                let id = fld.new_id(node_id);
+                ViewPathList(fld.fold_path(path),
+                             path_list_idents.move_map(|path_list_ident| {
+                                Spanned {
+                                    node: match path_list_ident.node {
+                                        PathListIdent { id, name } =>
+                                            PathListIdent {
+                                                id: fld.new_id(id),
+                                                name: name
+                                            },
+                                        PathListMod { id } =>
+                                            PathListMod { id: fld.new_id(id) }
+                                    },
+                                    span: fld.new_span(path_list_ident.span)
+                                }
+                             }),
+                             id)
+            }
+        },
+        span: fld.new_span(span)
+    })
 }
 
-pub fn noop_fold_arm<T: Folder>(a: &Arm, fld: &mut T) -> Arm {
+pub fn noop_fold_arm<T: Folder>(Arm {attrs, pats, guard, body}: Arm, fld: &mut T) -> Arm {
     Arm {
-        attrs: a.attrs.iter().map(|x| fld.fold_attribute(*x)).collect(),
-        pats: a.pats.iter().map(|x| fld.fold_pat(*x)).collect(),
-        guard: a.guard.map(|x| fld.fold_expr(x)),
-        body: fld.fold_expr(a.body),
+        attrs: attrs.move_map(|x| fld.fold_attribute(x)),
+        pats: pats.move_map(|x| fld.fold_pat(x)),
+        guard: guard.map(|x| fld.fold_expr(x)),
+        body: fld.fold_expr(body),
     }
 }
 
-pub fn noop_fold_decl<T: Folder>(d: Gc<Decl>, fld: &mut T) -> SmallVector<Gc<Decl>> {
-    let node = match d.node {
-        DeclLocal(ref l) => SmallVector::one(DeclLocal(fld.fold_local(*l))),
-        DeclItem(it) => {
-            fld.fold_item(it).move_iter().map(|i| DeclItem(i)).collect()
-        }
-    };
-
-    node.move_iter().map(|node| {
-        box(GC) Spanned {
-            node: node,
-            span: fld.new_span(d.span),
-        }
-    }).collect()
+pub fn noop_fold_decl<T: Folder>(d: P<Decl>, fld: &mut T) -> SmallVector<P<Decl>> {
+    d.and_then(|Spanned {node, span}| match node {
+        DeclLocal(l) => SmallVector::one(P(Spanned {
+            node: DeclLocal(fld.fold_local(l)),
+            span: fld.new_span(span)
+        })),
+        DeclItem(it) => fld.fold_item(it).move_iter().map(|i| P(Spanned {
+            node: DeclItem(i),
+            span: fld.new_span(span)
+        })).collect()
+    })
 }
 
 pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
-    let id = fld.new_id(t.id);
-    let node = match t.node {
-        TyNil | TyBot | TyInfer => t.node.clone(),
-        TyBox(ty) => TyBox(fld.fold_ty(ty)),
-        TyUniq(ty) => TyUniq(fld.fold_ty(ty)),
-        TyVec(ty) => TyVec(fld.fold_ty(ty)),
-        TyPtr(ref mt) => TyPtr(fld.fold_mt(mt)),
-        TyRptr(ref region, ref mt) => {
-            TyRptr(fld.fold_opt_lifetime(region), fld.fold_mt(mt))
-        }
-        TyClosure(ref f) => {
-            TyClosure(box(GC) ClosureTy {
-                fn_style: f.fn_style,
-                onceness: f.onceness,
-                bounds: fld.fold_bounds(&f.bounds),
-                decl: fld.fold_fn_decl(&*f.decl),
-                lifetimes: fld.fold_lifetime_defs(f.lifetimes.as_slice()),
-            })
-        }
-        TyProc(ref f) => {
-            TyProc(box(GC) ClosureTy {
-                fn_style: f.fn_style,
-                onceness: f.onceness,
-                bounds: fld.fold_bounds(&f.bounds),
-                decl: fld.fold_fn_decl(&*f.decl),
-                lifetimes: fld.fold_lifetime_defs(f.lifetimes.as_slice()),
-            })
-        }
-        TyBareFn(ref f) => {
-            TyBareFn(box(GC) BareFnTy {
-                lifetimes: fld.fold_lifetime_defs(f.lifetimes.as_slice()),
-                fn_style: f.fn_style,
-                abi: f.abi,
-                decl: fld.fold_fn_decl(&*f.decl)
-            })
-        }
-        TyUnboxedFn(ref f) => {
-            TyUnboxedFn(box(GC) UnboxedFnTy {
-                decl: fld.fold_fn_decl(&*f.decl),
-                kind: f.kind,
-            })
-        }
-        TyTup(ref tys) => TyTup(tys.iter().map(|&ty| fld.fold_ty(ty)).collect()),
-        TyParen(ref ty) => TyParen(fld.fold_ty(*ty)),
-        TyPath(ref path, ref bounds, id) => {
-            let id = fld.new_id(id);
-            TyPath(fld.fold_path(path),
-                    fld.fold_opt_bounds(bounds),
-                    id)
-        }
-        TyFixedLengthVec(ty, e) => {
-            TyFixedLengthVec(fld.fold_ty(ty), fld.fold_expr(e))
-        }
-        TyTypeof(expr) => TyTypeof(fld.fold_expr(expr)),
-    };
-    P(Ty {
-        id: id,
-        span: fld.new_span(t.span),
-        node: node,
+    t.map(|Ty {id, node, span}| Ty {
+        id: fld.new_id(id),
+        node: match node {
+            TyNil | TyBot | TyInfer => node,
+            TyBox(ty) => TyBox(fld.fold_ty(ty)),
+            TyUniq(ty) => TyUniq(fld.fold_ty(ty)),
+            TyVec(ty) => TyVec(fld.fold_ty(ty)),
+            TyPtr(mt) => TyPtr(fld.fold_mt(mt)),
+            TyRptr(region, mt) => {
+                TyRptr(fld.fold_opt_lifetime(region), fld.fold_mt(mt))
+            }
+            TyClosure(f) => {
+                TyClosure(f.map(|ClosureTy {fn_style, onceness, bounds, decl, lifetimes}| {
+                    ClosureTy {
+                        fn_style: fn_style,
+                        onceness: onceness,
+                        bounds: fld.fold_bounds(bounds),
+                        decl: fld.fold_fn_decl(decl),
+                        lifetimes: fld.fold_lifetime_defs(lifetimes)
+                    }
+                }))
+            }
+            TyProc(f) => {
+                TyProc(f.map(|ClosureTy {fn_style, onceness, bounds, decl, lifetimes}| {
+                    ClosureTy {
+                        fn_style: fn_style,
+                        onceness: onceness,
+                        bounds: fld.fold_bounds(bounds),
+                        decl: fld.fold_fn_decl(decl),
+                        lifetimes: fld.fold_lifetime_defs(lifetimes)
+                    }
+                }))
+            }
+            TyBareFn(f) => {
+                TyBareFn(f.map(|BareFnTy {lifetimes, fn_style, abi, decl}| BareFnTy {
+                    lifetimes: fld.fold_lifetime_defs(lifetimes),
+                    fn_style: fn_style,
+                    abi: abi,
+                    decl: fld.fold_fn_decl(decl)
+                }))
+            }
+            TyUnboxedFn(f) => {
+                TyUnboxedFn(f.map(|UnboxedFnTy {decl, kind}| UnboxedFnTy {
+                    decl: fld.fold_fn_decl(decl),
+                    kind: kind,
+                }))
+            }
+            TyTup(tys) => TyTup(tys.move_map(|ty| fld.fold_ty(ty))),
+            TyParen(ty) => TyParen(fld.fold_ty(ty)),
+            TyPath(path, bounds, id) => {
+                let id = fld.new_id(id);
+                TyPath(fld.fold_path(path),
+                        fld.fold_opt_bounds(bounds),
+                        id)
+            }
+            TyFixedLengthVec(ty, e) => {
+                TyFixedLengthVec(fld.fold_ty(ty), fld.fold_expr(e))
+            }
+            TyTypeof(expr) => TyTypeof(fld.fold_expr(expr))
+        },
+        span: fld.new_span(span)
     })
 }
 
-pub fn noop_fold_foreign_mod<T: Folder>(nm: &ForeignMod, fld: &mut T) -> ForeignMod {
-    ast::ForeignMod {
-        abi: nm.abi,
-        view_items: nm.view_items
-                        .iter()
-                        .map(|x| fld.fold_view_item(x))
-                        .collect(),
-        items: nm.items
-                    .iter()
-                    .map(|x| fld.fold_foreign_item(*x))
-                    .collect(),
+pub fn noop_fold_foreign_mod<T: Folder>(ForeignMod {abi, view_items, items}: ForeignMod,
+                                        fld: &mut T) -> ForeignMod {
+    ForeignMod {
+        abi: abi,
+        view_items: view_items.move_map(|x| fld.fold_view_item(x)),
+        items: items.move_map(|x| fld.fold_foreign_item(x)),
     }
 }
 
-pub fn noop_fold_variant<T: Folder>(v: &Variant, fld: &mut T) -> P<Variant> {
-    let id = fld.new_id(v.node.id);
-    let kind;
-    match v.node.kind {
-        TupleVariantKind(ref variant_args) => {
-            kind = TupleVariantKind(variant_args.iter().map(|x|
-                fld.fold_variant_arg(x)).collect())
-        }
-        StructVariantKind(ref struct_def) => {
-            kind = StructVariantKind(box(GC) ast::StructDef {
-                fields: struct_def.fields.iter()
-                    .map(|f| fld.fold_struct_field(f)).collect(),
-                ctor_id: struct_def.ctor_id.map(|c| fld.new_id(c)),
-                super_struct: match struct_def.super_struct {
-                    Some(t) => Some(fld.fold_ty(t)),
-                    None => None
-                },
-                is_virtual: struct_def.is_virtual,
-            })
-        }
-    }
-
-    let attrs = v.node.attrs.iter().map(|x| fld.fold_attribute(*x)).collect();
-
-    let de = match v.node.disr_expr {
-        Some(e) => Some(fld.fold_expr(e)),
-        None => None
-    };
-    let node = ast::Variant_ {
-        name: v.node.name,
-        attrs: attrs,
-        kind: kind,
-        id: id,
-        disr_expr: de,
-        vis: v.node.vis,
-    };
-    P(Spanned {
-        node: node,
-        span: fld.new_span(v.span),
+pub fn noop_fold_variant<T: Folder>(v: P<Variant>, fld: &mut T) -> P<Variant> {
+    v.map(|Spanned {node: Variant_ {id, name, attrs, kind, disr_expr, vis}, span}| Spanned {
+        node: Variant_ {
+            id: fld.new_id(id),
+            name: name,
+            attrs: attrs.move_map(|x| fld.fold_attribute(x)),
+            kind: match kind {
+                TupleVariantKind(variant_args) => {
+                    TupleVariantKind(variant_args.move_map(|x|
+                        fld.fold_variant_arg(x)))
+                }
+                StructVariantKind(struct_def) => {
+                    StructVariantKind(fld.fold_struct_def(struct_def))
+                }
+            },
+            disr_expr: disr_expr.map(|e| fld.fold_expr(e)),
+            vis: vis,
+        },
+        span: fld.new_span(span),
     })
 }
 
@@ -474,109 +455,103 @@ pub fn noop_fold_uint<T: Folder>(i: uint, _: &mut T) -> uint {
     i
 }
 
-pub fn noop_fold_path<T: Folder>(p: &Path, fld: &mut T) -> Path {
-    ast::Path {
-        span: fld.new_span(p.span),
-        global: p.global,
-        segments: p.segments.iter().map(|segment| ast::PathSegment {
-            identifier: fld.fold_ident(segment.identifier),
-            lifetimes: segment.lifetimes.iter().map(|l| fld.fold_lifetime(l)).collect(),
-            types: segment.types.iter().map(|&typ| fld.fold_ty(typ)).collect(),
-        }).collect()
+pub fn noop_fold_path<T: Folder>(Path {global, segments, span}: Path, fld: &mut T) -> Path {
+    Path {
+        global: global,
+        segments: segments.move_map(|PathSegment {identifier, lifetimes, types}| PathSegment {
+            identifier: fld.fold_ident(identifier),
+            lifetimes: fld.fold_lifetimes(lifetimes),
+            types: types.move_map(|typ| fld.fold_ty(typ)),
+        }),
+        span: fld.new_span(span)
     }
 }
 
-pub fn noop_fold_local<T: Folder>(l: Gc<Local>, fld: &mut T) -> Gc<Local> {
-    let id = fld.new_id(l.id); // Needs to be first, for ast_map.
-    box(GC) Local {
-        id: id,
-        ty: fld.fold_ty(l.ty),
-        pat: fld.fold_pat(l.pat),
-        init: l.init.map(|e| fld.fold_expr(e)),
-        span: fld.new_span(l.span),
-        source: l.source,
-    }
+pub fn noop_fold_local<T: Folder>(l: P<Local>, fld: &mut T) -> P<Local> {
+    l.map(|Local {id, pat, ty, init, source, span}| Local {
+        id: fld.new_id(id), // Needs to be first, for ast_map.
+        ty: fld.fold_ty(ty),
+        pat: fld.fold_pat(pat),
+        init: init.map(|e| fld.fold_expr(e)),
+        source: source,
+        span: fld.new_span(span)
+    })
 }
 
 pub fn noop_fold_attribute<T: Folder>(at: Attribute, fld: &mut T) -> Attribute {
+    let Spanned {node: Attribute_ {id, style, value, is_sugared_doc}, span} = at;
     Spanned {
-        span: fld.new_span(at.span),
-        node: ast::Attribute_ {
-            id: at.node.id,
-            style: at.node.style,
-            value: box (GC) fld.fold_meta_item(&*at.node.value),
-            is_sugared_doc: at.node.is_sugared_doc
-        }
+        node: Attribute_ {
+            id: id,
+            style: style,
+            value: fld.fold_meta_item(value),
+            is_sugared_doc: is_sugared_doc
+        },
+        span: fld.new_span(span)
     }
 }
 
-pub fn noop_fold_explicit_self_underscore<T: Folder>(es: &ExplicitSelf_, fld: &mut T)
+pub fn noop_fold_explicit_self_underscore<T: Folder>(es: ExplicitSelf_, fld: &mut T)
                                                      -> ExplicitSelf_ {
-    match *es {
-        SelfStatic | SelfValue(_) => *es,
-        SelfRegion(ref lifetime, m, id) => {
+    match es {
+        SelfStatic | SelfValue(_) => es,
+        SelfRegion(lifetime, m, id) => {
             SelfRegion(fld.fold_opt_lifetime(lifetime), m, id)
         }
-        SelfExplicit(ref typ, id) => SelfExplicit(fld.fold_ty(*typ), id),
+        SelfExplicit(typ, id) => SelfExplicit(fld.fold_ty(typ), id),
     }
 }
 
-pub fn noop_fold_explicit_self<T: Folder>(es: &ExplicitSelf, fld: &mut T) -> ExplicitSelf {
+pub fn noop_fold_explicit_self<T: Folder>(Spanned {span, node}: ExplicitSelf, fld: &mut T)
+                                          -> ExplicitSelf {
     Spanned {
-        span: fld.new_span(es.span),
-        node: fld.fold_explicit_self_underscore(&es.node)
+        node: fld.fold_explicit_self_underscore(node),
+        span: fld.new_span(span)
     }
 }
 
 
-pub fn noop_fold_mac<T: Folder>(macro: &Mac, fld: &mut T) -> Mac {
+pub fn noop_fold_mac<T: Folder>(Spanned {node, span}: Mac, fld: &mut T) -> Mac {
     Spanned {
-        node: match macro.node {
-            MacInvocTT(ref p, ref tts, ctxt) => {
-                MacInvocTT(fld.fold_path(p),
-                           fld.fold_tts(tts.as_slice()),
-                           ctxt)
+        node: match node {
+            MacInvocTT(p, tts, ctxt) => {
+                MacInvocTT(fld.fold_path(p), fld.fold_tts(tts.as_slice()), ctxt)
             }
         },
-        span: fld.new_span(macro.span)
+        span: fld.new_span(span)
     }
 }
 
-pub fn noop_fold_meta_item<T: Folder>(mi: &MetaItem, fld: &mut T) -> MetaItem {
-    Spanned {
-        node:
-            match mi.node {
-                MetaWord(ref id) => MetaWord((*id).clone()),
-                MetaList(ref id, ref mis) => {
-                    MetaList((*id).clone(),
-                             mis.iter()
-                                .map(|e| box (GC) fld.fold_meta_item(&**e)).collect())
-                }
-                MetaNameValue(ref id, ref s) => {
-                    MetaNameValue((*id).clone(), (*s).clone())
-                }
-            },
-        span: fld.new_span(mi.span) }
+pub fn noop_fold_meta_item<T: Folder>(mi: P<MetaItem>, fld: &mut T) -> P<MetaItem> {
+    mi.map(|Spanned {node, span}| Spanned {
+        node: match node {
+            MetaWord(id) => MetaWord(id),
+            MetaList(id, mis) => {
+                MetaList(id, mis.move_map(|e| fld.fold_meta_item(e)))
+            }
+            MetaNameValue(id, s) => MetaNameValue(id, s)
+        },
+        span: fld.new_span(span)
+    })
 }
 
-pub fn noop_fold_arg<T: Folder>(a: &Arg, fld: &mut T) -> Arg {
-    let id = fld.new_id(a.id); // Needs to be first, for ast_map.
+pub fn noop_fold_arg<T: Folder>(Arg {id, pat, ty}: Arg, fld: &mut T) -> Arg {
     Arg {
-        id: id,
-        ty: fld.fold_ty(a.ty),
-        pat: fld.fold_pat(a.pat),
+        id: fld.new_id(id), // Needs to be first, for ast_map.
+        pat: fld.fold_pat(pat),
+        ty: fld.fold_ty(ty)
     }
 }
 
 pub fn noop_fold_tt<T: Folder>(tt: &TokenTree, fld: &mut T) -> TokenTree {
     match *tt {
         TTTok(span, ref tok) =>
-            TTTok(span, fld.fold_token(tok)),
+            TTTok(span, fld.fold_token(tok.clone())),
         TTDelim(ref tts) => TTDelim(Rc::new(fld.fold_tts(tts.as_slice()))),
         TTSeq(span, ref pattern, ref sep, is_optional) =>
             TTSeq(span,
                   Rc::new(fld.fold_tts(pattern.as_slice())),
-                  sep.as_ref().map(|tok| fld.fold_token(tok)),
+                  sep.clone().map(|tok| fld.fold_token(tok)),
                   is_optional),
         TTNonterminal(sp,ref ident) =>
             TTNonterminal(sp,fld.fold_ident(*ident))
@@ -588,14 +563,14 @@ pub fn noop_fold_tts<T: Folder>(tts: &[TokenTree], fld: &mut T) -> Vec<TokenTree
 }
 
 // apply ident folder if it's an ident, apply other folds to interpolated nodes
-pub fn noop_fold_token<T: Folder>(t: &token::Token, fld: &mut T) -> token::Token {
-    match *t {
+pub fn noop_fold_token<T: Folder>(t: token::Token, fld: &mut T) -> token::Token {
+    match t {
         token::IDENT(id, followed_by_colons) => {
             token::IDENT(fld.fold_ident(id), followed_by_colons)
         }
         token::LIFETIME(id) => token::LIFETIME(fld.fold_ident(id)),
-        token::INTERPOLATED(ref nt) => token::INTERPOLATED(fld.fold_interpolated(nt)),
-        _ => (*t).clone()
+        token::INTERPOLATED(nt) => token::INTERPOLATED(fld.fold_interpolated(nt)),
+        _ => t
     }
 }
 
@@ -619,9 +594,9 @@ pub fn noop_fold_token<T: Folder>(t: &token::Token, fld: &mut T) -> token::Token
 // BTW, design choice: I considered just changing the type of, e.g., NtItem to contain
 // multiple items, but decided against it when I looked at parse_item_or_view_item and
 // tried to figure out what I would do with multiple items there....
-pub fn noop_fold_interpolated<T: Folder>(nt : &token::Nonterminal, fld: &mut T)
+pub fn noop_fold_interpolated<T: Folder>(nttoken::Nonterminal, fld: &mut T)
                                          -> token::Nonterminal {
-    match *nt {
+    match nt {
         token::NtItem(item) =>
             token::NtItem(fld.fold_item(item)
                           // this is probably okay, because the only folds likely
@@ -630,7 +605,7 @@ pub fn noop_fold_interpolated<T: Folder>(nt : &token::Nonterminal, fld: &mut T)
                           .expect_one("expected fold to produce exactly one item")),
         token::NtBlock(block) => token::NtBlock(fld.fold_block(block)),
         token::NtStmt(stmt) =>
-            token::NtStmt(fld.fold_stmt(&*stmt)
+            token::NtStmt(fld.fold_stmt(stmt)
                           // this is probably okay, because the only folds likely
                           // to peek inside interpolated nodes will be renamings/markings,
                           // which map single items to single items
@@ -638,403 +613,373 @@ pub fn noop_fold_interpolated<T: Folder>(nt : &token::Nonterminal, fld: &mut T)
         token::NtPat(pat) => token::NtPat(fld.fold_pat(pat)),
         token::NtExpr(expr) => token::NtExpr(fld.fold_expr(expr)),
         token::NtTy(ty) => token::NtTy(fld.fold_ty(ty)),
-        token::NtIdent(ref id, is_mod_name) =>
-            token::NtIdent(box fld.fold_ident(**id),is_mod_name),
-        token::NtMeta(meta_item) => token::NtMeta(box (GC) fld.fold_meta_item(&*meta_item)),
-        token::NtPath(ref path) => token::NtPath(box fld.fold_path(&**path)),
-        token::NtTT(tt) => token::NtTT(box (GC) fld.fold_tt(&*tt)),
+        token::NtIdent(box id, is_mod_name) =>
+            token::NtIdent(box fld.fold_ident(id), is_mod_name),
+        token::NtMeta(meta_item) => token::NtMeta(fld.fold_meta_item(meta_item)),
+        token::NtPath(box path) => token::NtPath(box fld.fold_path(path)),
+        token::NtTT(tt) => token::NtTT(P(fld.fold_tt(&*tt))),
         // it looks to me like we can leave out the matchers: token::NtMatchers(matchers)
-        _ => (*nt).clone()
+        _ => nt
     }
 }
 
-pub fn noop_fold_fn_decl<T: Folder>(decl: &FnDecl, fld: &mut T) -> P<FnDecl> {
-    P(FnDecl {
-        inputs: decl.inputs.iter().map(|x| fld.fold_arg(x)).collect(), // bad copy
-        output: fld.fold_ty(decl.output),
-        cf: decl.cf,
-        variadic: decl.variadic
+pub fn noop_fold_fn_decl<T: Folder>(decl: P<FnDecl>, fld: &mut T) -> P<FnDecl> {
+    decl.map(|FnDecl {inputs, output, cf, variadic}| FnDecl {
+        inputs: inputs.move_map(|x| fld.fold_arg(x)),
+        output: fld.fold_ty(output),
+        cf: cf,
+        variadic: variadic
     })
 }
 
-pub fn noop_fold_ty_param_bound<T: Folder>(tpb: &TyParamBound, fld: &mut T)
+pub fn noop_fold_ty_param_bound<T: Folder>(tpb: TyParamBound, fld: &mut T)
                                            -> TyParamBound {
-    match *tpb {
-        TraitTyParamBound(ref ty) => TraitTyParamBound(fld.fold_trait_ref(ty)),
-        RegionTyParamBound(ref lifetime) => RegionTyParamBound(fld.fold_lifetime(lifetime)),
-        UnboxedFnTyParamBound(ref unboxed_function_type) => {
+    match tpb {
+        TraitTyParamBound(ty) => TraitTyParamBound(fld.fold_trait_ref(ty)),
+        RegionTyParamBound(lifetime) => RegionTyParamBound(fld.fold_lifetime(lifetime)),
+        UnboxedFnTyParamBound(UnboxedFnTy {decl, kind}) => {
             UnboxedFnTyParamBound(UnboxedFnTy {
-                decl: fld.fold_fn_decl(&*unboxed_function_type.decl),
-                kind: unboxed_function_type.kind,
+                decl: fld.fold_fn_decl(decl),
+                kind: kind,
             })
         }
     }
 }
 
-pub fn noop_fold_ty_param<T: Folder>(tp: &TyParam, fld: &mut T) -> TyParam {
-    let id = fld.new_id(tp.id);
+pub fn noop_fold_ty_param<T: Folder>(tp: TyParam, fld: &mut T) -> TyParam {
+    let TyParam {id, ident, bounds, unbound, default, span} = tp;
     TyParam {
-        ident: tp.ident,
-        id: id,
-        bounds: fld.fold_bounds(&tp.bounds),
-        unbound: tp.unbound.as_ref().map(|x| fld.fold_ty_param_bound(x)),
-        default: tp.default.map(|x| fld.fold_ty(x)),
-        span: tp.span
+        id: fld.new_id(id),
+        ident: ident,
+        bounds: fld.fold_bounds(bounds),
+        unbound: unbound.map(|x| fld.fold_ty_param_bound(x)),
+        default: default.map(|x| fld.fold_ty(x)),
+        span: span
     }
 }
 
-pub fn noop_fold_ty_params<T: Folder>(tps: &[TyParam], fld: &mut T)
+pub fn noop_fold_ty_params<T: Folder>(tps: OwnedSlice<TyParam>, fld: &mut T)
                                       -> OwnedSlice<TyParam> {
-    tps.iter().map(|tp| fld.fold_ty_param(tp)).collect()
+    tps.move_map(|tp| fld.fold_ty_param(tp))
 }
 
-pub fn noop_fold_lifetime<T: Folder>(l: &Lifetime, fld: &mut T) -> Lifetime {
-    let id = fld.new_id(l.id);
+pub fn noop_fold_lifetime<T: Folder>(l: Lifetime, fld: &mut T) -> Lifetime {
     Lifetime {
-        id: id,
-        span: fld.new_span(l.span),
-        name: l.name
+        id: fld.new_id(l.id),
+        name: l.name,
+        span: fld.new_span(l.span)
     }
 }
 
-pub fn noop_fold_lifetime_def<T: Folder>(l: &LifetimeDef, fld: &mut T)
-                                         -> LifetimeDef
-{
+pub fn noop_fold_lifetime_def<T: Folder>(l: LifetimeDef, fld: &mut T)
+                                         -> LifetimeDef {
     LifetimeDef {
-        lifetime: fld.fold_lifetime(&l.lifetime),
-        bounds: fld.fold_lifetimes(l.bounds.as_slice()),
+        lifetime: fld.fold_lifetime(l.lifetime),
+        bounds: fld.fold_lifetimes(l.bounds),
     }
 }
 
-pub fn noop_fold_lifetimes<T: Folder>(lts: &[Lifetime], fld: &mut T) -> Vec<Lifetime> {
-    lts.iter().map(|l| fld.fold_lifetime(l)).collect()
+pub fn noop_fold_lifetimes<T: Folder>(lts: Vec<Lifetime>, fld: &mut T) -> Vec<Lifetime> {
+    lts.move_map(|l| fld.fold_lifetime(l))
 }
 
-pub fn noop_fold_lifetime_defs<T: Folder>(lts: &[LifetimeDef], fld: &mut T) -> Vec<LifetimeDef> {
-    lts.iter().map(|l| fld.fold_lifetime_def(l)).collect()
+pub fn noop_fold_lifetime_defs<T: Folder>(lts: Vec<LifetimeDef>, fld: &mut T)
+                                          -> Vec<LifetimeDef> {
+    lts.move_map(|l| fld.fold_lifetime_def(l))
 }
 
-pub fn noop_fold_opt_lifetime<T: Folder>(o_lt: &Option<Lifetime>, fld: &mut T)
-                                      -> Option<Lifetime> {
-    o_lt.as_ref().map(|lt| fld.fold_lifetime(lt))
+pub fn noop_fold_opt_lifetime<T: Folder>(o_lt: Option<Lifetime>, fld: &mut T)
+                                         -> Option<Lifetime> {
+    o_lt.map(|lt| fld.fold_lifetime(lt))
 }
 
-pub fn noop_fold_generics<T: Folder>(generics: &Generics, fld: &mut T) -> Generics {
+pub fn noop_fold_generics<T: Folder>(Generics {ty_params, lifetimes, where_clause}: Generics,
+                                     fld: &mut T) -> Generics {
     Generics {
-        ty_params: fld.fold_ty_params(generics.ty_params.as_slice()),
-        lifetimes: fld.fold_lifetime_defs(generics.lifetimes.as_slice()),
-        where_clause: fld.fold_where_clause(&generics.where_clause),
+        ty_params: fld.fold_ty_params(ty_params),
+        lifetimes: fld.fold_lifetime_defs(lifetimes),
+        where_clause: fld.fold_where_clause(where_clause),
     }
 }
 
 pub fn noop_fold_where_clause<T: Folder>(
-                              where_clause: &WhereClause,
+                              WhereClause {id, predicates}: WhereClause,
                               fld: &mut T)
                               -> WhereClause {
     WhereClause {
-        id: fld.new_id(where_clause.id),
-        predicates: where_clause.predicates.iter().map(|predicate| {
+        id: fld.new_id(id),
+        predicates: predicates.move_map(|predicate| {
             fld.fold_where_predicate(predicate)
-        }).collect(),
+        })
     }
 }
 
 pub fn noop_fold_where_predicate<T: Folder>(
-                                 predicate: &WherePredicate,
+                                 WherePredicate {id, ident, bounds, span}: WherePredicate,
                                  fld: &mut T)
                                  -> WherePredicate {
     WherePredicate {
-        id: fld.new_id(predicate.id),
-        span: fld.new_span(predicate.span),
-        ident: fld.fold_ident(predicate.ident),
-        bounds: predicate.bounds.map(|x| {
-            fld.fold_ty_param_bound(x)
-        }),
+        id: fld.new_id(id),
+        ident: fld.fold_ident(ident),
+        bounds: bounds.move_map(|x| fld.fold_ty_param_bound(x)),
+        span: fld.new_span(span)
     }
 }
 
-pub fn noop_fold_struct_def<T: Folder>(struct_def: Gc<StructDef>,
-                              fld: &mut T) -> Gc<StructDef> {
-    box(GC) ast::StructDef {
-        fields: struct_def.fields.iter().map(|f| fld.fold_struct_field(f)).collect(),
-        ctor_id: struct_def.ctor_id.map(|cid| fld.new_id(cid)),
-        super_struct: match struct_def.super_struct {
-            Some(t) => Some(fld.fold_ty(t)),
-            None => None
-        },
-        is_virtual: struct_def.is_virtual,
-    }
+pub fn noop_fold_struct_def<T: Folder>(struct_def: P<StructDef>, fld: &mut T) -> P<StructDef> {
+    struct_def.map(|StructDef {fields, ctor_id, super_struct, is_virtual}| StructDef {
+        fields: fields.move_map(|f| fld.fold_struct_field(f)),
+        ctor_id: ctor_id.map(|cid| fld.new_id(cid)),
+        super_struct: super_struct.map(|t| fld.fold_ty(t)),
+        is_virtual: is_virtual
+    })
 }
 
-pub fn noop_fold_trait_ref<T: Folder>(p: &TraitRef, fld: &mut T) -> TraitRef {
-    let id = fld.new_id(p.ref_id);
-    ast::TraitRef {
-        path: fld.fold_path(&p.path),
-        ref_id: id,
+pub fn noop_fold_trait_ref<T: Folder>(TraitRef {ref_id, path}: TraitRef, fld: &mut T) -> TraitRef {
+    TraitRef {
+        ref_id: fld.new_id(ref_id),
+        path: fld.fold_path(path),
     }
 }
 
-pub fn noop_fold_struct_field<T: Folder>(f: &StructField, fld: &mut T) -> StructField {
-    let id = fld.new_id(f.node.id);
+pub fn noop_fold_struct_field<T: Folder>(f: StructField, fld: &mut T) -> StructField {
+    let StructField {node: StructField_ {id, kind, ty, attrs}, span} = f;
     Spanned {
-        node: ast::StructField_ {
-            kind: f.node.kind,
-            id: id,
-            ty: fld.fold_ty(f.node.ty),
-            attrs: f.node.attrs.iter().map(|a| fld.fold_attribute(*a)).collect(),
+        node: StructField_ {
+            id: fld.new_id(id),
+            kind: kind,
+            ty: fld.fold_ty(ty),
+            attrs: attrs.move_map(|a| fld.fold_attribute(a))
         },
-        span: fld.new_span(f.span),
+        span: fld.new_span(span)
     }
 }
 
-pub fn noop_fold_field<T: Folder>(field: Field, folder: &mut T) -> Field {
-    ast::Field {
-        ident: respan(field.ident.span, folder.fold_ident(field.ident.node)),
-        expr: folder.fold_expr(field.expr),
-        span: folder.new_span(field.span),
+pub fn noop_fold_field<T: Folder>(Field {ident, expr, span}: Field, folder: &mut T) -> Field {
+    Field {
+        ident: respan(ident.span, folder.fold_ident(ident.node)),
+        expr: folder.fold_expr(expr),
+        span: folder.new_span(span)
     }
 }
 
-pub fn noop_fold_mt<T: Folder>(mt: &MutTy, folder: &mut T) -> MutTy {
+pub fn noop_fold_mt<T: Folder>(MutTy {ty, mutbl}: MutTy, folder: &mut T) -> MutTy {
     MutTy {
-        ty: folder.fold_ty(mt.ty),
-        mutbl: mt.mutbl,
+        ty: folder.fold_ty(ty),
+        mutbl: mutbl,
     }
 }
 
-pub fn noop_fold_opt_bounds<T: Folder>(b: &Option<OwnedSlice<TyParamBound>>, folder: &mut T)
-                              -> Option<OwnedSlice<TyParamBound>> {
-    b.as_ref().map(|bounds| folder.fold_bounds(bounds))
+pub fn noop_fold_opt_bounds<T: Folder>(b: Option<OwnedSlice<TyParamBound>>, folder: &mut T)
+                                       -> Option<OwnedSlice<TyParamBound>> {
+    b.map(|bounds| folder.fold_bounds(bounds))
 }
 
-fn noop_fold_bounds<T: Folder>(bounds: &TyParamBounds, folder: &mut T)
+fn noop_fold_bounds<T: Folder>(bounds: TyParamBounds, folder: &mut T)
                           -> TyParamBounds {
-    bounds.map(|bound| folder.fold_ty_param_bound(bound))
+    bounds.move_map(|bound| folder.fold_ty_param_bound(bound))
 }
 
-pub fn noop_fold_variant_arg<T: Folder>(va: &VariantArg, folder: &mut T) -> VariantArg {
-    let id = folder.new_id(va.id);
-    ast::VariantArg {
-        ty: folder.fold_ty(va.ty),
-        id: id,
+fn noop_fold_variant_arg<T: Folder>(VariantArg {id, ty}: VariantArg, folder: &mut T)
+                                    -> VariantArg {
+    VariantArg {
+        id: folder.new_id(id),
+        ty: folder.fold_ty(ty)
     }
 }
 
-pub fn noop_fold_view_item<T: Folder>(vi: &ViewItem, folder: &mut T)
-                                       -> ViewItem{
-    let inner_view_item = match vi.node {
-        ViewItemExternCrate(ref ident, ref string, node_id) => {
-            ViewItemExternCrate(ident.clone(),
-                              (*string).clone(),
-                              folder.new_id(node_id))
-        }
-        ViewItemUse(ref view_path) => {
-            ViewItemUse(folder.fold_view_path(*view_path))
-        }
-    };
+pub fn noop_fold_view_item<T: Folder>(ViewItem {node, attrs, vis, span}: ViewItem,
+                                      folder: &mut T) -> ViewItem {
     ViewItem {
-        node: inner_view_item,
-        attrs: vi.attrs.iter().map(|a| folder.fold_attribute(*a)).collect(),
-        vis: vi.vis,
-        span: folder.new_span(vi.span),
+        node: match node {
+            ViewItemExternCrate(ident, string, node_id) => {
+                ViewItemExternCrate(ident, string,
+                                    folder.new_id(node_id))
+            }
+            ViewItemUse(view_path) => {
+                ViewItemUse(folder.fold_view_path(view_path))
+            }
+        },
+        attrs: attrs.move_map(|a| folder.fold_attribute(a)),
+        vis: vis,
+        span: folder.new_span(span)
     }
 }
 
 pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> {
-    let id = folder.new_id(b.id); // Needs to be first, for ast_map.
-    let view_items = b.view_items.iter().map(|x| folder.fold_view_item(x)).collect();
-    let stmts = b.stmts.iter().flat_map(|s| folder.fold_stmt(&**s).move_iter()).collect();
-    P(Block {
-        id: id,
-        view_items: view_items,
-        stmts: stmts,
-        expr: b.expr.map(|x| folder.fold_expr(x)),
-        rules: b.rules,
-        span: folder.new_span(b.span),
+    b.map(|Block {id, view_items, stmts, expr, rules, span}| Block {
+        id: folder.new_id(id), // Needs to be first, for ast_map.
+        view_items: view_items.move_map(|x| folder.fold_view_item(x)),
+        stmts: stmts.move_iter().flat_map(|s| folder.fold_stmt(s).move_iter()).collect(),
+        expr: expr.map(|x| folder.fold_expr(x)),
+        rules: rules,
+        span: folder.new_span(span),
     })
 }
 
-pub fn noop_fold_item_underscore<T: Folder>(i: &Item_, folder: &mut T) -> Item_ {
-    match *i {
+pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
+    match i {
         ItemStatic(t, m, e) => {
             ItemStatic(folder.fold_ty(t), m, folder.fold_expr(e))
         }
-        ItemFn(decl, fn_style, abi, ref generics, body) => {
+        ItemFn(decl, fn_style, abi, generics, body) => {
             ItemFn(
-                folder.fold_fn_decl(&*decl),
+                folder.fold_fn_decl(decl),
                 fn_style,
                 abi,
                 folder.fold_generics(generics),
                 folder.fold_block(body)
             )
         }
-        ItemMod(ref m) => ItemMod(folder.fold_mod(m)),
-        ItemForeignMod(ref nm) => ItemForeignMod(folder.fold_foreign_mod(nm)),
-        ItemTy(t, ref generics) => {
+        ItemMod(m) => ItemMod(folder.fold_mod(m)),
+        ItemForeignMod(nm) => ItemForeignMod(folder.fold_foreign_mod(nm)),
+        ItemTy(t, generics) => {
             ItemTy(folder.fold_ty(t), folder.fold_generics(generics))
         }
-        ItemEnum(ref enum_definition, ref generics) => {
+        ItemEnum(enum_definition, generics) => {
             ItemEnum(
                 ast::EnumDef {
-                    variants: enum_definition.variants.iter().map(|&x| {
-                        folder.fold_variant(&*x)
-                    }).collect(),
+                    variants: enum_definition.variants.move_map(|x| folder.fold_variant(x)),
                 },
                 folder.fold_generics(generics))
         }
-        ItemStruct(ref struct_def, ref generics) => {
-            let struct_def = folder.fold_struct_def(*struct_def);
+        ItemStruct(struct_def, generics) => {
+            let struct_def = folder.fold_struct_def(struct_def);
             ItemStruct(struct_def, folder.fold_generics(generics))
         }
-        ItemImpl(ref generics, ref ifce, ty, ref impl_items) => {
+        ItemImpl(generics, ifce, ty, impl_items) => {
             ItemImpl(folder.fold_generics(generics),
-                     ifce.as_ref().map(|p| folder.fold_trait_ref(p)),
+                     ifce.map(|p| folder.fold_trait_ref(p)),
                      folder.fold_ty(ty),
-                     impl_items.iter()
-                               .flat_map(|impl_item| {
-                                    match *impl_item {
-                                        MethodImplItem(x) => {
-                                            folder.fold_method(x)
-                                                  .move_iter()
-                                                  .map(|x| MethodImplItem(x))
-                                        }
-                                    }
-                               }).collect()
-            )
+                     impl_items.move_iter().flat_map(|impl_item| match impl_item {
+                        MethodImplItem(x) => {
+                            folder.fold_method(x).move_iter().map(|x| MethodImplItem(x))
+                        }
+                     }).collect())
         }
-        ItemTrait(ref generics, ref unbound, ref bounds, ref methods) => {
+        ItemTrait(generics, unbound, bounds, methods) => {
             let bounds = folder.fold_bounds(bounds);
-            let methods = methods.iter().flat_map(|method| {
-                let r = match *method {
-                    RequiredMethod(ref m) => {
-                            SmallVector::one(RequiredMethod(
-                                    folder.fold_type_method(m))).move_iter()
-                    }
-                    ProvidedMethod(method) => {
-                            // the awkward collect/iter idiom here is because
-                            // even though an iter and a map satisfy the same trait bound,
-                            // they're not actually the same type, so the method arms
-                            // don't unify.
-                            let methods : SmallVector<ast::TraitItem> =
-                                folder.fold_method(method).move_iter()
-                                .map(|m| ProvidedMethod(m)).collect();
-                            methods.move_iter()
-                        }
-                };
-                r
+            let methods = methods.move_iter().flat_map(|method| match method {
+                RequiredMethod(m) => {
+                    SmallVector::one(RequiredMethod(folder.fold_type_method(m))).move_iter()
+                }
+                ProvidedMethod(method) => {
+                    // the awkward collect/iter idiom here is because
+                    // even though an iter and a map satisfy the same trait bound,
+                    // they're not actually the same type, so the method arms
+                    // don't unify.
+                    let methods: SmallVector<ast::TraitItem> =
+                        folder.fold_method(method).move_iter()
+                        .map(|m| ProvidedMethod(m)).collect();
+                    methods.move_iter()
+                }
             }).collect();
             ItemTrait(folder.fold_generics(generics),
-                      unbound.clone(),
+                      unbound,
                       bounds,
                       methods)
         }
-        ItemMac(ref m) => ItemMac(folder.fold_mac(m)),
+        ItemMac(m) => ItemMac(folder.fold_mac(m)),
     }
 }
 
-pub fn noop_fold_type_method<T: Folder>(m: &TypeMethod, fld: &mut T) -> TypeMethod {
-    let id = fld.new_id(m.id); // Needs to be first, for ast_map.
+pub fn noop_fold_type_method<T: Folder>(m: TypeMethod, fld: &mut T) -> TypeMethod {
+    let TypeMethod {id, ident, attrs, fn_style, abi, decl, generics, explicit_self, vis, span} = m;
     TypeMethod {
-        id: id,
-        ident: fld.fold_ident(m.ident),
-        attrs: m.attrs.iter().map(|a| fld.fold_attribute(*a)).collect(),
-        fn_style: m.fn_style,
-        abi: m.abi,
-        decl: fld.fold_fn_decl(&*m.decl),
-        generics: fld.fold_generics(&m.generics),
-        explicit_self: fld.fold_explicit_self(&m.explicit_self),
-        span: fld.new_span(m.span),
-        vis: m.vis,
+        id: fld.new_id(id), // Needs to be first, for ast_map.
+        ident: fld.fold_ident(ident),
+        attrs: attrs.move_map(|a| fld.fold_attribute(a)),
+        fn_style: fn_style,
+        abi: abi,
+        decl: fld.fold_fn_decl(decl),
+        generics: fld.fold_generics(generics),
+        explicit_self: fld.fold_explicit_self(explicit_self),
+        vis: vis,
+        span: fld.new_span(span)
     }
 }
 
-pub fn noop_fold_mod<T: Folder>(m: &Mod, folder: &mut T) -> Mod {
-    ast::Mod {
-        inner: folder.new_span(m.inner),
-        view_items: m.view_items
-                     .iter()
-                     .map(|x| folder.fold_view_item(x)).collect(),
-        items: m.items.iter().flat_map(|x| folder.fold_item(*x).move_iter()).collect(),
+pub fn noop_fold_mod<T: Folder>(Mod {inner, view_items, items}: Mod, folder: &mut T) -> Mod {
+    Mod {
+        inner: folder.new_span(inner),
+        view_items: view_items.move_map(|x| folder.fold_view_item(x)),
+        items: items.move_iter().flat_map(|x| folder.fold_item(x).move_iter()).collect(),
     }
 }
 
-pub fn noop_fold_crate<T: Folder>(c: Crate, folder: &mut T) -> Crate {
+pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, config, exported_macros, span}: Crate,
+                                  folder: &mut T) -> Crate {
     Crate {
-        module: folder.fold_mod(&c.module),
-        attrs: c.attrs.iter().map(|x| folder.fold_attribute(*x)).collect(),
-        config: c.config.iter().map(|x| box (GC) folder.fold_meta_item(&**x)).collect(),
-        span: folder.new_span(c.span),
-        exported_macros: c.exported_macros
+        module: folder.fold_mod(module),
+        attrs: attrs.move_map(|x| folder.fold_attribute(x)),
+        config: folder.fold_meta_items(config),
+        exported_macros: exported_macros,
+        span: folder.new_span(span)
     }
 }
 
 // fold one item into possibly many items
-pub fn noop_fold_item<T: Folder>(i: &Item,
-                                 folder: &mut T) -> SmallVector<Gc<Item>> {
-    SmallVector::one(box(GC) folder.fold_item_simple(i))
+pub fn noop_fold_item<T: Folder>(i: P<Item>, folder: &mut T) -> SmallVector<P<Item>> {
+    SmallVector::one(i.map(|i| folder.fold_item_simple(i)))
 }
 
-
 // fold one item into exactly one item
-pub fn noop_fold_item_simple<T: Folder>(i: &Item, folder: &mut T) -> Item {
-    let id = folder.new_id(i.id); // Needs to be first, for ast_map.
-    let node = folder.fold_item_underscore(&i.node);
+pub fn noop_fold_item_simple<T: Folder>(Item {id, ident, attrs, node, vis, span}: Item,
+                                        folder: &mut T) -> Item {
+    let id = folder.new_id(id); // Needs to be first, for ast_map.
+    let node = folder.fold_item_underscore(node);
     let ident = match node {
         // The node may have changed, recompute the "pretty" impl name.
-        ItemImpl(_, ref maybe_trait, ty, _) => {
-            ast_util::impl_pretty_name(maybe_trait, &*ty)
+        ItemImpl(_, ref maybe_trait, ref ty, _) => {
+            ast_util::impl_pretty_name(maybe_trait, &**ty)
         }
-        _ => i.ident
+        _ => ident
     };
 
     Item {
         id: id,
         ident: folder.fold_ident(ident),
-        attrs: i.attrs.iter().map(|e| folder.fold_attribute(*e)).collect(),
+        attrs: attrs.move_map(|e| folder.fold_attribute(e)),
         node: node,
-        vis: i.vis,
-        span: folder.new_span(i.span)
+        vis: vis,
+        span: folder.new_span(span)
     }
 }
 
-pub fn noop_fold_foreign_item<T: Folder>(ni: &ForeignItem,
-                                         folder: &mut T) -> Gc<ForeignItem> {
-    let id = folder.new_id(ni.id); // Needs to be first, for ast_map.
-    box(GC) ForeignItem {
-        id: id,
-        ident: folder.fold_ident(ni.ident),
-        attrs: ni.attrs.iter().map(|x| folder.fold_attribute(*x)).collect(),
-        node: match ni.node {
-            ForeignItemFn(ref fdec, ref generics) => {
-                ForeignItemFn(P(FnDecl {
-                    inputs: fdec.inputs.iter().map(|a| folder.fold_arg(a)).collect(),
-                    output: folder.fold_ty(fdec.output),
-                    cf: fdec.cf,
-                    variadic: fdec.variadic
+pub fn noop_fold_foreign_item<T: Folder>(ni: P<ForeignItem>, folder: &mut T) -> P<ForeignItem> {
+    ni.map(|ForeignItem {id, ident, attrs, node, span, vis}| ForeignItem {
+        id: folder.new_id(id), // Needs to be first, for ast_map.
+        ident: folder.fold_ident(ident),
+        attrs: attrs.move_map(|x| folder.fold_attribute(x)),
+        node: match node {
+            ForeignItemFn(fdec, generics) => {
+                ForeignItemFn(fdec.map(|FnDecl {inputs, output, cf, variadic}| FnDecl {
+                    inputs: inputs.move_map(|a| folder.fold_arg(a)),
+                    output: folder.fold_ty(output),
+                    cf: cf,
+                    variadic: variadic
                 }), folder.fold_generics(generics))
             }
             ForeignItemStatic(t, m) => {
                 ForeignItemStatic(folder.fold_ty(t), m)
             }
         },
-        span: folder.new_span(ni.span),
-        vis: ni.vis,
-    }
+        vis: vis,
+        span: folder.new_span(span)
+    })
 }
 
 // Default fold over a method.
 // Invariant: produces exactly one method.
-pub fn noop_fold_method<T: Folder>(m: &Method, folder: &mut T) -> SmallVector<Gc<Method>> {
-    let id = folder.new_id(m.id); // Needs to be first, for ast_map.
-    SmallVector::one(box(GC) Method {
-        attrs: m.attrs.iter().map(|a| folder.fold_attribute(*a)).collect(),
-        id: id,
-        span: folder.new_span(m.span),
-        node: match m.node {
+pub fn noop_fold_method<T: Folder>(m: P<Method>, folder: &mut T) -> SmallVector<P<Method>> {
+    SmallVector::one(m.map(|Method {id, attrs, node, span}| Method {
+        id: folder.new_id(id), // Needs to be first, for ast_map.
+        attrs: attrs.move_map(|a| folder.fold_attribute(a)),
+        node: match node {
             MethDecl(ident,
-                     ref generics,
+                     generics,
                      abi,
-                     ref explicit_self,
+                     explicit_self,
                      fn_style,
                      decl,
                      body,
@@ -1044,215 +989,226 @@ pub fn noop_fold_method<T: Folder>(m: &Method, folder: &mut T) -> SmallVector<Gc
                          abi,
                          folder.fold_explicit_self(explicit_self),
                          fn_style,
-                         folder.fold_fn_decl(&*decl),
+                         folder.fold_fn_decl(decl),
                          folder.fold_block(body),
                          vis)
             },
-            MethMac(ref mac) => MethMac(folder.fold_mac(mac)),
-        }
-    })
+            MethMac(mac) => MethMac(folder.fold_mac(mac)),
+        },
+        span: folder.new_span(span)
+    }))
 }
 
-pub fn noop_fold_pat<T: Folder>(p: Gc<Pat>, folder: &mut T) -> Gc<Pat> {
-    let id = folder.new_id(p.id);
-    let node = match p.node {
-        PatWild(k) => PatWild(k),
-        PatIdent(binding_mode, ref pth1, ref sub) => {
-            PatIdent(binding_mode,
-                     Spanned{span: folder.new_span(pth1.span),
-                             node: folder.fold_ident(pth1.node)},
-                     sub.map(|x| folder.fold_pat(x)))
-        }
-        PatLit(e) => PatLit(folder.fold_expr(e)),
-        PatEnum(ref pth, ref pats) => {
-            PatEnum(folder.fold_path(pth),
-                    pats.as_ref().map(|pats| pats.iter().map(|x| folder.fold_pat(*x)).collect()))
-        }
-        PatStruct(ref pth, ref fields, etc) => {
-            let pth_ = folder.fold_path(pth);
-            let fs = fields.iter().map(|f| {
-                ast::FieldPat {
-                    ident: f.ident,
-                    pat: folder.fold_pat(f.pat)
-                }
-            }).collect();
-            PatStruct(pth_, fs, etc)
-        }
-        PatTup(ref elts) => PatTup(elts.iter().map(|x| folder.fold_pat(*x)).collect()),
-        PatBox(inner) => PatBox(folder.fold_pat(inner)),
-        PatRegion(inner) => PatRegion(folder.fold_pat(inner)),
-        PatRange(e1, e2) => {
-            PatRange(folder.fold_expr(e1), folder.fold_expr(e2))
+pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> {
+    p.map(|Pat {id, node, span}| Pat {
+        id: folder.new_id(id),
+        node: match node {
+            PatWild(k) => PatWild(k),
+            PatIdent(binding_mode, pth1, sub) => {
+                PatIdent(binding_mode,
+                        Spanned{span: folder.new_span(pth1.span),
+                                node: folder.fold_ident(pth1.node)},
+                        sub.map(|x| folder.fold_pat(x)))
+            }
+            PatLit(e) => PatLit(folder.fold_expr(e)),
+            PatEnum(pth, pats) => {
+                PatEnum(folder.fold_path(pth),
+                        pats.map(|pats| pats.move_map(|x| folder.fold_pat(x))))
+            }
+            PatStruct(pth, fields, etc) => {
+                let pth = folder.fold_path(pth);
+                let fs = fields.move_map(|f| {
+                    ast::FieldPat {
+                        ident: f.ident,
+                        pat: folder.fold_pat(f.pat)
+                    }
+                });
+                PatStruct(pth, fs, etc)
+            }
+            PatTup(elts) => PatTup(elts.move_map(|x| folder.fold_pat(x))),
+            PatBox(inner) => PatBox(folder.fold_pat(inner)),
+            PatRegion(inner) => PatRegion(folder.fold_pat(inner)),
+            PatRange(e1, e2) => {
+                PatRange(folder.fold_expr(e1), folder.fold_expr(e2))
+            },
+            PatVec(before, slice, after) => {
+                PatVec(before.move_map(|x| folder.fold_pat(x)),
+                       slice.map(|x| folder.fold_pat(x)),
+                       after.move_map(|x| folder.fold_pat(x)))
+            }
+            PatMac(mac) => PatMac(folder.fold_mac(mac))
         },
-        PatVec(ref before, ref slice, ref after) => {
-            PatVec(before.iter().map(|x| folder.fold_pat(*x)).collect(),
-                    slice.map(|x| folder.fold_pat(x)),
-                    after.iter().map(|x| folder.fold_pat(*x)).collect())
-        }
-        PatMac(ref mac) => PatMac(folder.fold_mac(mac)),
-    };
-
-    box(GC) Pat {
-        id: id,
-        span: folder.new_span(p.span),
-        node: node,
-    }
+        span: folder.new_span(span)
+    })
 }
 
-pub fn noop_fold_expr<T: Folder>(e: Gc<Expr>, folder: &mut T) -> Gc<Expr> {
-    let id = folder.new_id(e.id);
-    let node = match e.node {
-        ExprBox(p, e) => {
-            ExprBox(folder.fold_expr(p), folder.fold_expr(e))
-        }
-        ExprVec(ref exprs) => {
-            ExprVec(exprs.iter().map(|&x| folder.fold_expr(x)).collect())
-        }
-        ExprRepeat(expr, count) => {
-            ExprRepeat(folder.fold_expr(expr), folder.fold_expr(count))
-        }
-        ExprTup(ref elts) => ExprTup(elts.iter().map(|x| folder.fold_expr(*x)).collect()),
-        ExprCall(f, ref args) => {
-            ExprCall(folder.fold_expr(f),
-                     args.iter().map(|&x| folder.fold_expr(x)).collect())
-        }
-        ExprMethodCall(i, ref tps, ref args) => {
-            ExprMethodCall(
-                respan(i.span, folder.fold_ident(i.node)),
-                tps.iter().map(|&x| folder.fold_ty(x)).collect(),
-                args.iter().map(|&x| folder.fold_expr(x)).collect())
-        }
-        ExprBinary(binop, lhs, rhs) => {
-            ExprBinary(binop,
-                       folder.fold_expr(lhs),
-                       folder.fold_expr(rhs))
-        }
-        ExprUnary(binop, ohs) => {
-            ExprUnary(binop, folder.fold_expr(ohs))
-        }
-        ExprLit(_) => e.node.clone(),
-        ExprCast(expr, ty) => {
-            ExprCast(folder.fold_expr(expr), folder.fold_ty(ty))
-        }
-        ExprAddrOf(m, ohs) => ExprAddrOf(m, folder.fold_expr(ohs)),
-        ExprIf(cond, tr, fl) => {
-            ExprIf(folder.fold_expr(cond),
-                   folder.fold_block(tr),
-                   fl.map(|x| folder.fold_expr(x)))
-        }
-        ExprWhile(cond, body, opt_ident) => {
-            ExprWhile(folder.fold_expr(cond),
-                      folder.fold_block(body),
-                      opt_ident.map(|i| folder.fold_ident(i)))
-        }
-        ExprForLoop(pat, iter, body, ref opt_ident) => {
-            ExprForLoop(folder.fold_pat(pat),
-                        folder.fold_expr(iter),
-                        folder.fold_block(body),
+pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) -> Expr {
+    Expr {
+        id: folder.new_id(id),
+        node: match node {
+            ExprBox(p, e) => {
+                ExprBox(folder.fold_expr(p), folder.fold_expr(e))
+            }
+            ExprVec(exprs) => {
+                ExprVec(exprs.move_map(|x| folder.fold_expr(x)))
+            }
+            ExprRepeat(expr, count) => {
+                ExprRepeat(folder.fold_expr(expr), folder.fold_expr(count))
+            }
+            ExprTup(elts) => ExprTup(elts.move_map(|x| folder.fold_expr(x))),
+            ExprCall(f, args) => {
+                ExprCall(folder.fold_expr(f),
+                         args.move_map(|x| folder.fold_expr(x)))
+            }
+            ExprMethodCall(i, tps, args) => {
+                ExprMethodCall(
+                    respan(i.span, folder.fold_ident(i.node)),
+                    tps.move_map(|x| folder.fold_ty(x)),
+                    args.move_map(|x| folder.fold_expr(x)))
+            }
+            ExprBinary(binop, lhs, rhs) => {
+                ExprBinary(binop,
+                        folder.fold_expr(lhs),
+                        folder.fold_expr(rhs))
+            }
+            ExprUnary(binop, ohs) => {
+                ExprUnary(binop, folder.fold_expr(ohs))
+            }
+            ExprLit(l) => ExprLit(l),
+            ExprCast(expr, ty) => {
+                ExprCast(folder.fold_expr(expr), folder.fold_ty(ty))
+            }
+            ExprAddrOf(m, ohs) => ExprAddrOf(m, folder.fold_expr(ohs)),
+            ExprIf(cond, tr, fl) => {
+                ExprIf(folder.fold_expr(cond),
+                       folder.fold_block(tr),
+                       fl.map(|x| folder.fold_expr(x)))
+            }
+            ExprWhile(cond, body, opt_ident) => {
+                ExprWhile(folder.fold_expr(cond),
+                          folder.fold_block(body),
+                          opt_ident.map(|i| folder.fold_ident(i)))
+            }
+            ExprForLoop(pat, iter, body, opt_ident) => {
+                ExprForLoop(folder.fold_pat(pat),
+                            folder.fold_expr(iter),
+                            folder.fold_block(body),
+                            opt_ident.map(|i| folder.fold_ident(i)))
+            }
+            ExprLoop(body, opt_ident) => {
+                ExprLoop(folder.fold_block(body),
                         opt_ident.map(|i| folder.fold_ident(i)))
-        }
-        ExprLoop(body, opt_ident) => {
-            ExprLoop(folder.fold_block(body),
-                     opt_ident.map(|i| folder.fold_ident(i)))
-        }
-        ExprMatch(expr, ref arms) => {
-            ExprMatch(folder.fold_expr(expr),
-                      arms.iter().map(|x| folder.fold_arm(x)).collect())
-        }
-        ExprFnBlock(capture_clause, ref decl, ref body) => {
-            ExprFnBlock(capture_clause,
-                        folder.fold_fn_decl(&**decl),
-                        folder.fold_block(body.clone()))
-        }
-        ExprProc(ref decl, ref body) => {
-            ExprProc(folder.fold_fn_decl(&**decl),
-                     folder.fold_block(body.clone()))
-        }
-        ExprUnboxedFn(capture_clause, kind, ref decl, ref body) => {
-            ExprUnboxedFn(capture_clause,
-                          kind,
-                          folder.fold_fn_decl(&**decl),
-                          folder.fold_block(*body))
-        }
-        ExprBlock(ref blk) => ExprBlock(folder.fold_block(*blk)),
-        ExprAssign(el, er) => {
-            ExprAssign(folder.fold_expr(el), folder.fold_expr(er))
-        }
-        ExprAssignOp(op, el, er) => {
-            ExprAssignOp(op,
-                         folder.fold_expr(el),
-                         folder.fold_expr(er))
-        }
-        ExprField(el, id, ref tys) => {
-            ExprField(folder.fold_expr(el),
-                      respan(id.span, folder.fold_ident(id.node)),
-                      tys.iter().map(|&x| folder.fold_ty(x)).collect())
-        }
-        ExprTupField(el, id, ref tys) => {
-            ExprTupField(folder.fold_expr(el),
-                      respan(id.span, folder.fold_uint(id.node)),
-                      tys.iter().map(|&x| folder.fold_ty(x)).collect())
-        }
-        ExprIndex(el, er) => {
-            ExprIndex(folder.fold_expr(el), folder.fold_expr(er))
-        }
-        ExprPath(ref pth) => ExprPath(folder.fold_path(pth)),
-        ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|x| folder.fold_ident(x))),
-        ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|x| folder.fold_ident(x))),
-        ExprRet(ref e) => {
-            ExprRet(e.map(|x| folder.fold_expr(x)))
-        }
-        ExprInlineAsm(ref a) => {
+            }
+            ExprMatch(expr, arms) => {
+                ExprMatch(folder.fold_expr(expr),
+                        arms.move_map(|x| folder.fold_arm(x)))
+            }
+            ExprFnBlock(capture_clause, decl, body) => {
+                ExprFnBlock(capture_clause,
+                            folder.fold_fn_decl(decl),
+                            folder.fold_block(body))
+            }
+            ExprProc(decl, body) => {
+                ExprProc(folder.fold_fn_decl(decl),
+                         folder.fold_block(body))
+            }
+            ExprUnboxedFn(capture_clause, kind, decl, body) => {
+                ExprUnboxedFn(capture_clause,
+                            kind,
+                            folder.fold_fn_decl(decl),
+                            folder.fold_block(body))
+            }
+            ExprBlock(blk) => ExprBlock(folder.fold_block(blk)),
+            ExprAssign(el, er) => {
+                ExprAssign(folder.fold_expr(el), folder.fold_expr(er))
+            }
+            ExprAssignOp(op, el, er) => {
+                ExprAssignOp(op,
+                            folder.fold_expr(el),
+                            folder.fold_expr(er))
+            }
+            ExprField(el, ident, tys) => {
+                ExprField(folder.fold_expr(el),
+                          respan(ident.span, folder.fold_ident(ident.node)),
+                          tys.move_map(|x| folder.fold_ty(x)))
+            }
+            ExprTupField(el, ident, tys) => {
+                ExprTupField(folder.fold_expr(el),
+                             respan(ident.span, folder.fold_uint(ident.node)),
+                             tys.move_map(|x| folder.fold_ty(x)))
+            }
+            ExprIndex(el, er) => {
+                ExprIndex(folder.fold_expr(el), folder.fold_expr(er))
+            }
+            ExprPath(pth) => ExprPath(folder.fold_path(pth)),
+            ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|x| folder.fold_ident(x))),
+            ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|x| folder.fold_ident(x))),
+            ExprRet(e) => ExprRet(e.map(|x| folder.fold_expr(x))),
             ExprInlineAsm(InlineAsm {
-                inputs: a.inputs.iter().map(|&(ref c, input)| {
-                    ((*c).clone(), folder.fold_expr(input))
-                }).collect(),
-                outputs: a.outputs.iter().map(|&(ref c, out, is_rw)| {
-                    ((*c).clone(), folder.fold_expr(out), is_rw)
-                }).collect(),
-                .. (*a).clone()
-            })
-        }
-        ExprMac(ref mac) => ExprMac(folder.fold_mac(mac)),
-        ExprStruct(ref path, ref fields, maybe_expr) => {
-            ExprStruct(folder.fold_path(path),
-                       fields.iter().map(|x| folder.fold_field(*x)).collect(),
-                       maybe_expr.map(|x| folder.fold_expr(x)))
+                inputs,
+                outputs,
+                asm,
+                asm_str_style,
+                clobbers,
+                volatile,
+                alignstack,
+                dialect
+            }) => ExprInlineAsm(InlineAsm {
+                inputs: inputs.move_map(|(c, input)| {
+                    (c, folder.fold_expr(input))
+                }),
+                outputs: outputs.move_map(|(c, out, is_rw)| {
+                    (c, folder.fold_expr(out), is_rw)
+                }),
+                asm: asm,
+                asm_str_style: asm_str_style,
+                clobbers: clobbers,
+                volatile: volatile,
+                alignstack: alignstack,
+                dialect: dialect
+            }),
+            ExprMac(mac) => ExprMac(folder.fold_mac(mac)),
+            ExprStruct(path, fields, maybe_expr) => {
+                ExprStruct(folder.fold_path(path),
+                        fields.move_map(|x| folder.fold_field(x)),
+                        maybe_expr.map(|x| folder.fold_expr(x)))
+            },
+            ExprParen(ex) => ExprParen(folder.fold_expr(ex))
         },
-        ExprParen(ex) => ExprParen(folder.fold_expr(ex))
-    };
-
-    box(GC) Expr {
-        id: id,
-        node: node,
-        span: folder.new_span(e.span),
+        span: folder.new_span(span)
     }
 }
 
-pub fn noop_fold_stmt<T: Folder>(s: &Stmt,
-                                 folder: &mut T) -> SmallVector<Gc<Stmt>> {
-    let nodes = match s.node {
+pub fn noop_fold_stmt<T: Folder>(Spanned {node, span}: Stmt, folder: &mut T)
+                                 -> SmallVector<P<Stmt>> {
+    let span = folder.new_span(span);
+    match node {
         StmtDecl(d, id) => {
             let id = folder.new_id(id);
-            folder.fold_decl(d).move_iter()
-                    .map(|d| StmtDecl(d, id))
-                    .collect()
+            folder.fold_decl(d).move_iter().map(|d| P(Spanned {
+                node: StmtDecl(d, id),
+                span: span
+            })).collect()
         }
         StmtExpr(e, id) => {
             let id = folder.new_id(id);
-            SmallVector::one(StmtExpr(folder.fold_expr(e), id))
+            SmallVector::one(P(Spanned {
+                node: StmtExpr(folder.fold_expr(e), id),
+                span: span
+            }))
         }
         StmtSemi(e, id) => {
             let id = folder.new_id(id);
-            SmallVector::one(StmtSemi(folder.fold_expr(e), id))
+            SmallVector::one(P(Spanned {
+                node: StmtSemi(folder.fold_expr(e), id),
+                span: span
+            }))
         }
-        StmtMac(ref mac, semi) => SmallVector::one(StmtMac(folder.fold_mac(mac), semi))
-    };
-
-    nodes.move_iter().map(|node| box(GC) Spanned {
-        node: node,
-        span: folder.new_span(s.span),
-    }).collect()
+        StmtMac(mac, semi) => SmallVector::one(P(Spanned {
+            node: StmtMac(folder.fold_mac(mac), semi),
+            span: span
+        }))
+    }
 }
 
 #[cfg(test)]
index 517c5e5bf47da3ca809503387efdc79740bc8090..47aef987a63d04426428acede8c63fd942a562c6 100644 (file)
@@ -12,6 +12,8 @@
 use std::slice;
 use std::vec;
 
+use fold::MoveMap;
+
 /// A vector type optimized for cases where the size is almost always 0 or 1
 pub struct SmallVector<T> {
     repr: SmallVectorRepr<T>,
@@ -20,7 +22,7 @@ pub struct SmallVector<T> {
 enum SmallVectorRepr<T> {
     Zero,
     One(T),
-    Many(Vec<T> ),
+    Many(Vec<T>),
 }
 
 impl<T> Collection for SmallVector<T> {
@@ -160,6 +162,17 @@ fn size_hint(&self) -> (uint, Option<uint>) {
     }
 }
 
+impl<T> MoveMap<T> for SmallVector<T> {
+    fn move_map(self, f: |T| -> T) -> SmallVector<T> {
+        let repr = match self.repr {
+            Zero => Zero,
+            One(v) => One(f(v)),
+            Many(vs) => Many(vs.move_map(f))
+        };
+        SmallVector { repr: repr }
+    }
+}
+
 #[cfg(test)]
 mod test {
     use super::*;