about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2014-05-16 00:16:13 -0700
committerAlex Crichton <alex@alexcrichton.com>2014-06-11 09:11:40 -0700
commit53ad426e92f8099a701f3f54c02dc8f069f5939a (patch)
treecef835fc4f6319f12bf1c47c90682bdbcf17afac
parent531ed3d599000de2517cba102c83fe44a1f1e252 (diff)
downloadrust-53ad426e92f8099a701f3f54c02dc8f069f5939a.tar.gz
rust-53ad426e92f8099a701f3f54c02dc8f069f5939a.zip
syntax: Move the AST from @T to Gc<T>
-rw-r--r--src/libsyntax/ast.rs147
-rw-r--r--src/libsyntax/ast_map.rs111
-rw-r--r--src/libsyntax/ast_util.rs42
-rw-r--r--src/libsyntax/attr.rs54
-rw-r--r--src/libsyntax/codemap.rs4
-rw-r--r--src/libsyntax/ext/asm.rs3
-rw-r--r--src/libsyntax/ext/base.rs61
-rw-r--r--src/libsyntax/ext/build.rs418
-rw-r--r--src/libsyntax/ext/concat_idents.rs2
-rw-r--r--src/libsyntax/ext/deriving/bounds.rs8
-rw-r--r--src/libsyntax/ext/deriving/clone.rs10
-rw-r--r--src/libsyntax/ext/deriving/cmp/eq.rs12
-rw-r--r--src/libsyntax/ext/deriving/cmp/ord.rs11
-rw-r--r--src/libsyntax/ext/deriving/cmp/totaleq.rs11
-rw-r--r--src/libsyntax/ext/deriving/cmp/totalord.rs9
-rw-r--r--src/libsyntax/ext/deriving/decodable.rs14
-rw-r--r--src/libsyntax/ext/deriving/default.rs11
-rw-r--r--src/libsyntax/ext/deriving/encodable.rs10
-rw-r--r--src/libsyntax/ext/deriving/generic/mod.rs141
-rw-r--r--src/libsyntax/ext/deriving/generic/ty.rs5
-rw-r--r--src/libsyntax/ext/deriving/hash.rs11
-rw-r--r--src/libsyntax/ext/deriving/mod.rs8
-rw-r--r--src/libsyntax/ext/deriving/primitive.rs11
-rw-r--r--src/libsyntax/ext/deriving/rand.rs15
-rw-r--r--src/libsyntax/ext/deriving/show.rs9
-rw-r--r--src/libsyntax/ext/deriving/zero.rs11
-rw-r--r--src/libsyntax/ext/expand.rs78
-rw-r--r--src/libsyntax/ext/format.rs49
-rw-r--r--src/libsyntax/ext/quote.rs52
-rw-r--r--src/libsyntax/ext/source_util.rs3
-rw-r--r--src/libsyntax/ext/tt/macro_parser.rs2
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs9
-rw-r--r--src/libsyntax/fold.rs110
-rw-r--r--src/libsyntax/parse/attr.rs24
-rw-r--r--src/libsyntax/parse/classify.rs5
-rw-r--r--src/libsyntax/parse/mod.rs35
-rw-r--r--src/libsyntax/parse/obsolete.rs8
-rw-r--r--src/libsyntax/parse/parser.rs241
-rw-r--r--src/libsyntax/parse/token.rs20
-rw-r--r--src/libsyntax/print/pprust.rs382
-rw-r--r--src/libsyntax/visit.rs278
41 files changed, 1278 insertions, 1167 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 2f5459b6f2e..7c1e82a2a6f 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -21,15 +21,16 @@ use std::fmt;
 use std::fmt::Show;
 use std::option::Option;
 use std::rc::Rc;
+use std::gc::Gc;
 use serialize::{Encodable, Decodable, Encoder, Decoder};
 
 /// A pointer abstraction. FIXME(eddyb) #10676 use Rc<T> in the future.
-pub type P<T> = @T;
+pub type P<T> = Gc<T>;
 
 #[allow(non_snake_case_functions)]
 /// Construct a P<T> from a T value.
 pub fn P<T: 'static>(value: T) -> P<T> {
-    @value
+    box(GC) value
 }
 
 // FIXME #6993: in librustc, uses of "ident" should be replaced
@@ -217,7 +218,7 @@ pub enum DefRegion {
 
 // The set of MetaItems that define the compilation environment of the crate,
 // used to drive conditional compilation
-pub type CrateConfig = Vec<@MetaItem> ;
+pub type CrateConfig = Vec<Gc<MetaItem>>;
 
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
 pub struct Crate {
@@ -232,7 +233,7 @@ pub type MetaItem = Spanned<MetaItem_>;
 #[deriving(Clone, Encodable, Decodable, Eq, Hash)]
 pub enum MetaItem_ {
     MetaWord(InternedString),
-    MetaList(InternedString, Vec<@MetaItem> ),
+    MetaList(InternedString, Vec<Gc<MetaItem>>),
     MetaNameValue(InternedString, Lit),
 }
 
@@ -264,8 +265,8 @@ impl PartialEq for MetaItem_ {
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
 pub struct Block {
     pub view_items: Vec<ViewItem>,
-    pub stmts: Vec<@Stmt>,
-    pub expr: Option<@Expr>,
+    pub stmts: Vec<Gc<Stmt>>,
+    pub expr: Option<Gc<Expr>>,
     pub id: NodeId,
     pub rules: BlockCheckMode,
     pub span: Span,
@@ -281,7 +282,7 @@ pub struct Pat {
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
 pub struct FieldPat {
     pub ident: Ident,
-    pub pat: @Pat,
+    pub pat: Gc<Pat>,
 }
 
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
@@ -301,18 +302,18 @@ pub enum Pat_ {
     // which it is. The resolver determines this, and
     // records this pattern's NodeId in an auxiliary
     // set (of "pat_idents that refer to nullary enums")
-    PatIdent(BindingMode, Path, Option<@Pat>),
-    PatEnum(Path, Option<Vec<@Pat> >), /* "none" means a * pattern where
+    PatIdent(BindingMode, Path, Option<Gc<Pat>>),
+    PatEnum(Path, Option<Vec<Gc<Pat>>>), /* "none" means a * pattern where
                                      * we don't bind the fields to names */
-    PatStruct(Path, Vec<FieldPat> , bool),
-    PatTup(Vec<@Pat> ),
-    PatBox(@Pat),
-    PatRegion(@Pat), // reference pattern
-    PatLit(@Expr),
-    PatRange(@Expr, @Expr),
+    PatStruct(Path, Vec<FieldPat>, bool),
+    PatTup(Vec<Gc<Pat>>),
+    PatBox(Gc<Pat>),
+    PatRegion(Gc<Pat>), // reference pattern
+    PatLit(Gc<Expr>),
+    PatRange(Gc<Expr>, Gc<Expr>),
     // [a, b, ..i, y, z] is represented as
     // PatVec(~[a, b], Some(i), ~[y, z])
-    PatVec(Vec<@Pat> , Option<@Pat>, Vec<@Pat> ),
+    PatVec(Vec<Gc<Pat>>, Option<Gc<Pat>>, Vec<Gc<Pat>>),
     PatMac(Mac),
 }
 
@@ -365,13 +366,13 @@ pub type Stmt = Spanned<Stmt_>;
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
 pub enum Stmt_ {
     // could be an item or a local (let) binding:
-    StmtDecl(@Decl, NodeId),
+    StmtDecl(Gc<Decl>, NodeId),
 
     // expr without trailing semi-colon (must have unit type):
-    StmtExpr(@Expr, NodeId),
+    StmtExpr(Gc<Expr>, NodeId),
 
     // expr with trailing semi-colon (may have any type):
-    StmtSemi(@Expr, NodeId),
+    StmtSemi(Gc<Expr>, NodeId),
 
     // bool: is there a trailing sem-colon?
     StmtMac(Mac, bool),
@@ -391,8 +392,8 @@ pub enum LocalSource {
 #[deriving(PartialEq, Eq, Encodable, Decodable, Hash)]
 pub struct Local {
     pub ty: P<Ty>,
-    pub pat: @Pat,
-    pub init: Option<@Expr>,
+    pub pat: Gc<Pat>,
+    pub init: Option<Gc<Expr>>,
     pub id: NodeId,
     pub span: Span,
     pub source: LocalSource,
@@ -403,23 +404,23 @@ pub type Decl = Spanned<Decl_>;
 #[deriving(PartialEq, Eq, Encodable, Decodable, Hash)]
 pub enum Decl_ {
     // a local (let) binding:
-    DeclLocal(@Local),
+    DeclLocal(Gc<Local>),
     // an item binding:
-    DeclItem(@Item),
+    DeclItem(Gc<Item>),
 }
 
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
 pub struct Arm {
     pub attrs: Vec<Attribute>,
-    pub pats: Vec<@Pat>,
-    pub guard: Option<@Expr>,
-    pub body: @Expr,
+    pub pats: Vec<Gc<Pat>>,
+    pub guard: Option<Gc<Expr>>,
+    pub body: Gc<Expr>,
 }
 
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
 pub struct Field {
     pub ident: SpannedIdent,
-    pub expr: @Expr,
+    pub expr: Gc<Expr>,
     pub span: Span,
 }
 
@@ -446,56 +447,56 @@ pub struct Expr {
 
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
 pub enum Expr_ {
-    ExprVstore(@Expr, ExprVstore),
+    ExprVstore(Gc<Expr>, ExprVstore),
     // First expr is the place; second expr is the value.
-    ExprBox(@Expr, @Expr),
-    ExprVec(Vec<@Expr>),
-    ExprCall(@Expr, Vec<@Expr>),
-    ExprMethodCall(SpannedIdent, Vec<P<Ty>>, Vec<@Expr>),
-    ExprTup(Vec<@Expr>),
-    ExprBinary(BinOp, @Expr, @Expr),
-    ExprUnary(UnOp, @Expr),
-    ExprLit(@Lit),
-    ExprCast(@Expr, P<Ty>),
-    ExprIf(@Expr, P<Block>, Option<@Expr>),
-    ExprWhile(@Expr, P<Block>),
+    ExprBox(Gc<Expr>, Gc<Expr>),
+    ExprVec(Vec<Gc<Expr>>),
+    ExprCall(Gc<Expr>, Vec<Gc<Expr>>),
+    ExprMethodCall(SpannedIdent, Vec<P<Ty>>, Vec<Gc<Expr>>),
+    ExprTup(Vec<Gc<Expr>>),
+    ExprBinary(BinOp, Gc<Expr>, Gc<Expr>),
+    ExprUnary(UnOp, Gc<Expr>),
+    ExprLit(Gc<Lit>),
+    ExprCast(Gc<Expr>, P<Ty>),
+    ExprIf(Gc<Expr>, P<Block>, Option<Gc<Expr>>),
+    ExprWhile(Gc<Expr>, P<Block>),
     // FIXME #6993: change to Option<Name>
-    ExprForLoop(@Pat, @Expr, P<Block>, Option<Ident>),
+    ExprForLoop(Gc<Pat>, Gc<Expr>, P<Block>, Option<Ident>),
     // Conditionless loop (can be exited with break, cont, or ret)
     // FIXME #6993: change to Option<Name>
     ExprLoop(P<Block>, Option<Ident>),
-    ExprMatch(@Expr, Vec<Arm>),
+    ExprMatch(Gc<Expr>, Vec<Arm>),
     ExprFnBlock(P<FnDecl>, P<Block>),
     ExprProc(P<FnDecl>, P<Block>),
     ExprBlock(P<Block>),
 
-    ExprAssign(@Expr, @Expr),
-    ExprAssignOp(BinOp, @Expr, @Expr),
-    ExprField(@Expr, Ident, Vec<P<Ty>>),
-    ExprIndex(@Expr, @Expr),
+    ExprAssign(Gc<Expr>, Gc<Expr>),
+    ExprAssignOp(BinOp, Gc<Expr>, Gc<Expr>),
+    ExprField(Gc<Expr>, Ident, Vec<P<Ty>>),
+    ExprIndex(Gc<Expr>, Gc<Expr>),
 
     /// Expression that looks like a "name". For example,
     /// `std::slice::from_elem::<uint>` is an ExprPath that's the "name" part
     /// of a function call.
     ExprPath(Path),
 
-    ExprAddrOf(Mutability, @Expr),
+    ExprAddrOf(Mutability, Gc<Expr>),
     ExprBreak(Option<Ident>),
     ExprAgain(Option<Ident>),
-    ExprRet(Option<@Expr>),
+    ExprRet(Option<Gc<Expr>>),
 
     ExprInlineAsm(InlineAsm),
 
     ExprMac(Mac),
 
     // A struct literal expression.
-    ExprStruct(Path, Vec<Field> , Option<@Expr> /* base */),
+    ExprStruct(Path, Vec<Field> , Option<Gc<Expr>> /* base */),
 
     // A vector literal constructed from one repeated element.
-    ExprRepeat(@Expr /* element */, @Expr /* count */),
+    ExprRepeat(Gc<Expr> /* element */, Gc<Expr> /* count */),
 
     // No-op: used solely so we can pretty-print faithfully
-    ExprParen(@Expr)
+    ExprParen(Gc<Expr>)
 }
 
 // When the main rust parser encounters a syntax-extension invocation, it
@@ -667,7 +668,7 @@ pub struct TypeMethod {
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
 pub enum TraitMethod {
     Required(TypeMethod),
-    Provided(@Method),
+    Provided(Gc<Method>),
 }
 
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
@@ -782,16 +783,16 @@ pub enum Ty_ {
     TyBox(P<Ty>),
     TyUniq(P<Ty>),
     TyVec(P<Ty>),
-    TyFixedLengthVec(P<Ty>, @Expr),
+    TyFixedLengthVec(P<Ty>, Gc<Expr>),
     TyPtr(MutTy),
     TyRptr(Option<Lifetime>, MutTy),
-    TyClosure(@ClosureTy, Option<Lifetime>),
-    TyProc(@ClosureTy),
-    TyBareFn(@BareFnTy),
-    TyUnboxedFn(@UnboxedFnTy),
+    TyClosure(Gc<ClosureTy>, Option<Lifetime>),
+    TyProc(Gc<ClosureTy>),
+    TyBareFn(Gc<BareFnTy>),
+    TyUnboxedFn(Gc<UnboxedFnTy>),
     TyTup(Vec<P<Ty>> ),
     TyPath(Path, Option<OwnedSlice<TyParamBound>>, NodeId), // for #7264; see above
-    TyTypeof(@Expr),
+    TyTypeof(Gc<Expr>),
     // TyInfer means the type should be inferred instead of it having been
     // specified. This can appear anywhere in a type.
     TyInfer,
@@ -808,8 +809,8 @@ pub struct InlineAsm {
     pub asm: InternedString,
     pub asm_str_style: StrStyle,
     pub clobbers: InternedString,
-    pub inputs: Vec<(InternedString, @Expr)>,
-    pub outputs: Vec<(InternedString, @Expr)>,
+    pub inputs: Vec<(InternedString, Gc<Expr>)>,
+    pub outputs: Vec<(InternedString, Gc<Expr>)>,
     pub volatile: bool,
     pub alignstack: bool,
     pub dialect: AsmDialect
@@ -818,7 +819,7 @@ pub struct InlineAsm {
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
 pub struct Arg {
     pub ty: P<Ty>,
-    pub pat: @Pat,
+    pub pat: Gc<Pat>,
     pub id: NodeId,
 }
 
@@ -832,7 +833,7 @@ impl Arg {
                 node: TyInfer,
                 span: DUMMY_SP,
             }),
-            pat: @Pat {
+            pat: box(GC) Pat {
                 id: DUMMY_NODE_ID,
                 node: PatIdent(BindByValue(mutability), path, None),
                 span: span
@@ -903,14 +904,14 @@ pub struct Mod {
     /// to the last token in the external file.
     pub inner: Span,
     pub view_items: Vec<ViewItem>,
-    pub items: Vec<@Item>,
+    pub items: Vec<Gc<Item>>,
 }
 
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
 pub struct ForeignMod {
     pub abi: Abi,
     pub view_items: Vec<ViewItem>,
-    pub items: Vec<@ForeignItem>,
+    pub items: Vec<Gc<ForeignItem>>,
 }
 
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
@@ -922,7 +923,7 @@ pub struct VariantArg {
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
 pub enum VariantKind {
     TupleVariantKind(Vec<VariantArg>),
-    StructVariantKind(@StructDef),
+    StructVariantKind(Gc<StructDef>),
 }
 
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
@@ -936,7 +937,7 @@ pub struct Variant_ {
     pub attrs: Vec<Attribute>,
     pub kind: VariantKind,
     pub id: NodeId,
-    pub disr_expr: Option<@Expr>,
+    pub disr_expr: Option<Gc<Expr>>,
     pub vis: Visibility,
 }
 
@@ -984,7 +985,7 @@ pub enum ViewItem_ {
     // (containing arbitrary characters) from which to fetch the crate sources
     // For example, extern crate whatever = "github.com/mozilla/rust"
     ViewItemExternCrate(Ident, Option<(InternedString,StrStyle)>, NodeId),
-    ViewItemUse(@ViewPath),
+    ViewItemUse(Gc<ViewPath>),
 }
 
 // Meta-data associated with an item
@@ -1007,7 +1008,7 @@ pub struct AttrId(pub uint);
 pub struct Attribute_ {
     pub id: AttrId,
     pub style: AttrStyle,
-    pub value: @MetaItem,
+    pub value: Gc<MetaItem>,
     pub is_sugared_doc: bool,
 }
 
@@ -1105,18 +1106,18 @@ pub struct Item {
 
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
 pub enum Item_ {
-    ItemStatic(P<Ty>, Mutability, @Expr),
+    ItemStatic(P<Ty>, Mutability, Gc<Expr>),
     ItemFn(P<FnDecl>, FnStyle, Abi, Generics, P<Block>),
     ItemMod(Mod),
     ItemForeignMod(ForeignMod),
     ItemTy(P<Ty>, Generics),
     ItemEnum(EnumDef, Generics),
-    ItemStruct(@StructDef, Generics),
+    ItemStruct(Gc<StructDef>, Generics),
     ItemTrait(Generics, Sized, Vec<TraitRef> , Vec<TraitMethod> ),
     ItemImpl(Generics,
              Option<TraitRef>, // (optional) trait this impl implements
              P<Ty>, // self
-             Vec<@Method> ),
+             Vec<Gc<Method>>),
     // a macro invocation (which includes macro definition)
     ItemMac(Mac),
 }
@@ -1142,9 +1143,9 @@ pub enum ForeignItem_ {
 // that we trans.
 #[deriving(PartialEq, Eq, Encodable, Decodable, Hash)]
 pub enum InlinedItem {
-    IIItem(@Item),
-    IIMethod(DefId /* impl id */, bool /* is provided */, @Method),
-    IIForeign(@ForeignItem),
+    IIItem(Gc<Item>),
+    IIMethod(DefId /* impl id */, bool /* is provided */, Gc<Method>),
+    IIForeign(Gc<ForeignItem>),
 }
 
 #[cfg(test)]
diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs
index 9a7b4f7d949..d78c9c2edc3 100644
--- a/src/libsyntax/ast_map.rs
+++ b/src/libsyntax/ast_map.rs
@@ -20,9 +20,9 @@ use util::small_vector::SmallVector;
 
 use std::cell::RefCell;
 use std::fmt;
+use std::gc::Gc;
 use std::iter;
 use std::slice;
-use std::string::String;
 
 #[deriving(Clone, PartialEq)]
 pub enum PathElem {
@@ -94,22 +94,22 @@ pub fn path_to_str<PI: Iterator<PathElem>>(mut path: PI) -> String {
 
 #[deriving(Clone)]
 pub enum Node {
-    NodeItem(@Item),
-    NodeForeignItem(@ForeignItem),
-    NodeTraitMethod(@TraitMethod),
-    NodeMethod(@Method),
+    NodeItem(Gc<Item>),
+    NodeForeignItem(Gc<ForeignItem>),
+    NodeTraitMethod(Gc<TraitMethod>),
+    NodeMethod(Gc<Method>),
     NodeVariant(P<Variant>),
-    NodeExpr(@Expr),
-    NodeStmt(@Stmt),
-    NodeArg(@Pat),
-    NodeLocal(@Pat),
-    NodePat(@Pat),
+    NodeExpr(Gc<Expr>),
+    NodeStmt(Gc<Stmt>),
+    NodeArg(Gc<Pat>),
+    NodeLocal(Gc<Pat>),
+    NodePat(Gc<Pat>),
     NodeBlock(P<Block>),
 
     /// NodeStructCtor represents a tuple struct.
-    NodeStructCtor(@StructDef),
+    NodeStructCtor(Gc<StructDef>),
 
-    NodeLifetime(@Lifetime),
+    NodeLifetime(Gc<Lifetime>),
 }
 
 // The odd layout is to bring down the total size.
@@ -119,19 +119,19 @@ enum MapEntry {
     NotPresent,
 
     // All the node types, with a parent ID.
-    EntryItem(NodeId, @Item),
-    EntryForeignItem(NodeId, @ForeignItem),
-    EntryTraitMethod(NodeId, @TraitMethod),
-    EntryMethod(NodeId, @Method),
+    EntryItem(NodeId, Gc<Item>),
+    EntryForeignItem(NodeId, Gc<ForeignItem>),
+    EntryTraitMethod(NodeId, Gc<TraitMethod>),
+    EntryMethod(NodeId, Gc<Method>),
     EntryVariant(NodeId, P<Variant>),
-    EntryExpr(NodeId, @Expr),
-    EntryStmt(NodeId, @Stmt),
-    EntryArg(NodeId, @Pat),
-    EntryLocal(NodeId, @Pat),
-    EntryPat(NodeId, @Pat),
+    EntryExpr(NodeId, Gc<Expr>),
+    EntryStmt(NodeId, Gc<Stmt>),
+    EntryArg(NodeId, Gc<Pat>),
+    EntryLocal(NodeId, Gc<Pat>),
+    EntryPat(NodeId, Gc<Pat>),
     EntryBlock(NodeId, P<Block>),
-    EntryStructCtor(NodeId, @StructDef),
-    EntryLifetime(NodeId, @Lifetime),
+    EntryStructCtor(NodeId, Gc<StructDef>),
+    EntryLifetime(NodeId, Gc<Lifetime>),
 
     // Roots for node trees.
     RootCrate,
@@ -262,14 +262,14 @@ impl Map {
         }
     }
 
-    pub fn expect_item(&self, id: NodeId) -> @Item {
+    pub fn expect_item(&self, id: NodeId) -> Gc<Item> {
         match self.find(id) {
             Some(NodeItem(item)) => item,
             _ => fail!("expected item, found {}", self.node_to_str(id))
         }
     }
 
-    pub fn expect_struct(&self, id: NodeId) -> @StructDef {
+    pub fn expect_struct(&self, id: NodeId) -> Gc<StructDef> {
         match self.find(id) {
             Some(NodeItem(i)) => {
                 match i.node {
@@ -294,7 +294,7 @@ impl Map {
         }
     }
 
-    pub fn expect_foreign_item(&self, id: NodeId) -> @ForeignItem {
+    pub fn expect_foreign_item(&self, id: NodeId) -> Gc<ForeignItem> {
         match self.find(id) {
             Some(NodeForeignItem(item)) => item,
             _ => fail!("expected foreign item, found {}", self.node_to_str(id))
@@ -457,11 +457,11 @@ impl<'a, F: FoldOps> Folder for Ctx<'a, F> {
         self.fold_ops.new_span(span)
     }
 
-    fn fold_item(&mut self, i: @Item) -> SmallVector<@Item> {
+    fn fold_item(&mut self, i: Gc<Item>) -> SmallVector<Gc<Item>> {
         let parent = self.parent;
         self.parent = DUMMY_NODE_ID;
 
-        let i = fold::noop_fold_item(i, self).expect_one("expected one item");
+        let i = fold::noop_fold_item(&*i, self).expect_one("expected one item");
         assert_eq!(self.parent, i.id);
 
         match i.node {
@@ -476,16 +476,17 @@ impl<'a, F: FoldOps> Folder for Ctx<'a, F> {
                 }
             }
             ItemForeignMod(ref nm) => {
-                for &nitem in nm.items.iter() {
-                    self.insert(nitem.id, EntryForeignItem(self.parent, nitem));
+                for nitem in nm.items.iter() {
+                    self.insert(nitem.id, EntryForeignItem(self.parent,
+                                                           nitem.clone()));
                 }
             }
-            ItemStruct(struct_def, _) => {
+            ItemStruct(ref struct_def, _) => {
                 // If this is a tuple-like struct, register the constructor.
                 match struct_def.ctor_id {
                     Some(ctor_id) => {
                         self.insert(ctor_id, EntryStructCtor(self.parent,
-                                                             struct_def));
+                                                             struct_def.clone()));
                     }
                     None => {}
                 }
@@ -499,11 +500,11 @@ impl<'a, F: FoldOps> Folder for Ctx<'a, F> {
                     match *tm {
                         Required(ref m) => {
                             self.insert(m.id, EntryTraitMethod(self.parent,
-                                                               @(*tm).clone()));
+                                                               box(GC) (*tm).clone()));
                         }
                         Provided(m) => {
                             self.insert(m.id, EntryTraitMethod(self.parent,
-                                                               @Provided(m)));
+                                                               box(GC) Provided(m)));
                         }
                     }
                 }
@@ -517,7 +518,7 @@ impl<'a, F: FoldOps> Folder for Ctx<'a, F> {
         SmallVector::one(i)
     }
 
-    fn fold_pat(&mut self, pat: @Pat) -> @Pat {
+    fn fold_pat(&mut self, pat: Gc<Pat>) -> Gc<Pat> {
         let pat = fold::noop_fold_pat(pat, self);
         match pat.node {
             PatIdent(..) => {
@@ -532,7 +533,7 @@ impl<'a, F: FoldOps> Folder for Ctx<'a, F> {
         pat
     }
 
-    fn fold_expr(&mut self, expr: @Expr) -> @Expr {
+    fn fold_expr(&mut self, expr: Gc<Expr>) -> Gc<Expr> {
         let expr = fold::noop_fold_expr(expr, self);
 
         self.insert(expr.id, EntryExpr(self.parent, expr));
@@ -540,9 +541,9 @@ impl<'a, F: FoldOps> Folder for Ctx<'a, F> {
         expr
     }
 
-    fn fold_stmt(&mut self, stmt: &Stmt) -> SmallVector<@Stmt> {
+    fn fold_stmt(&mut self, stmt: &Stmt) -> SmallVector<Gc<Stmt>> {
         let stmt = fold::noop_fold_stmt(stmt, self).expect_one("expected one statement");
-        self.insert(ast_util::stmt_id(stmt), EntryStmt(self.parent, stmt));
+        self.insert(ast_util::stmt_id(&*stmt), EntryStmt(self.parent, stmt));
         SmallVector::one(stmt)
     }
 
@@ -555,10 +556,10 @@ impl<'a, F: FoldOps> Folder for Ctx<'a, F> {
         m
     }
 
-    fn fold_method(&mut self, m: @Method) -> @Method {
+    fn fold_method(&mut self, m: Gc<Method>) -> Gc<Method> {
         let parent = self.parent;
         self.parent = DUMMY_NODE_ID;
-        let m = fold::noop_fold_method(m, self);
+        let m = fold::noop_fold_method(&*m, self);
         assert_eq!(self.parent, m.id);
         self.parent = parent;
         m
@@ -580,7 +581,7 @@ impl<'a, F: FoldOps> Folder for Ctx<'a, F> {
 
     fn fold_lifetime(&mut self, lifetime: &Lifetime) -> Lifetime {
         let lifetime = fold::noop_fold_lifetime(lifetime, self);
-        self.insert(lifetime.id, EntryLifetime(self.parent, @lifetime));
+        self.insert(lifetime.id, EntryLifetime(self.parent, box(GC) lifetime));
         lifetime
     }
 }
@@ -643,7 +644,7 @@ pub fn map_decoded_item<F: FoldOps>(map: &Map,
         IIItem(_) => {}
         IIMethod(impl_did, is_provided, m) => {
             let entry = if is_provided {
-                EntryTraitMethod(cx.parent, @Provided(m))
+                EntryTraitMethod(cx.parent, box(GC) Provided(m))
             } else {
                 EntryMethod(cx.parent, m)
             };
@@ -701,28 +702,28 @@ fn node_id_to_str(map: &Map, id: NodeId) -> String {
                     token::get_ident(variant.node.name),
                     map.path_to_str(id), id)).to_string()
         }
-        Some(NodeExpr(expr)) => {
+        Some(NodeExpr(ref expr)) => {
             (format!("expr {} (id={})",
-                    pprust::expr_to_str(expr), id)).to_string()
+                    pprust::expr_to_str(&**expr), id)).to_string()
         }
-        Some(NodeStmt(stmt)) => {
+        Some(NodeStmt(ref stmt)) => {
             (format!("stmt {} (id={})",
-                    pprust::stmt_to_str(stmt), id)).to_string()
+                    pprust::stmt_to_str(&**stmt), id)).to_string()
         }
-        Some(NodeArg(pat)) => {
+        Some(NodeArg(ref pat)) => {
             (format!("arg {} (id={})",
-                    pprust::pat_to_str(pat), id)).to_string()
+                    pprust::pat_to_str(&**pat), id)).to_string()
         }
-        Some(NodeLocal(pat)) => {
+        Some(NodeLocal(ref pat)) => {
             (format!("local {} (id={})",
-                    pprust::pat_to_str(pat), id)).to_string()
+                    pprust::pat_to_str(&**pat), id)).to_string()
         }
-        Some(NodePat(pat)) => {
-            (format!("pat {} (id={})", pprust::pat_to_str(pat), id)).to_string()
+        Some(NodePat(ref pat)) => {
+            (format!("pat {} (id={})", pprust::pat_to_str(&**pat), id)).to_string()
         }
-        Some(NodeBlock(block)) => {
+        Some(NodeBlock(ref block)) => {
             (format!("block {} (id={})",
-                    pprust::block_to_str(block), id)).to_string()
+                    pprust::block_to_str(&**block), id)).to_string()
         }
         Some(NodeStructCtor(_)) => {
             (format!("struct_ctor {} (id={})",
@@ -730,7 +731,7 @@ fn node_id_to_str(map: &Map, id: NodeId) -> String {
         }
         Some(NodeLifetime(ref l)) => {
             (format!("lifetime {} (id={})",
-                    pprust::lifetime_to_str(*l), id)).to_string()
+                    pprust::lifetime_to_str(&**l), id)).to_string()
         }
         None => {
             (format!("unknown node (id={})", id)).to_string()
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index a1ad3cc14c5..fcddbfa9a89 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -21,7 +21,7 @@ use visit;
 
 use std::cell::Cell;
 use std::cmp;
-use std::string::String;
+use std::gc::Gc;
 use std::u32;
 
 pub fn path_name_i(idents: &[Ident]) -> String {
@@ -93,7 +93,7 @@ pub fn is_shift_binop(b: BinOp) -> bool {
 
 pub fn unop_to_str(op: UnOp) -> &'static str {
     match op {
-      UnBox => "@",
+      UnBox => "box(GC) ",
       UnUniq => "box() ",
       UnDeref => "*",
       UnNot => "!",
@@ -101,7 +101,7 @@ pub fn unop_to_str(op: UnOp) -> &'static str {
     }
 }
 
-pub fn is_path(e: @Expr) -> bool {
+pub fn is_path(e: Gc<Expr>) -> bool {
     return match e.node { ExprPath(_) => true, _ => false };
 }
 
@@ -181,11 +181,11 @@ pub fn float_ty_to_str(t: FloatTy) -> String {
     }
 }
 
-pub fn is_call_expr(e: @Expr) -> bool {
+pub fn is_call_expr(e: Gc<Expr>) -> bool {
     match e.node { ExprCall(..) => true, _ => false }
 }
 
-pub fn block_from_expr(e: @Expr) -> P<Block> {
+pub fn block_from_expr(e: Gc<Expr>) -> P<Block> {
     P(Block {
         view_items: Vec::new(),
         stmts: Vec::new(),
@@ -210,8 +210,8 @@ pub fn ident_to_path(s: Span, identifier: Ident) -> Path {
     }
 }
 
-pub fn ident_to_pat(id: NodeId, s: Span, i: Ident) -> @Pat {
-    @ast::Pat { id: id,
+pub fn ident_to_pat(id: NodeId, s: Span, i: Ident) -> Gc<Pat> {
+    box(GC) ast::Pat { id: id,
                 node: PatIdent(BindByValue(MutImmutable), ident_to_path(s, i), None),
                 span: s }
 }
@@ -229,7 +229,7 @@ pub fn is_unguarded(a: &Arm) -> bool {
     }
 }
 
-pub fn unguarded_pat(a: &Arm) -> Option<Vec<@Pat> > {
+pub fn unguarded_pat(a: &Arm) -> Option<Vec<Gc<Pat>>> {
     if is_unguarded(a) {
         Some(/* FIXME (#2543) */ a.pats.clone())
     } else {
@@ -254,7 +254,7 @@ pub fn impl_pretty_name(trait_ref: &Option<TraitRef>, ty: &Ty) -> Ident {
     token::gensym_ident(pretty.as_slice())
 }
 
-pub fn public_methods(ms: Vec<@Method> ) -> Vec<@Method> {
+pub fn public_methods(ms: Vec<Gc<Method>> ) -> Vec<Gc<Method>> {
     ms.move_iter().filter(|m| {
         match m.vis {
             Public => true,
@@ -285,7 +285,7 @@ pub fn trait_method_to_ty_method(method: &TraitMethod) -> TypeMethod {
 }
 
 pub fn split_trait_methods(trait_methods: &[TraitMethod])
-    -> (Vec<TypeMethod> , Vec<@Method> ) {
+    -> (Vec<TypeMethod> , Vec<Gc<Method>> ) {
     let mut reqd = Vec::new();
     let mut provd = Vec::new();
     for trt_method in trait_methods.iter() {
@@ -610,7 +610,7 @@ pub fn compute_id_range_for_fn_body(fk: &visit::FnKind,
     visitor.result.get()
 }
 
-pub fn is_item_impl(item: @ast::Item) -> bool {
+pub fn is_item_impl(item: Gc<ast::Item>) -> bool {
     match item.node {
         ItemImpl(..) => true,
         _            => false
@@ -623,20 +623,20 @@ pub fn walk_pat(pat: &Pat, it: |&Pat| -> bool) -> bool {
     }
 
     match pat.node {
-        PatIdent(_, _, Some(p)) => walk_pat(p, it),
+        PatIdent(_, _, Some(ref p)) => walk_pat(&**p, it),
         PatStruct(_, ref fields, _) => {
-            fields.iter().advance(|f| walk_pat(f.pat, |p| it(p)))
+            fields.iter().advance(|f| walk_pat(&*f.pat, |p| it(p)))
         }
         PatEnum(_, Some(ref s)) | PatTup(ref s) => {
-            s.iter().advance(|&p| walk_pat(p, |p| it(p)))
+            s.iter().advance(|p| walk_pat(&**p, |p| it(p)))
         }
-        PatBox(s) | PatRegion(s) => {
-            walk_pat(s, it)
+        PatBox(ref s) | PatRegion(ref s) => {
+            walk_pat(&**s, it)
         }
         PatVec(ref before, ref slice, ref after) => {
-            before.iter().advance(|&p| walk_pat(p, |p| it(p))) &&
-                slice.iter().advance(|&p| walk_pat(p, |p| it(p))) &&
-                after.iter().advance(|&p| walk_pat(p, |p| it(p)))
+            before.iter().advance(|p| walk_pat(&**p, |p| it(p))) &&
+                slice.iter().advance(|p| walk_pat(&**p, |p| it(p))) &&
+                after.iter().advance(|p| walk_pat(&**p, |p| it(p)))
         }
         PatMac(_) => fail!("attempted to analyze unexpanded pattern"),
         PatWild | PatWildMulti | PatLit(_) | PatRange(_, _) | PatIdent(_, _, _) |
@@ -685,7 +685,7 @@ pub fn struct_def_is_tuple_like(struct_def: &ast::StructDef) -> bool {
 
 /// Returns true if the given pattern consists solely of an identifier
 /// and false otherwise.
-pub fn pat_is_ident(pat: @ast::Pat) -> bool {
+pub fn pat_is_ident(pat: Gc<ast::Pat>) -> bool {
     match pat.node {
         ast::PatIdent(..) => true,
         _ => false,
@@ -720,7 +720,7 @@ pub fn segments_name_eq(a : &[ast::PathSegment], b : &[ast::PathSegment]) -> boo
 }
 
 // Returns true if this literal is a string and false otherwise.
-pub fn lit_is_str(lit: @Lit) -> bool {
+pub fn lit_is_str(lit: Gc<Lit>) -> bool {
     match lit.node {
         LitStr(..) => true,
         _ => false,
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index 6005513af11..83f1326c656 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -22,6 +22,7 @@ use crateid::CrateId;
 
 use std::collections::HashSet;
 use std::collections::BitvSet;
+use std::gc::Gc;
 
 local_data_key!(used_attrs: BitvSet)
 
@@ -52,7 +53,7 @@ pub trait AttrMetaMethods {
      */
     fn value_str(&self) -> Option<InternedString>;
     /// Gets a list of inner meta items from a list MetaItem type.
-    fn meta_item_list<'a>(&'a self) -> Option<&'a [@MetaItem]>;
+    fn meta_item_list<'a>(&'a self) -> Option<&'a [Gc<MetaItem>]>;
 }
 
 impl AttrMetaMethods for Attribute {
@@ -67,7 +68,7 @@ impl AttrMetaMethods for Attribute {
     fn value_str(&self) -> Option<InternedString> {
         self.meta().value_str()
     }
-    fn meta_item_list<'a>(&'a self) -> Option<&'a [@MetaItem]> {
+    fn meta_item_list<'a>(&'a self) -> Option<&'a [Gc<MetaItem>]> {
         self.node.value.meta_item_list()
     }
 }
@@ -93,7 +94,7 @@ impl AttrMetaMethods for MetaItem {
         }
     }
 
-    fn meta_item_list<'a>(&'a self) -> Option<&'a [@MetaItem]> {
+    fn meta_item_list<'a>(&'a self) -> Option<&'a [Gc<MetaItem>]> {
         match self.node {
             MetaList(_, ref l) => Some(l.as_slice()),
             _ => None
@@ -102,23 +103,23 @@ impl AttrMetaMethods for MetaItem {
 }
 
 // Annoying, but required to get test_cfg to work
-impl AttrMetaMethods for @MetaItem {
+impl AttrMetaMethods for Gc<MetaItem> {
     fn name(&self) -> InternedString { (**self).name() }
     fn value_str(&self) -> Option<InternedString> { (**self).value_str() }
-    fn meta_item_list<'a>(&'a self) -> Option<&'a [@MetaItem]> {
+    fn meta_item_list<'a>(&'a self) -> Option<&'a [Gc<MetaItem>]> {
         (**self).meta_item_list()
     }
 }
 
 
 pub trait AttributeMethods {
-    fn meta(&self) -> @MetaItem;
+    fn meta(&self) -> Gc<MetaItem>;
     fn desugar_doc(&self) -> Attribute;
 }
 
 impl AttributeMethods for Attribute {
     /// Extract the MetaItem from inside this Attribute.
-    fn meta(&self) -> @MetaItem {
+    fn meta(&self) -> Gc<MetaItem> {
         self.node.value
     }
 
@@ -146,22 +147,23 @@ impl AttributeMethods for Attribute {
 /* Constructors */
 
 pub fn mk_name_value_item_str(name: InternedString, value: InternedString)
-                              -> @MetaItem {
+                              -> Gc<MetaItem> {
     let value_lit = dummy_spanned(ast::LitStr(value, ast::CookedStr));
     mk_name_value_item(name, value_lit)
 }
 
 pub fn mk_name_value_item(name: InternedString, value: ast::Lit)
-                          -> @MetaItem {
-    @dummy_spanned(MetaNameValue(name, value))
+                          -> Gc<MetaItem> {
+    box(GC) dummy_spanned(MetaNameValue(name, value))
 }
 
-pub fn mk_list_item(name: InternedString, items: Vec<@MetaItem> ) -> @MetaItem {
-    @dummy_spanned(MetaList(name, items))
+pub fn mk_list_item(name: InternedString,
+                    items: Vec<Gc<MetaItem>>) -> Gc<MetaItem> {
+    box(GC) dummy_spanned(MetaList(name, items))
 }
 
-pub fn mk_word_item(name: InternedString) -> @MetaItem {
-    @dummy_spanned(MetaWord(name))
+pub fn mk_word_item(name: InternedString) -> Gc<MetaItem> {
+    box(GC) dummy_spanned(MetaWord(name))
 }
 
 local_data_key!(next_attr_id: uint)
@@ -173,7 +175,7 @@ pub fn mk_attr_id() -> AttrId {
 }
 
 /// Returns an inner attribute with the given value.
-pub fn mk_attr_inner(id: AttrId, item: @MetaItem) -> Attribute {
+pub fn mk_attr_inner(id: AttrId, item: Gc<MetaItem>) -> Attribute {
     dummy_spanned(Attribute_ {
         id: id,
         style: ast::AttrInner,
@@ -183,7 +185,7 @@ pub fn mk_attr_inner(id: AttrId, item: @MetaItem) -> Attribute {
 }
 
 /// Returns an outer attribute with the given value.
-pub fn mk_attr_outer(id: AttrId, item: @MetaItem) -> Attribute {
+pub fn mk_attr_outer(id: AttrId, item: Gc<MetaItem>) -> Attribute {
     dummy_spanned(Attribute_ {
         id: id,
         style: ast::AttrOuter,
@@ -200,7 +202,7 @@ pub fn mk_sugared_doc_attr(id: AttrId, text: InternedString, lo: BytePos,
     let attr = Attribute_ {
         id: id,
         style: style,
-        value: @spanned(lo, hi, MetaNameValue(InternedString::new("doc"),
+        value: box(GC) spanned(lo, hi, MetaNameValue(InternedString::new("doc"),
                                               lit)),
         is_sugared_doc: true
     };
@@ -211,8 +213,8 @@ pub fn mk_sugared_doc_attr(id: AttrId, text: InternedString, lo: BytePos,
 /// Check if `needle` occurs in `haystack` by a structural
 /// comparison. This is slightly subtle, and relies on ignoring the
 /// span included in the `==` comparison a plain MetaItem.
-pub fn contains(haystack: &[@ast::MetaItem],
-                needle: @ast::MetaItem) -> bool {
+pub fn contains(haystack: &[Gc<ast::MetaItem>],
+                needle: Gc<ast::MetaItem>) -> bool {
     debug!("attr::contains (name={})", needle.name());
     haystack.iter().any(|item| {
         debug!("  testing: {}", item.name());
@@ -235,7 +237,7 @@ pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: &str)
         .and_then(|at| at.value_str())
 }
 
-pub fn last_meta_item_value_str_by_name(items: &[@MetaItem], name: &str)
+pub fn last_meta_item_value_str_by_name(items: &[Gc<MetaItem>], name: &str)
                                      -> Option<InternedString> {
     items.iter()
          .rev()
@@ -245,12 +247,12 @@ pub fn last_meta_item_value_str_by_name(items: &[@MetaItem], name: &str)
 
 /* Higher-level applications */
 
-pub fn sort_meta_items(items: &[@MetaItem]) -> Vec<@MetaItem> {
+pub fn sort_meta_items(items: &[Gc<MetaItem>]) -> Vec<Gc<MetaItem>> {
     // This is sort of stupid here, but we need to sort by
     // human-readable strings.
     let mut v = items.iter()
         .map(|&mi| (mi.name(), mi))
-        .collect::<Vec<(InternedString, @MetaItem)> >();
+        .collect::<Vec<(InternedString, Gc<MetaItem>)> >();
 
     v.sort_by(|&(ref a, _), &(ref b, _)| a.cmp(b));
 
@@ -258,7 +260,7 @@ pub fn sort_meta_items(items: &[@MetaItem]) -> Vec<@MetaItem> {
     v.move_iter().map(|(_, m)| {
         match m.node {
             MetaList(ref n, ref mis) => {
-                @Spanned {
+                box(GC) Spanned {
                     node: MetaList((*n).clone(),
                                    sort_meta_items(mis.as_slice())),
                     .. /*bad*/ (*m).clone()
@@ -273,7 +275,7 @@ pub fn sort_meta_items(items: &[@MetaItem]) -> Vec<@MetaItem> {
  * From a list of crate attributes get only the meta_items that affect crate
  * linkage
  */
-pub fn find_linkage_metas(attrs: &[Attribute]) -> Vec<@MetaItem> {
+pub fn find_linkage_metas(attrs: &[Attribute]) -> Vec<Gc<MetaItem>> {
     let mut result = Vec::new();
     for attr in attrs.iter().filter(|at| at.check_name("link")) {
         match attr.meta().node {
@@ -330,7 +332,7 @@ pub fn find_inline_attr(attrs: &[Attribute]) -> InlineAttr {
 /// test_cfg(`[foo="a", bar]`, `[cfg(bar, foo="a")]`) == true
 /// test_cfg(`[foo="a", bar]`, `[cfg(bar, foo="b")]`) == false
 pub fn test_cfg<AM: AttrMetaMethods, It: Iterator<AM>>
-    (cfg: &[@MetaItem], mut metas: It) -> bool {
+    (cfg: &[Gc<MetaItem>], mut metas: It) -> bool {
     // having no #[cfg(...)] attributes counts as matching.
     let mut no_cfgs = true;
 
@@ -422,7 +424,7 @@ pub fn find_stability(attrs: &[Attribute]) -> Option<Stability> {
     })
 }
 
-pub fn require_unique_names(diagnostic: &SpanHandler, metas: &[@MetaItem]) {
+pub fn require_unique_names(diagnostic: &SpanHandler, metas: &[Gc<MetaItem>]) {
     let mut set = HashSet::new();
     for meta in metas.iter() {
         let name = meta.name();
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index f31d0d86940..d9e3e4e941d 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -23,8 +23,8 @@ source code snippets, etc.
 
 use serialize::{Encodable, Decodable, Encoder, Decoder};
 use std::cell::RefCell;
+use std::gc::Gc;
 use std::rc::Rc;
-use std::string::String;
 
 pub trait Pos {
     fn from_uint(n: uint) -> Self;
@@ -91,7 +91,7 @@ pub struct Span {
     pub hi: BytePos,
     /// Information about where the macro came from, if this piece of
     /// code was created by a macro expansion.
-    pub expn_info: Option<@ExpnInfo>
+    pub expn_info: Option<Gc<ExpnInfo>>
 }
 
 pub static DUMMY_SP: Span = Span { lo: BytePos(0), hi: BytePos(0), expn_info: None };
diff --git a/src/libsyntax/ext/asm.rs b/src/libsyntax/ext/asm.rs
index 06916d5ac09..665d9da664d 100644
--- a/src/libsyntax/ext/asm.rs
+++ b/src/libsyntax/ext/asm.rs
@@ -20,7 +20,6 @@ use parse;
 use parse::token::InternedString;
 use parse::token;
 
-
 enum State {
     Asm,
     Outputs,
@@ -214,7 +213,7 @@ pub fn expand_asm(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                                                  out));
     }
 
-    MacExpr::new(@ast::Expr {
+    MacExpr::new(box(GC) ast::Expr {
         id: ast::DUMMY_NODE_ID,
         node: ast::ExprInlineAsm(ast::InlineAsm {
             asm: token::intern_and_get_ident(asm.get()),
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index b656b0c06a0..f9a9e276eb0 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -20,6 +20,7 @@ use parse::token::{InternedString, intern, str_to_ident};
 use util::small_vector::SmallVector;
 
 use std::collections::HashMap;
+use std::gc::Gc;
 
 // new-style macro! tt code:
 //
@@ -35,10 +36,10 @@ pub struct MacroDef {
 }
 
 pub type ItemDecorator =
-    fn(&mut ExtCtxt, Span, @ast::MetaItem, @ast::Item, |@ast::Item|);
+    fn(&mut ExtCtxt, Span, Gc<ast::MetaItem>, Gc<ast::Item>, |Gc<ast::Item>|);
 
 pub type ItemModifier =
-    fn(&mut ExtCtxt, Span, @ast::MetaItem, @ast::Item) -> @ast::Item;
+    fn(&mut ExtCtxt, Span, Gc<ast::MetaItem>, Gc<ast::Item>) -> Gc<ast::Item>;
 
 pub struct BasicMacroExpander {
     pub expander: MacroExpanderFn,
@@ -104,11 +105,11 @@ pub trait MacResult {
         None
     }
     /// Create an expression.
-    fn make_expr(&self) -> Option<@ast::Expr> {
+    fn make_expr(&self) -> Option<Gc<ast::Expr>> {
         None
     }
     /// Create zero or more items.
-    fn make_items(&self) -> Option<SmallVector<@ast::Item>> {
+    fn make_items(&self) -> Option<SmallVector<Gc<ast::Item>>> {
         None
     }
     /// Create a pattern.
@@ -120,23 +121,23 @@ pub trait MacResult {
     ///
     /// By default this attempts to create an expression statement,
     /// returning None if that fails.
-    fn make_stmt(&self) -> Option<@ast::Stmt> {
+    fn make_stmt(&self) -> Option<Gc<ast::Stmt>> {
         self.make_expr()
-            .map(|e| @codemap::respan(e.span, ast::StmtExpr(e, ast::DUMMY_NODE_ID)))
+            .map(|e| box(GC) codemap::respan(e.span, ast::StmtExpr(e, ast::DUMMY_NODE_ID)))
     }
 }
 
 /// A convenience type for macros that return a single expression.
 pub struct MacExpr {
-    e: @ast::Expr
+    e: Gc<ast::Expr>,
 }
 impl MacExpr {
-    pub fn new(e: @ast::Expr) -> Box<MacResult> {
+    pub fn new(e: Gc<ast::Expr>) -> Box<MacResult> {
         box MacExpr { e: e } as Box<MacResult>
     }
 }
 impl MacResult for MacExpr {
-    fn make_expr(&self) -> Option<@ast::Expr> {
+    fn make_expr(&self) -> Option<Gc<ast::Expr>> {
         Some(self.e)
     }
 }
@@ -156,22 +157,22 @@ impl MacResult for MacPat {
 }
 /// A convenience type for macros that return a single item.
 pub struct MacItem {
-    i: @ast::Item
+    i: Gc<ast::Item>
 }
 impl MacItem {
-    pub fn new(i: @ast::Item) -> Box<MacResult> {
+    pub fn new(i: Gc<ast::Item>) -> Box<MacResult> {
         box MacItem { i: i } as Box<MacResult>
     }
 }
 impl MacResult for MacItem {
-    fn make_items(&self) -> Option<SmallVector<@ast::Item>> {
+    fn make_items(&self) -> Option<SmallVector<Gc<ast::Item>>> {
         Some(SmallVector::one(self.i))
     }
-    fn make_stmt(&self) -> Option<@ast::Stmt> {
-        Some(@codemap::respan(
+    fn make_stmt(&self) -> Option<Gc<ast::Stmt>> {
+        Some(box(GC) codemap::respan(
             self.i.span,
             ast::StmtDecl(
-                @codemap::respan(self.i.span, ast::DeclItem(self.i)),
+                box(GC) codemap::respan(self.i.span, ast::DeclItem(self.i)),
                 ast::DUMMY_NODE_ID)))
     }
 }
@@ -202,10 +203,10 @@ impl DummyResult {
     }
 
     /// A plain dummy expression.
-    pub fn raw_expr(sp: Span) -> @ast::Expr {
-        @ast::Expr {
+    pub fn raw_expr(sp: Span) -> Gc<ast::Expr> {
+        box(GC) ast::Expr {
             id: ast::DUMMY_NODE_ID,
-            node: ast::ExprLit(@codemap::respan(sp, ast::LitNil)),
+            node: ast::ExprLit(box(GC) codemap::respan(sp, ast::LitNil)),
             span: sp,
         }
     }
@@ -221,21 +222,21 @@ impl DummyResult {
 }
 
 impl MacResult for DummyResult {
-    fn make_expr(&self) -> Option<@ast::Expr> {
+    fn make_expr(&self) -> Option<Gc<ast::Expr>> {
         Some(DummyResult::raw_expr(self.span))
     }
-    fn make_pat(&self) -> Option<@ast::Pat> {
+    fn make_pat(&self) -> Option<Gc<ast::Pat>> {
         Some(DummyResult::raw_pat(self.span))
     }
-    fn make_items(&self) -> Option<SmallVector<@ast::Item>> {
+    fn make_items(&self) -> Option<SmallVector<Gc<ast::Item>>> {
         if self.expr_only {
             None
         } else {
             Some(SmallVector::zero())
         }
     }
-    fn make_stmt(&self) -> Option<@ast::Stmt> {
-        Some(@codemap::respan(self.span,
+    fn make_stmt(&self) -> Option<Gc<ast::Stmt>> {
+        Some(box(GC) codemap::respan(self.span,
                               ast::StmtExpr(DummyResult::raw_expr(self.span),
                                             ast::DUMMY_NODE_ID)))
     }
@@ -397,7 +398,7 @@ pub fn syntax_expander_table() -> SyntaxEnv {
 pub struct ExtCtxt<'a> {
     pub parse_sess: &'a parse::ParseSess,
     pub cfg: ast::CrateConfig,
-    pub backtrace: Option<@ExpnInfo>,
+    pub backtrace: Option<Gc<ExpnInfo>>,
     pub ecfg: expand::ExpansionConfig,
 
     pub mod_path: Vec<ast::Ident> ,
@@ -417,7 +418,7 @@ impl<'a> ExtCtxt<'a> {
         }
     }
 
-    pub fn expand_expr(&mut self, mut e: @ast::Expr) -> @ast::Expr {
+    pub fn expand_expr(&mut self, mut e: Gc<ast::Expr>) -> Gc<ast::Expr> {
         loop {
             match e.node {
                 ast::ExprMac(..) => {
@@ -442,7 +443,7 @@ impl<'a> ExtCtxt<'a> {
         }
     }
     pub fn print_backtrace(&self) { }
-    pub fn backtrace(&self) -> Option<@ExpnInfo> { self.backtrace }
+    pub fn backtrace(&self) -> Option<Gc<ExpnInfo>> { self.backtrace }
     pub fn mod_push(&mut self, i: ast::Ident) { self.mod_path.push(i); }
     pub fn mod_pop(&mut self) { self.mod_path.pop().unwrap(); }
     pub fn mod_path(&self) -> Vec<ast::Ident> {
@@ -455,9 +456,9 @@ impl<'a> ExtCtxt<'a> {
         match ei {
             ExpnInfo {call_site: cs, callee: ref callee} => {
                 self.backtrace =
-                    Some(@ExpnInfo {
+                    Some(box(GC) ExpnInfo {
                         call_site: Span {lo: cs.lo, hi: cs.hi,
-                                         expn_info: self.backtrace},
+                                         expn_info: self.backtrace.clone()},
                         callee: (*callee).clone()
                     });
             }
@@ -528,7 +529,7 @@ impl<'a> ExtCtxt<'a> {
 /// Extract a string literal from the macro expanded version of `expr`,
 /// emitting `err_msg` if `expr` is not a string literal. This does not stop
 /// compilation on error, merely emits a non-fatal error and returns None.
-pub fn expr_to_str(cx: &mut ExtCtxt, expr: @ast::Expr, err_msg: &str)
+pub fn expr_to_str(cx: &mut ExtCtxt, expr: Gc<ast::Expr>, err_msg: &str)
                    -> Option<(InternedString, ast::StrStyle)> {
     // we want to be able to handle e.g. concat("foo", "bar")
     let expr = cx.expand_expr(expr);
@@ -584,7 +585,7 @@ pub fn get_single_str_from_tts(cx: &ExtCtxt,
 /// parsing error, emit a non-fatal error and return None.
 pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
                           sp: Span,
-                          tts: &[ast::TokenTree]) -> Option<Vec<@ast::Expr> > {
+                          tts: &[ast::TokenTree]) -> Option<Vec<Gc<ast::Expr>>> {
     let mut p = parse::new_parser_from_tts(cx.parse_sess(),
                                            cx.cfg(),
                                            tts.iter()
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 14769e3e510..148b653b61c 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -21,6 +21,8 @@ use parse::token::special_idents;
 use parse::token::InternedString;
 use parse::token;
 
+use std::gc::Gc;
+
 // Transitional reexports so qquote can find the paths it is looking for
 mod syntax {
     pub use ext;
@@ -73,115 +75,129 @@ pub trait AstBuilder {
     fn lifetime(&self, span: Span, ident: ast::Name) -> ast::Lifetime;
 
     // statements
-    fn stmt_expr(&self, expr: @ast::Expr) -> @ast::Stmt;
-    fn stmt_let(&self, sp: Span, mutbl: bool, ident: ast::Ident, ex: @ast::Expr) -> @ast::Stmt;
+    fn stmt_expr(&self, expr: Gc<ast::Expr>) -> Gc<ast::Stmt>;
+    fn stmt_let(&self, sp: Span, mutbl: bool, ident: ast::Ident,
+                ex: Gc<ast::Expr>) -> Gc<ast::Stmt>;
     fn stmt_let_typed(&self,
                       sp: Span,
                       mutbl: bool,
                       ident: ast::Ident,
                       typ: P<ast::Ty>,
-                      ex: @ast::Expr)
-                      -> @ast::Stmt;
+                      ex: Gc<ast::Expr>)
+                      -> Gc<ast::Stmt>;
 
     // blocks
-    fn block(&self, span: Span, stmts: Vec<@ast::Stmt> , expr: Option<@ast::Expr>) -> P<ast::Block>;
-    fn block_expr(&self, expr: @ast::Expr) -> P<ast::Block>;
+    fn block(&self, span: Span, stmts: Vec<Gc<ast::Stmt>>,
+             expr: Option<Gc<ast::Expr>>) -> P<ast::Block>;
+    fn block_expr(&self, expr: Gc<ast::Expr>) -> P<ast::Block>;
     fn block_all(&self, span: Span,
                  view_items: Vec<ast::ViewItem> ,
-                 stmts: Vec<@ast::Stmt> ,
-                 expr: Option<@ast::Expr>) -> P<ast::Block>;
+                 stmts: Vec<Gc<ast::Stmt>> ,
+                 expr: Option<Gc<ast::Expr>>) -> P<ast::Block>;
 
     // expressions
-    fn expr(&self, span: Span, node: ast::Expr_) -> @ast::Expr;
-    fn expr_path(&self, path: ast::Path) -> @ast::Expr;
-    fn expr_ident(&self, span: Span, id: ast::Ident) -> @ast::Expr;
+    fn expr(&self, span: Span, node: ast::Expr_) -> Gc<ast::Expr>;
+    fn expr_path(&self, path: ast::Path) -> Gc<ast::Expr>;
+    fn expr_ident(&self, span: Span, id: ast::Ident) -> Gc<ast::Expr>;
 
-    fn expr_self(&self, span: Span) -> @ast::Expr;
+    fn expr_self(&self, span: Span) -> Gc<ast::Expr>;
     fn expr_binary(&self, sp: Span, op: ast::BinOp,
-                   lhs: @ast::Expr, rhs: @ast::Expr) -> @ast::Expr;
-    fn expr_deref(&self, sp: Span, e: @ast::Expr) -> @ast::Expr;
-    fn expr_unary(&self, sp: Span, op: ast::UnOp, e: @ast::Expr) -> @ast::Expr;
-
-    fn expr_managed(&self, sp: Span, e: @ast::Expr) -> @ast::Expr;
-    fn expr_addr_of(&self, sp: Span, e: @ast::Expr) -> @ast::Expr;
-    fn expr_mut_addr_of(&self, sp: Span, e: @ast::Expr) -> @ast::Expr;
-    fn expr_field_access(&self, span: Span, expr: @ast::Expr, ident: ast::Ident) -> @ast::Expr;
-    fn expr_call(&self, span: Span, expr: @ast::Expr, args: Vec<@ast::Expr> ) -> @ast::Expr;
-    fn expr_call_ident(&self, span: Span, id: ast::Ident, args: Vec<@ast::Expr> ) -> @ast::Expr;
+                   lhs: Gc<ast::Expr>, rhs: Gc<ast::Expr>) -> Gc<ast::Expr>;
+    fn expr_deref(&self, sp: Span, e: Gc<ast::Expr>) -> Gc<ast::Expr>;
+    fn expr_unary(&self, sp: Span, op: ast::UnOp, e: Gc<ast::Expr>) -> Gc<ast::Expr>;
+
+    fn expr_managed(&self, sp: Span, e: Gc<ast::Expr>) -> Gc<ast::Expr>;
+    fn expr_addr_of(&self, sp: Span, e: Gc<ast::Expr>) -> Gc<ast::Expr>;
+    fn expr_mut_addr_of(&self, sp: Span, e: Gc<ast::Expr>) -> Gc<ast::Expr>;
+    fn expr_field_access(&self, span: Span, expr: Gc<ast::Expr>,
+                         ident: ast::Ident) -> Gc<ast::Expr>;
+    fn expr_call(&self, span: Span, expr: Gc<ast::Expr>,
+                 args: Vec<Gc<ast::Expr>>) -> Gc<ast::Expr>;
+    fn expr_call_ident(&self, span: Span, id: ast::Ident,
+                       args: Vec<Gc<ast::Expr>>) -> Gc<ast::Expr>;
     fn expr_call_global(&self, sp: Span, fn_path: Vec<ast::Ident> ,
-                        args: Vec<@ast::Expr> ) -> @ast::Expr;
+                        args: Vec<Gc<ast::Expr>>) -> Gc<ast::Expr>;
     fn expr_method_call(&self, span: Span,
-                        expr: @ast::Expr, ident: ast::Ident,
-                        args: Vec<@ast::Expr> ) -> @ast::Expr;
-    fn expr_block(&self, b: P<ast::Block>) -> @ast::Expr;
-    fn expr_cast(&self, sp: Span, expr: @ast::Expr, ty: P<ast::Ty>) -> @ast::Expr;
-
-    fn field_imm(&self, span: Span, name: Ident, e: @ast::Expr) -> ast::Field;
-    fn expr_struct(&self, span: Span, path: ast::Path, fields: Vec<ast::Field> ) -> @ast::Expr;
-    fn expr_struct_ident(&self, span: Span, id: ast::Ident, fields: Vec<ast::Field> ) -> @ast::Expr;
-
-    fn expr_lit(&self, sp: Span, lit: ast::Lit_) -> @ast::Expr;
-
-    fn expr_uint(&self, span: Span, i: uint) -> @ast::Expr;
-    fn expr_int(&self, sp: Span, i: int) -> @ast::Expr;
-    fn expr_u8(&self, sp: Span, u: u8) -> @ast::Expr;
-    fn expr_bool(&self, sp: Span, value: bool) -> @ast::Expr;
-
-    fn expr_vstore(&self, sp: Span, expr: @ast::Expr, vst: ast::ExprVstore) -> @ast::Expr;
-    fn expr_vec(&self, sp: Span, exprs: Vec<@ast::Expr> ) -> @ast::Expr;
-    fn expr_vec_ng(&self, sp: Span) -> @ast::Expr;
-    fn expr_vec_slice(&self, sp: Span, exprs: Vec<@ast::Expr> ) -> @ast::Expr;
-    fn expr_str(&self, sp: Span, s: InternedString) -> @ast::Expr;
-    fn expr_str_uniq(&self, sp: Span, s: InternedString) -> @ast::Expr;
-
-    fn expr_some(&self, sp: Span, expr: @ast::Expr) -> @ast::Expr;
-    fn expr_none(&self, sp: Span) -> @ast::Expr;
-
-    fn expr_fail(&self, span: Span, msg: InternedString) -> @ast::Expr;
-    fn expr_unreachable(&self, span: Span) -> @ast::Expr;
-
-    fn expr_ok(&self, span: Span, expr: @ast::Expr) -> @ast::Expr;
-    fn expr_err(&self, span: Span, expr: @ast::Expr) -> @ast::Expr;
-    fn expr_try(&self, span: Span, head: @ast::Expr) -> @ast::Expr;
-
-    fn pat(&self, span: Span, pat: ast::Pat_) -> @ast::Pat;
-    fn pat_wild(&self, span: Span) -> @ast::Pat;
-    fn pat_lit(&self, span: Span, expr: @ast::Expr) -> @ast::Pat;
-    fn pat_ident(&self, span: Span, ident: ast::Ident) -> @ast::Pat;
+                        expr: Gc<ast::Expr>, ident: ast::Ident,
+                        args: Vec<Gc<ast::Expr>> ) -> Gc<ast::Expr>;
+    fn expr_block(&self, b: P<ast::Block>) -> Gc<ast::Expr>;
+    fn expr_cast(&self, sp: Span, expr: Gc<ast::Expr>,
+                 ty: P<ast::Ty>) -> Gc<ast::Expr>;
+
+    fn field_imm(&self, span: Span, name: Ident, e: Gc<ast::Expr>) -> ast::Field;
+    fn expr_struct(&self, span: Span, path: ast::Path,
+                   fields: Vec<ast::Field> ) -> Gc<ast::Expr>;
+    fn expr_struct_ident(&self, span: Span, id: ast::Ident,
+                         fields: Vec<ast::Field> ) -> Gc<ast::Expr>;
+
+    fn expr_lit(&self, sp: Span, lit: ast::Lit_) -> Gc<ast::Expr>;
+
+    fn expr_uint(&self, span: Span, i: uint) -> Gc<ast::Expr>;
+    fn expr_int(&self, sp: Span, i: int) -> Gc<ast::Expr>;
+    fn expr_u8(&self, sp: Span, u: u8) -> Gc<ast::Expr>;
+    fn expr_bool(&self, sp: Span, value: bool) -> Gc<ast::Expr>;
+
+    fn expr_vstore(&self, sp: Span, expr: Gc<ast::Expr>, vst: ast::ExprVstore) -> Gc<ast::Expr>;
+    fn expr_vec(&self, sp: Span, exprs: Vec<Gc<ast::Expr>> ) -> Gc<ast::Expr>;
+    fn expr_vec_ng(&self, sp: Span) -> Gc<ast::Expr>;
+    fn expr_vec_slice(&self, sp: Span, exprs: Vec<Gc<ast::Expr>> ) -> Gc<ast::Expr>;
+    fn expr_str(&self, sp: Span, s: InternedString) -> Gc<ast::Expr>;
+    fn expr_str_uniq(&self, sp: Span, s: InternedString) -> Gc<ast::Expr>;
+
+    fn expr_some(&self, sp: Span, expr: Gc<ast::Expr>) -> Gc<ast::Expr>;
+    fn expr_none(&self, sp: Span) -> Gc<ast::Expr>;
+
+    fn expr_fail(&self, span: Span, msg: InternedString) -> Gc<ast::Expr>;
+    fn expr_unreachable(&self, span: Span) -> Gc<ast::Expr>;
+
+    fn expr_ok(&self, span: Span, expr: Gc<ast::Expr>) -> Gc<ast::Expr>;
+    fn expr_err(&self, span: Span, expr: Gc<ast::Expr>) -> Gc<ast::Expr>;
+    fn expr_try(&self, span: Span, head: Gc<ast::Expr>) -> Gc<ast::Expr>;
+
+    fn pat(&self, span: Span, pat: ast::Pat_) -> Gc<ast::Pat>;
+    fn pat_wild(&self, span: Span) -> Gc<ast::Pat>;
+    fn pat_lit(&self, span: Span, expr: Gc<ast::Expr>) -> Gc<ast::Pat>;
+    fn pat_ident(&self, span: Span, ident: ast::Ident) -> Gc<ast::Pat>;
 
     fn pat_ident_binding_mode(&self,
                               span: Span,
                               ident: ast::Ident,
-                              bm: ast::BindingMode) -> @ast::Pat;
-    fn pat_enum(&self, span: Span, path: ast::Path, subpats: Vec<@ast::Pat> ) -> @ast::Pat;
+                              bm: ast::BindingMode) -> Gc<ast::Pat>;
+    fn pat_enum(&self, span: Span, path: ast::Path,
+                subpats: Vec<Gc<ast::Pat>>) -> Gc<ast::Pat>;
     fn pat_struct(&self, span: Span,
-                  path: ast::Path, field_pats: Vec<ast::FieldPat> ) -> @ast::Pat;
+                  path: ast::Path, field_pats: Vec<ast::FieldPat> ) -> Gc<ast::Pat>;
 
-    fn arm(&self, span: Span, pats: Vec<@ast::Pat> , expr: @ast::Expr) -> ast::Arm;
+    fn arm(&self, span: Span, pats: Vec<Gc<ast::Pat>> , expr: Gc<ast::Expr>) -> ast::Arm;
     fn arm_unreachable(&self, span: Span) -> ast::Arm;
 
-    fn expr_match(&self, span: Span, arg: @ast::Expr, arms: Vec<ast::Arm> ) -> @ast::Expr;
+    fn expr_match(&self, span: Span, arg: Gc<ast::Expr>, arms: Vec<ast::Arm> ) -> Gc<ast::Expr>;
     fn expr_if(&self, span: Span,
-               cond: @ast::Expr, then: @ast::Expr, els: Option<@ast::Expr>) -> @ast::Expr;
+               cond: Gc<ast::Expr>, then: Gc<ast::Expr>,
+               els: Option<Gc<ast::Expr>>) -> Gc<ast::Expr>;
 
     fn lambda_fn_decl(&self, span: Span,
-                      fn_decl: P<ast::FnDecl>, blk: P<ast::Block>) -> @ast::Expr;
+                      fn_decl: P<ast::FnDecl>, blk: P<ast::Block>) -> Gc<ast::Expr>;
 
-    fn lambda(&self, span: Span, ids: Vec<ast::Ident> , blk: P<ast::Block>) -> @ast::Expr;
-    fn lambda0(&self, span: Span, blk: P<ast::Block>) -> @ast::Expr;
-    fn lambda1(&self, span: Span, blk: P<ast::Block>, ident: ast::Ident) -> @ast::Expr;
+    fn lambda(&self, span: Span, ids: Vec<ast::Ident> , blk: P<ast::Block>) -> Gc<ast::Expr>;
+    fn lambda0(&self, span: Span, blk: P<ast::Block>) -> Gc<ast::Expr>;
+    fn lambda1(&self, span: Span, blk: P<ast::Block>, ident: ast::Ident) -> Gc<ast::Expr>;
 
-    fn lambda_expr(&self, span: Span, ids: Vec<ast::Ident> , blk: @ast::Expr) -> @ast::Expr;
-    fn lambda_expr_0(&self, span: Span, expr: @ast::Expr) -> @ast::Expr;
-    fn lambda_expr_1(&self, span: Span, expr: @ast::Expr, ident: ast::Ident) -> @ast::Expr;
+    fn lambda_expr(&self, span: Span, ids: Vec<ast::Ident> , blk: Gc<ast::Expr>) -> Gc<ast::Expr>;
+    fn lambda_expr_0(&self, span: Span, expr: Gc<ast::Expr>) -> Gc<ast::Expr>;
+    fn lambda_expr_1(&self, span: Span, expr: Gc<ast::Expr>, ident: ast::Ident) -> Gc<ast::Expr>;
 
-    fn lambda_stmts(&self, span: Span, ids: Vec<ast::Ident> , blk: Vec<@ast::Stmt> ) -> @ast::Expr;
-    fn lambda_stmts_0(&self, span: Span, stmts: Vec<@ast::Stmt> ) -> @ast::Expr;
-    fn lambda_stmts_1(&self, span: Span, stmts: Vec<@ast::Stmt> , ident: ast::Ident) -> @ast::Expr;
+    fn lambda_stmts(&self, span: Span, ids: Vec<ast::Ident>,
+                    blk: Vec<Gc<ast::Stmt>>) -> Gc<ast::Expr>;
+    fn lambda_stmts_0(&self, span: Span,
+                      stmts: Vec<Gc<ast::Stmt>>) -> Gc<ast::Expr>;
+    fn lambda_stmts_1(&self, span: Span,
+                      stmts: Vec<Gc<ast::Stmt>>, ident: ast::Ident) -> Gc<ast::Expr>;
 
     // items
     fn item(&self, span: Span,
-            name: Ident, attrs: Vec<ast::Attribute> , node: ast::Item_) -> @ast::Item;
+            name: Ident, attrs: Vec<ast::Attribute>,
+            node: ast::Item_) -> Gc<ast::Item>;
 
     fn arg(&self, span: Span, name: Ident, ty: P<ast::Ty>) -> ast::Arg;
     // FIXME unused self
@@ -193,56 +209,59 @@ pub trait AstBuilder {
                     inputs: Vec<ast::Arg> ,
                     output: P<ast::Ty>,
                     generics: Generics,
-                    body: P<ast::Block>) -> @ast::Item;
+                    body: P<ast::Block>) -> Gc<ast::Item>;
     fn item_fn(&self,
                span: Span,
                name: Ident,
                inputs: Vec<ast::Arg> ,
                output: P<ast::Ty>,
-               body: P<ast::Block>) -> @ast::Item;
+               body: P<ast::Block>) -> Gc<ast::Item>;
 
     fn variant(&self, span: Span, name: Ident, tys: Vec<P<ast::Ty>> ) -> ast::Variant;
     fn item_enum_poly(&self,
                       span: Span,
                       name: Ident,
                       enum_definition: ast::EnumDef,
-                      generics: Generics) -> @ast::Item;
-    fn item_enum(&self, span: Span, name: Ident, enum_def: ast::EnumDef) -> @ast::Item;
+                      generics: Generics) -> Gc<ast::Item>;
+    fn item_enum(&self, span: Span, name: Ident,
+                 enum_def: ast::EnumDef) -> Gc<ast::Item>;
 
     fn item_struct_poly(&self,
                         span: Span,
                         name: Ident,
                         struct_def: ast::StructDef,
-                        generics: Generics) -> @ast::Item;
-    fn item_struct(&self, span: Span, name: Ident, struct_def: ast::StructDef) -> @ast::Item;
+                        generics: Generics) -> Gc<ast::Item>;
+    fn item_struct(&self, span: Span, name: Ident,
+                   struct_def: ast::StructDef) -> Gc<ast::Item>;
 
     fn item_mod(&self, span: Span, inner_span: Span,
-                name: Ident, attrs: Vec<ast::Attribute> ,
-                vi: Vec<ast::ViewItem> , items: Vec<@ast::Item> ) -> @ast::Item;
+                name: Ident, attrs: Vec<ast::Attribute>,
+                vi: Vec<ast::ViewItem>,
+                items: Vec<Gc<ast::Item>>) -> Gc<ast::Item>;
 
     fn item_ty_poly(&self,
                     span: Span,
                     name: Ident,
                     ty: P<ast::Ty>,
-                    generics: Generics) -> @ast::Item;
-    fn item_ty(&self, span: Span, name: Ident, ty: P<ast::Ty>) -> @ast::Item;
+                    generics: Generics) -> Gc<ast::Item>;
+    fn item_ty(&self, span: Span, name: Ident, ty: P<ast::Ty>) -> Gc<ast::Item>;
 
-    fn attribute(&self, sp: Span, mi: @ast::MetaItem) -> ast::Attribute;
+    fn attribute(&self, sp: Span, mi: Gc<ast::MetaItem>) -> ast::Attribute;
 
-    fn meta_word(&self, sp: Span, w: InternedString) -> @ast::MetaItem;
+    fn meta_word(&self, sp: Span, w: InternedString) -> Gc<ast::MetaItem>;
     fn meta_list(&self,
                  sp: Span,
                  name: InternedString,
-                 mis: Vec<@ast::MetaItem> )
-                 -> @ast::MetaItem;
+                 mis: Vec<Gc<ast::MetaItem>>)
+                 -> Gc<ast::MetaItem>;
     fn meta_name_value(&self,
                        sp: Span,
                        name: InternedString,
                        value: ast::Lit_)
-                       -> @ast::MetaItem;
+                       -> Gc<ast::MetaItem>;
 
     fn view_use(&self, sp: Span,
-                vis: ast::Visibility, vp: @ast::ViewPath) -> ast::ViewItem;
+                vis: ast::Visibility, vp: Gc<ast::ViewPath>) -> ast::ViewItem;
     fn view_use_simple(&self, sp: Span, vis: ast::Visibility, path: ast::Path) -> ast::ViewItem;
     fn view_use_simple_(&self, sp: Span, vis: ast::Visibility,
                         ident: ast::Ident, path: ast::Path) -> ast::ViewItem;
@@ -418,17 +437,18 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         ast::Lifetime { id: ast::DUMMY_NODE_ID, span: span, name: name }
     }
 
-    fn stmt_expr(&self, expr: @ast::Expr) -> @ast::Stmt {
-        @respan(expr.span, ast::StmtSemi(expr, ast::DUMMY_NODE_ID))
+    fn stmt_expr(&self, expr: Gc<ast::Expr>) -> Gc<ast::Stmt> {
+        box(GC) respan(expr.span, ast::StmtSemi(expr, ast::DUMMY_NODE_ID))
     }
 
-    fn stmt_let(&self, sp: Span, mutbl: bool, ident: ast::Ident, ex: @ast::Expr) -> @ast::Stmt {
+    fn stmt_let(&self, sp: Span, mutbl: bool, ident: ast::Ident,
+                ex: Gc<ast::Expr>) -> Gc<ast::Stmt> {
         let pat = if mutbl {
             self.pat_ident_binding_mode(sp, ident, ast::BindByValue(ast::MutMutable))
         } else {
             self.pat_ident(sp, ident)
         };
-        let local = @ast::Local {
+        let local = box(GC) ast::Local {
             ty: self.ty_infer(sp),
             pat: pat,
             init: Some(ex),
@@ -437,7 +457,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
             source: ast::LocalLet,
         };
         let decl = respan(sp, ast::DeclLocal(local));
-        @respan(sp, ast::StmtDecl(@decl, ast::DUMMY_NODE_ID))
+        box(GC) respan(sp, ast::StmtDecl(box(GC) decl, ast::DUMMY_NODE_ID))
     }
 
     fn stmt_let_typed(&self,
@@ -445,14 +465,14 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
                       mutbl: bool,
                       ident: ast::Ident,
                       typ: P<ast::Ty>,
-                      ex: @ast::Expr)
-                      -> @ast::Stmt {
+                      ex: Gc<ast::Expr>)
+                      -> Gc<ast::Stmt> {
         let pat = if mutbl {
             self.pat_ident_binding_mode(sp, ident, ast::BindByValue(ast::MutMutable))
         } else {
             self.pat_ident(sp, ident)
         };
-        let local = @ast::Local {
+        let local = box(GC) ast::Local {
             ty: typ,
             pat: pat,
             init: Some(ex),
@@ -461,21 +481,22 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
             source: ast::LocalLet,
         };
         let decl = respan(sp, ast::DeclLocal(local));
-        @respan(sp, ast::StmtDecl(@decl, ast::DUMMY_NODE_ID))
+        box(GC) respan(sp, ast::StmtDecl(box(GC) decl, ast::DUMMY_NODE_ID))
     }
 
-    fn block(&self, span: Span, stmts: Vec<@ast::Stmt> , expr: Option<@Expr>) -> P<ast::Block> {
+    fn block(&self, span: Span, stmts: Vec<Gc<ast::Stmt>>,
+             expr: Option<Gc<Expr>>) -> P<ast::Block> {
         self.block_all(span, Vec::new(), stmts, expr)
     }
 
-    fn block_expr(&self, expr: @ast::Expr) -> P<ast::Block> {
+    fn block_expr(&self, expr: Gc<ast::Expr>) -> P<ast::Block> {
         self.block_all(expr.span, Vec::new(), Vec::new(), Some(expr))
     }
     fn block_all(&self,
                  span: Span,
                  view_items: Vec<ast::ViewItem> ,
-                 stmts: Vec<@ast::Stmt> ,
-                 expr: Option<@ast::Expr>) -> P<ast::Block> {
+                 stmts: Vec<Gc<ast::Stmt>>,
+                 expr: Option<Gc<ast::Expr>>) -> P<ast::Block> {
             P(ast::Block {
                view_items: view_items,
                stmts: stmts,
@@ -486,107 +507,109 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
             })
     }
 
-    fn expr(&self, span: Span, node: ast::Expr_) -> @ast::Expr {
-        @ast::Expr {
+    fn expr(&self, span: Span, node: ast::Expr_) -> Gc<ast::Expr> {
+        box(GC) ast::Expr {
             id: ast::DUMMY_NODE_ID,
             node: node,
             span: span,
         }
     }
 
-    fn expr_path(&self, path: ast::Path) -> @ast::Expr {
+    fn expr_path(&self, path: ast::Path) -> Gc<ast::Expr> {
         self.expr(path.span, ast::ExprPath(path))
     }
 
-    fn expr_ident(&self, span: Span, id: ast::Ident) -> @ast::Expr {
+    fn expr_ident(&self, span: Span, id: ast::Ident) -> Gc<ast::Expr> {
         self.expr_path(self.path_ident(span, id))
     }
-    fn expr_self(&self, span: Span) -> @ast::Expr {
+    fn expr_self(&self, span: Span) -> Gc<ast::Expr> {
         self.expr_ident(span, special_idents::self_)
     }
 
     fn expr_binary(&self, sp: Span, op: ast::BinOp,
-                   lhs: @ast::Expr, rhs: @ast::Expr) -> @ast::Expr {
+                   lhs: Gc<ast::Expr>, rhs: Gc<ast::Expr>) -> Gc<ast::Expr> {
         self.expr(sp, ast::ExprBinary(op, lhs, rhs))
     }
 
-    fn expr_deref(&self, sp: Span, e: @ast::Expr) -> @ast::Expr {
+    fn expr_deref(&self, sp: Span, e: Gc<ast::Expr>) -> Gc<ast::Expr> {
         self.expr_unary(sp, ast::UnDeref, e)
     }
-    fn expr_unary(&self, sp: Span, op: ast::UnOp, e: @ast::Expr) -> @ast::Expr {
+    fn expr_unary(&self, sp: Span, op: ast::UnOp, e: Gc<ast::Expr>) -> Gc<ast::Expr> {
         self.expr(sp, ast::ExprUnary(op, e))
     }
 
-    fn expr_managed(&self, sp: Span, e: @ast::Expr) -> @ast::Expr {
+    fn expr_managed(&self, sp: Span, e: Gc<ast::Expr>) -> Gc<ast::Expr> {
         self.expr_unary(sp, ast::UnBox, e)
     }
 
-    fn expr_field_access(&self, sp: Span, expr: @ast::Expr, ident: ast::Ident) -> @ast::Expr {
+    fn expr_field_access(&self, sp: Span, expr: Gc<ast::Expr>, ident: ast::Ident) -> Gc<ast::Expr> {
         self.expr(sp, ast::ExprField(expr, ident, Vec::new()))
     }
-    fn expr_addr_of(&self, sp: Span, e: @ast::Expr) -> @ast::Expr {
+    fn expr_addr_of(&self, sp: Span, e: Gc<ast::Expr>) -> Gc<ast::Expr> {
         self.expr(sp, ast::ExprAddrOf(ast::MutImmutable, e))
     }
-    fn expr_mut_addr_of(&self, sp: Span, e: @ast::Expr) -> @ast::Expr {
+    fn expr_mut_addr_of(&self, sp: Span, e: Gc<ast::Expr>) -> Gc<ast::Expr> {
         self.expr(sp, ast::ExprAddrOf(ast::MutMutable, e))
     }
 
-    fn expr_call(&self, span: Span, expr: @ast::Expr, args: Vec<@ast::Expr> ) -> @ast::Expr {
+    fn expr_call(&self, span: Span, expr: Gc<ast::Expr>,
+                 args: Vec<Gc<ast::Expr>>) -> Gc<ast::Expr> {
         self.expr(span, ast::ExprCall(expr, args))
     }
-    fn expr_call_ident(&self, span: Span, id: ast::Ident, args: Vec<@ast::Expr> ) -> @ast::Expr {
+    fn expr_call_ident(&self, span: Span, id: ast::Ident,
+                       args: Vec<Gc<ast::Expr>>) -> Gc<ast::Expr> {
         self.expr(span, ast::ExprCall(self.expr_ident(span, id), args))
     }
     fn expr_call_global(&self, sp: Span, fn_path: Vec<ast::Ident> ,
-                      args: Vec<@ast::Expr> ) -> @ast::Expr {
+                      args: Vec<Gc<ast::Expr>> ) -> Gc<ast::Expr> {
         let pathexpr = self.expr_path(self.path_global(sp, fn_path));
         self.expr_call(sp, pathexpr, args)
     }
     fn expr_method_call(&self, span: Span,
-                        expr: @ast::Expr,
+                        expr: Gc<ast::Expr>,
                         ident: ast::Ident,
-                        mut args: Vec<@ast::Expr> ) -> @ast::Expr {
+                        mut args: Vec<Gc<ast::Expr>> ) -> Gc<ast::Expr> {
         let id = Spanned { node: ident, span: span };
         args.unshift(expr);
         self.expr(span, ast::ExprMethodCall(id, Vec::new(), args))
     }
-    fn expr_block(&self, b: P<ast::Block>) -> @ast::Expr {
+    fn expr_block(&self, b: P<ast::Block>) -> Gc<ast::Expr> {
         self.expr(b.span, ast::ExprBlock(b))
     }
-    fn field_imm(&self, span: Span, name: Ident, e: @ast::Expr) -> ast::Field {
+    fn field_imm(&self, span: Span, name: Ident, e: Gc<ast::Expr>) -> ast::Field {
         ast::Field { ident: respan(span, name), expr: e, span: span }
     }
-    fn expr_struct(&self, span: Span, path: ast::Path, fields: Vec<ast::Field> ) -> @ast::Expr {
+    fn expr_struct(&self, span: Span, path: ast::Path, fields: Vec<ast::Field> ) -> Gc<ast::Expr> {
         self.expr(span, ast::ExprStruct(path, fields, None))
     }
     fn expr_struct_ident(&self, span: Span,
-                         id: ast::Ident, fields: Vec<ast::Field> ) -> @ast::Expr {
+                         id: ast::Ident, fields: Vec<ast::Field> ) -> Gc<ast::Expr> {
         self.expr_struct(span, self.path_ident(span, id), fields)
     }
 
-    fn expr_lit(&self, sp: Span, lit: ast::Lit_) -> @ast::Expr {
-        self.expr(sp, ast::ExprLit(@respan(sp, lit)))
+    fn expr_lit(&self, sp: Span, lit: ast::Lit_) -> Gc<ast::Expr> {
+        self.expr(sp, ast::ExprLit(box(GC) respan(sp, lit)))
     }
-    fn expr_uint(&self, span: Span, i: uint) -> @ast::Expr {
+    fn expr_uint(&self, span: Span, i: uint) -> Gc<ast::Expr> {
         self.expr_lit(span, ast::LitUint(i as u64, ast::TyU))
     }
-    fn expr_int(&self, sp: Span, i: int) -> @ast::Expr {
+    fn expr_int(&self, sp: Span, i: int) -> Gc<ast::Expr> {
         self.expr_lit(sp, ast::LitInt(i as i64, ast::TyI))
     }
-    fn expr_u8(&self, sp: Span, u: u8) -> @ast::Expr {
+    fn expr_u8(&self, sp: Span, u: u8) -> Gc<ast::Expr> {
         self.expr_lit(sp, ast::LitUint(u as u64, ast::TyU8))
     }
-    fn expr_bool(&self, sp: Span, value: bool) -> @ast::Expr {
+    fn expr_bool(&self, sp: Span, value: bool) -> Gc<ast::Expr> {
         self.expr_lit(sp, ast::LitBool(value))
     }
 
-    fn expr_vstore(&self, sp: Span, expr: @ast::Expr, vst: ast::ExprVstore) -> @ast::Expr {
+    fn expr_vstore(&self, sp: Span, expr: Gc<ast::Expr>, vst: ast::ExprVstore) -> Gc<ast::Expr> {
         self.expr(sp, ast::ExprVstore(expr, vst))
     }
-    fn expr_vec(&self, sp: Span, exprs: Vec<@ast::Expr> ) -> @ast::Expr {
+    fn expr_vec(&self, sp: Span, exprs: Vec<Gc<ast::Expr>> ) -> Gc<ast::Expr> {
         self.expr(sp, ast::ExprVec(exprs))
     }
-    fn expr_vec_ng(&self, sp: Span) -> @ast::Expr {
+    fn expr_vec_ng(&self, sp: Span) -> Gc<ast::Expr> {
         self.expr_call_global(sp,
                               vec!(self.ident_of("std"),
                                    self.ident_of("vec"),
@@ -594,23 +617,23 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
                                    self.ident_of("new")),
                               Vec::new())
     }
-    fn expr_vec_slice(&self, sp: Span, exprs: Vec<@ast::Expr> ) -> @ast::Expr {
+    fn expr_vec_slice(&self, sp: Span, exprs: Vec<Gc<ast::Expr>> ) -> Gc<ast::Expr> {
         self.expr_vstore(sp, self.expr_vec(sp, exprs), ast::ExprVstoreSlice)
     }
-    fn expr_str(&self, sp: Span, s: InternedString) -> @ast::Expr {
+    fn expr_str(&self, sp: Span, s: InternedString) -> Gc<ast::Expr> {
         self.expr_lit(sp, ast::LitStr(s, ast::CookedStr))
     }
-    fn expr_str_uniq(&self, sp: Span, s: InternedString) -> @ast::Expr {
+    fn expr_str_uniq(&self, sp: Span, s: InternedString) -> Gc<ast::Expr> {
         self.expr_vstore(sp, self.expr_str(sp, s), ast::ExprVstoreUniq)
     }
 
 
-    fn expr_cast(&self, sp: Span, expr: @ast::Expr, ty: P<ast::Ty>) -> @ast::Expr {
+    fn expr_cast(&self, sp: Span, expr: Gc<ast::Expr>, ty: P<ast::Ty>) -> Gc<ast::Expr> {
         self.expr(sp, ast::ExprCast(expr, ty))
     }
 
 
-    fn expr_some(&self, sp: Span, expr: @ast::Expr) -> @ast::Expr {
+    fn expr_some(&self, sp: Span, expr: Gc<ast::Expr>) -> Gc<ast::Expr> {
         let some = vec!(
             self.ident_of("std"),
             self.ident_of("option"),
@@ -618,7 +641,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         self.expr_call_global(sp, some, vec!(expr))
     }
 
-    fn expr_none(&self, sp: Span) -> @ast::Expr {
+    fn expr_none(&self, sp: Span) -> Gc<ast::Expr> {
         let none = self.path_global(sp, vec!(
             self.ident_of("std"),
             self.ident_of("option"),
@@ -626,7 +649,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         self.expr_path(none)
     }
 
-    fn expr_fail(&self, span: Span, msg: InternedString) -> @ast::Expr {
+    fn expr_fail(&self, span: Span, msg: InternedString) -> Gc<ast::Expr> {
         let loc = self.codemap().lookup_char_pos(span.lo);
         self.expr_call_global(
             span,
@@ -643,13 +666,13 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
                 self.expr_uint(span, loc.line)))
     }
 
-    fn expr_unreachable(&self, span: Span) -> @ast::Expr {
+    fn expr_unreachable(&self, span: Span) -> Gc<ast::Expr> {
         self.expr_fail(span,
                        InternedString::new(
                            "internal error: entered unreachable code"))
     }
 
-    fn expr_ok(&self, sp: Span, expr: @ast::Expr) -> @ast::Expr {
+    fn expr_ok(&self, sp: Span, expr: Gc<ast::Expr>) -> Gc<ast::Expr> {
         let ok = vec!(
             self.ident_of("std"),
             self.ident_of("result"),
@@ -657,7 +680,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         self.expr_call_global(sp, ok, vec!(expr))
     }
 
-    fn expr_err(&self, sp: Span, expr: @ast::Expr) -> @ast::Expr {
+    fn expr_err(&self, sp: Span, expr: Gc<ast::Expr>) -> Gc<ast::Expr> {
         let err = vec!(
             self.ident_of("std"),
             self.ident_of("result"),
@@ -665,7 +688,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         self.expr_call_global(sp, err, vec!(expr))
     }
 
-    fn expr_try(&self, sp: Span, head: @ast::Expr) -> @ast::Expr {
+    fn expr_try(&self, sp: Span, head: Gc<ast::Expr>) -> Gc<ast::Expr> {
         let ok = self.ident_of("Ok");
         let ok_path = self.path_ident(sp, ok);
         let err = self.ident_of("Err");
@@ -694,38 +717,38 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     }
 
 
-    fn pat(&self, span: Span, pat: ast::Pat_) -> @ast::Pat {
-        @ast::Pat { id: ast::DUMMY_NODE_ID, node: pat, span: span }
+    fn pat(&self, span: Span, pat: ast::Pat_) -> Gc<ast::Pat> {
+        box(GC) ast::Pat { id: ast::DUMMY_NODE_ID, node: pat, span: span }
     }
-    fn pat_wild(&self, span: Span) -> @ast::Pat {
+    fn pat_wild(&self, span: Span) -> Gc<ast::Pat> {
         self.pat(span, ast::PatWild)
     }
-    fn pat_lit(&self, span: Span, expr: @ast::Expr) -> @ast::Pat {
+    fn pat_lit(&self, span: Span, expr: Gc<ast::Expr>) -> Gc<ast::Pat> {
         self.pat(span, ast::PatLit(expr))
     }
-    fn pat_ident(&self, span: Span, ident: ast::Ident) -> @ast::Pat {
+    fn pat_ident(&self, span: Span, ident: ast::Ident) -> Gc<ast::Pat> {
         self.pat_ident_binding_mode(span, ident, ast::BindByValue(ast::MutImmutable))
     }
 
     fn pat_ident_binding_mode(&self,
                               span: Span,
                               ident: ast::Ident,
-                              bm: ast::BindingMode) -> @ast::Pat {
+                              bm: ast::BindingMode) -> Gc<ast::Pat> {
         let path = self.path_ident(span, ident);
         let pat = ast::PatIdent(bm, path, None);
         self.pat(span, pat)
     }
-    fn pat_enum(&self, span: Span, path: ast::Path, subpats: Vec<@ast::Pat> ) -> @ast::Pat {
+    fn pat_enum(&self, span: Span, path: ast::Path, subpats: Vec<Gc<ast::Pat>> ) -> Gc<ast::Pat> {
         let pat = ast::PatEnum(path, Some(subpats));
         self.pat(span, pat)
     }
     fn pat_struct(&self, span: Span,
-                  path: ast::Path, field_pats: Vec<ast::FieldPat> ) -> @ast::Pat {
+                  path: ast::Path, field_pats: Vec<ast::FieldPat> ) -> Gc<ast::Pat> {
         let pat = ast::PatStruct(path, field_pats, false);
         self.pat(span, pat)
     }
 
-    fn arm(&self, _span: Span, pats: Vec<@ast::Pat> , expr: @ast::Expr) -> ast::Arm {
+    fn arm(&self, _span: Span, pats: Vec<Gc<ast::Pat>> , expr: Gc<ast::Expr>) -> ast::Arm {
         ast::Arm {
             attrs: vec!(),
             pats: pats,
@@ -738,56 +761,60 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         self.arm(span, vec!(self.pat_wild(span)), self.expr_unreachable(span))
     }
 
-    fn expr_match(&self, span: Span, arg: @ast::Expr, arms: Vec<ast::Arm> ) -> @Expr {
+    fn expr_match(&self, span: Span, arg: Gc<ast::Expr>,
+                  arms: Vec<ast::Arm>) -> Gc<Expr> {
         self.expr(span, ast::ExprMatch(arg, arms))
     }
 
     fn expr_if(&self, span: Span,
-               cond: @ast::Expr, then: @ast::Expr, els: Option<@ast::Expr>) -> @ast::Expr {
+               cond: Gc<ast::Expr>, then: Gc<ast::Expr>,
+               els: Option<Gc<ast::Expr>>) -> Gc<ast::Expr> {
         let els = els.map(|x| self.expr_block(self.block_expr(x)));
         self.expr(span, ast::ExprIf(cond, self.block_expr(then), els))
     }
 
     fn lambda_fn_decl(&self, span: Span,
-                      fn_decl: P<ast::FnDecl>, blk: P<ast::Block>) -> @ast::Expr {
+                      fn_decl: P<ast::FnDecl>, blk: P<ast::Block>) -> Gc<ast::Expr> {
         self.expr(span, ast::ExprFnBlock(fn_decl, blk))
     }
-    fn lambda(&self, span: Span, ids: Vec<ast::Ident> , blk: P<ast::Block>) -> @ast::Expr {
+    fn lambda(&self, span: Span, ids: Vec<ast::Ident> , blk: P<ast::Block>) -> Gc<ast::Expr> {
         let fn_decl = self.fn_decl(
             ids.iter().map(|id| self.arg(span, *id, self.ty_infer(span))).collect(),
             self.ty_infer(span));
 
         self.expr(span, ast::ExprFnBlock(fn_decl, blk))
     }
-    fn lambda0(&self, span: Span, blk: P<ast::Block>) -> @ast::Expr {
+    fn lambda0(&self, span: Span, blk: P<ast::Block>) -> Gc<ast::Expr> {
         self.lambda(span, Vec::new(), blk)
     }
 
-    fn lambda1(&self, span: Span, blk: P<ast::Block>, ident: ast::Ident) -> @ast::Expr {
+    fn lambda1(&self, span: Span, blk: P<ast::Block>, ident: ast::Ident) -> Gc<ast::Expr> {
         self.lambda(span, vec!(ident), blk)
     }
 
-    fn lambda_expr(&self, span: Span, ids: Vec<ast::Ident> , expr: @ast::Expr) -> @ast::Expr {
+    fn lambda_expr(&self, span: Span, ids: Vec<ast::Ident> , expr: Gc<ast::Expr>) -> Gc<ast::Expr> {
         self.lambda(span, ids, self.block_expr(expr))
     }
-    fn lambda_expr_0(&self, span: Span, expr: @ast::Expr) -> @ast::Expr {
+    fn lambda_expr_0(&self, span: Span, expr: Gc<ast::Expr>) -> Gc<ast::Expr> {
         self.lambda0(span, self.block_expr(expr))
     }
-    fn lambda_expr_1(&self, span: Span, expr: @ast::Expr, ident: ast::Ident) -> @ast::Expr {
+    fn lambda_expr_1(&self, span: Span, expr: Gc<ast::Expr>, ident: ast::Ident) -> Gc<ast::Expr> {
         self.lambda1(span, self.block_expr(expr), ident)
     }
 
     fn lambda_stmts(&self,
                     span: Span,
                     ids: Vec<ast::Ident>,
-                    stmts: Vec<@ast::Stmt>)
-                    -> @ast::Expr {
+                    stmts: Vec<Gc<ast::Stmt>>)
+                    -> Gc<ast::Expr> {
         self.lambda(span, ids, self.block(span, stmts, None))
     }
-    fn lambda_stmts_0(&self, span: Span, stmts: Vec<@ast::Stmt> ) -> @ast::Expr {
+    fn lambda_stmts_0(&self, span: Span,
+                      stmts: Vec<Gc<ast::Stmt>>) -> Gc<ast::Expr> {
         self.lambda0(span, self.block(span, stmts, None))
     }
-    fn lambda_stmts_1(&self, span: Span, stmts: Vec<@ast::Stmt> , ident: ast::Ident) -> @ast::Expr {
+    fn lambda_stmts_1(&self, span: Span, stmts: Vec<Gc<ast::Stmt>>,
+                      ident: ast::Ident) -> Gc<ast::Expr> {
         self.lambda1(span, self.block(span, stmts, None), ident)
     }
 
@@ -811,10 +838,11 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     }
 
     fn item(&self, span: Span,
-            name: Ident, attrs: Vec<ast::Attribute> , node: ast::Item_) -> @ast::Item {
+            name: Ident, attrs: Vec<ast::Attribute>,
+            node: ast::Item_) -> Gc<ast::Item> {
         // FIXME: Would be nice if our generated code didn't violate
         // Rust coding conventions
-        @ast::Item { ident: name,
+        box(GC) ast::Item { ident: name,
                     attrs: attrs,
                     id: ast::DUMMY_NODE_ID,
                     node: node,
@@ -828,7 +856,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
                     inputs: Vec<ast::Arg> ,
                     output: P<ast::Ty>,
                     generics: Generics,
-                    body: P<ast::Block>) -> @ast::Item {
+                    body: P<ast::Block>) -> Gc<ast::Item> {
         self.item(span,
                   name,
                   Vec::new(),
@@ -845,7 +873,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
                inputs: Vec<ast::Arg> ,
                output: P<ast::Ty>,
                body: P<ast::Block>
-              ) -> @ast::Item {
+              ) -> Gc<ast::Item> {
         self.item_fn_poly(
             span,
             name,
@@ -873,18 +901,18 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
 
     fn item_enum_poly(&self, span: Span, name: Ident,
                       enum_definition: ast::EnumDef,
-                      generics: Generics) -> @ast::Item {
+                      generics: Generics) -> Gc<ast::Item> {
         self.item(span, name, Vec::new(), ast::ItemEnum(enum_definition, generics))
     }
 
     fn item_enum(&self, span: Span, name: Ident,
-                 enum_definition: ast::EnumDef) -> @ast::Item {
+                 enum_definition: ast::EnumDef) -> Gc<ast::Item> {
         self.item_enum_poly(span, name, enum_definition,
                             ast_util::empty_generics())
     }
 
     fn item_struct(&self, span: Span, name: Ident,
-                   struct_def: ast::StructDef) -> @ast::Item {
+                   struct_def: ast::StructDef) -> Gc<ast::Item> {
         self.item_struct_poly(
             span,
             name,
@@ -894,14 +922,14 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     }
 
     fn item_struct_poly(&self, span: Span, name: Ident,
-        struct_def: ast::StructDef, generics: Generics) -> @ast::Item {
-        self.item(span, name, Vec::new(), ast::ItemStruct(@struct_def, generics))
+        struct_def: ast::StructDef, generics: Generics) -> Gc<ast::Item> {
+        self.item(span, name, Vec::new(), ast::ItemStruct(box(GC) struct_def, generics))
     }
 
     fn item_mod(&self, span: Span, inner_span: Span, name: Ident,
                 attrs: Vec<ast::Attribute> ,
                 vi: Vec<ast::ViewItem> ,
-                items: Vec<@ast::Item> ) -> @ast::Item {
+                items: Vec<Gc<ast::Item>>) -> Gc<ast::Item> {
         self.item(
             span,
             name,
@@ -915,15 +943,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     }
 
     fn item_ty_poly(&self, span: Span, name: Ident, ty: P<ast::Ty>,
-                    generics: Generics) -> @ast::Item {
+                    generics: Generics) -> Gc<ast::Item> {
         self.item(span, name, Vec::new(), ast::ItemTy(ty, generics))
     }
 
-    fn item_ty(&self, span: Span, name: Ident, ty: P<ast::Ty>) -> @ast::Item {
+    fn item_ty(&self, span: Span, name: Ident, ty: P<ast::Ty>) -> Gc<ast::Item> {
         self.item_ty_poly(span, name, ty, ast_util::empty_generics())
     }
 
-    fn attribute(&self, sp: Span, mi: @ast::MetaItem) -> ast::Attribute {
+    fn attribute(&self, sp: Span, mi: Gc<ast::MetaItem>) -> ast::Attribute {
         respan(sp, ast::Attribute_ {
             id: attr::mk_attr_id(),
             style: ast::AttrOuter,
@@ -932,26 +960,26 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         })
     }
 
-    fn meta_word(&self, sp: Span, w: InternedString) -> @ast::MetaItem {
-        @respan(sp, ast::MetaWord(w))
+    fn meta_word(&self, sp: Span, w: InternedString) -> Gc<ast::MetaItem> {
+        box(GC) respan(sp, ast::MetaWord(w))
     }
     fn meta_list(&self,
                  sp: Span,
                  name: InternedString,
-                 mis: Vec<@ast::MetaItem> )
-                 -> @ast::MetaItem {
-        @respan(sp, ast::MetaList(name, mis))
+                 mis: Vec<Gc<ast::MetaItem>> )
+                 -> Gc<ast::MetaItem> {
+        box(GC) respan(sp, ast::MetaList(name, mis))
     }
     fn meta_name_value(&self,
                        sp: Span,
                        name: InternedString,
                        value: ast::Lit_)
-                       -> @ast::MetaItem {
-        @respan(sp, ast::MetaNameValue(name, respan(sp, value)))
+                       -> Gc<ast::MetaItem> {
+        box(GC) respan(sp, ast::MetaNameValue(name, respan(sp, value)))
     }
 
     fn view_use(&self, sp: Span,
-                vis: ast::Visibility, vp: @ast::ViewPath) -> ast::ViewItem {
+                vis: ast::Visibility, vp: Gc<ast::ViewPath>) -> ast::ViewItem {
         ast::ViewItem {
             node: ast::ViewItemUse(vp),
             attrs: Vec::new(),
@@ -968,7 +996,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     fn view_use_simple_(&self, sp: Span, vis: ast::Visibility,
                         ident: ast::Ident, path: ast::Path) -> ast::ViewItem {
         self.view_use(sp, vis,
-                      @respan(sp,
+                      box(GC) respan(sp,
                            ast::ViewPathSimple(ident,
                                                path,
                                                ast::DUMMY_NODE_ID)))
@@ -981,7 +1009,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         }).collect();
 
         self.view_use(sp, vis,
-                      @respan(sp,
+                      box(GC) respan(sp,
                            ast::ViewPathList(self.path(sp, path),
                                              imports,
                                              ast::DUMMY_NODE_ID)))
@@ -990,7 +1018,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     fn view_use_glob(&self, sp: Span,
                      vis: ast::Visibility, path: Vec<ast::Ident> ) -> ast::ViewItem {
         self.view_use(sp, vis,
-                      @respan(sp,
+                      box(GC) respan(sp,
                            ast::ViewPathGlob(self.path(sp, path), ast::DUMMY_NODE_ID)))
     }
 }
@@ -1013,8 +1041,8 @@ pub trait Duplicate {
     fn duplicate(&self, cx: &ExtCtxt) -> Self;
 }
 
-impl Duplicate for @ast::Expr {
-    fn duplicate(&self, _: &ExtCtxt) -> @ast::Expr {
+impl Duplicate for Gc<ast::Expr> {
+    fn duplicate(&self, _: &ExtCtxt) -> Gc<ast::Expr> {
         let mut folder = Duplicator;
         folder.fold_expr(*self)
     }
diff --git a/src/libsyntax/ext/concat_idents.rs b/src/libsyntax/ext/concat_idents.rs
index dad7f3e6979..3522095ed70 100644
--- a/src/libsyntax/ext/concat_idents.rs
+++ b/src/libsyntax/ext/concat_idents.rs
@@ -44,7 +44,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
     }
     let res = str_to_ident(res_str.as_slice());
 
-    let e = @ast::Expr {
+    let e = box(GC) ast::Expr {
         id: ast::DUMMY_NODE_ID,
         node: ast::ExprPath(
             ast::Path {
diff --git a/src/libsyntax/ext/deriving/bounds.rs b/src/libsyntax/ext/deriving/bounds.rs
index 81fb1e46bba..fac9f37c462 100644
--- a/src/libsyntax/ext/deriving/bounds.rs
+++ b/src/libsyntax/ext/deriving/bounds.rs
@@ -14,11 +14,13 @@ use ext::base::ExtCtxt;
 use ext::deriving::generic::*;
 use ext::deriving::generic::ty::*;
 
+use std::gc::Gc;
+
 pub fn expand_deriving_bound(cx: &mut ExtCtxt,
                              span: Span,
-                             mitem: @MetaItem,
-                             item: @Item,
-                             push: |@Item|) {
+                             mitem: Gc<MetaItem>,
+                             item: Gc<Item>,
+                             push: |Gc<Item>|) {
 
     let name = match mitem.node {
         MetaWord(ref tname) => {
diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs
index 6ddfedfeb4f..93e4920bc1d 100644
--- a/src/libsyntax/ext/deriving/clone.rs
+++ b/src/libsyntax/ext/deriving/clone.rs
@@ -16,11 +16,13 @@ use ext::deriving::generic::*;
 use ext::deriving::generic::ty::*;
 use parse::token::InternedString;
 
+use std::gc::Gc;
+
 pub fn expand_deriving_clone(cx: &mut ExtCtxt,
                              span: Span,
-                             mitem: @MetaItem,
-                             item: @Item,
-                             push: |@Item|) {
+                             mitem: Gc<MetaItem>,
+                             item: Gc<Item>,
+                             push: |Gc<Item>|) {
     let inline = cx.meta_word(span, InternedString::new("inline"));
     let attrs = vec!(cx.attribute(span, inline));
     let trait_def = TraitDef {
@@ -51,7 +53,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt,
 fn cs_clone(
     name: &str,
     cx: &mut ExtCtxt, trait_span: Span,
-    substr: &Substructure) -> @Expr {
+    substr: &Substructure) -> Gc<Expr> {
     let clone_ident = substr.method_ident;
     let ctor_ident;
     let all_fields;
diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs
index e7a6cb35582..ef8d477a98e 100644
--- a/src/libsyntax/ext/deriving/cmp/eq.rs
+++ b/src/libsyntax/ext/deriving/cmp/eq.rs
@@ -16,18 +16,20 @@ use ext::deriving::generic::*;
 use ext::deriving::generic::ty::*;
 use parse::token::InternedString;
 
+use std::gc::Gc;
+
 pub fn expand_deriving_eq(cx: &mut ExtCtxt,
                           span: Span,
-                          mitem: @MetaItem,
-                          item: @Item,
-                          push: |@Item|) {
+                          mitem: Gc<MetaItem>,
+                          item: Gc<Item>,
+                          push: |Gc<Item>|) {
     // structures are equal if all fields are equal, and non equal, if
     // any fields are not equal or if the enum variants are different
-    fn cs_eq(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
+    fn cs_eq(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> Gc<Expr> {
         cs_and(|cx, span, _, _| cx.expr_bool(span, false),
                                  cx, span, substr)
     }
-    fn cs_ne(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
+    fn cs_ne(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> Gc<Expr> {
         cs_or(|cx, span, _, _| cx.expr_bool(span, true),
               cx, span, substr)
     }
diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs
index 24cc286b190..88ebe8a60fa 100644
--- a/src/libsyntax/ext/deriving/cmp/ord.rs
+++ b/src/libsyntax/ext/deriving/cmp/ord.rs
@@ -17,11 +17,13 @@ use ext::deriving::generic::*;
 use ext::deriving::generic::ty::*;
 use parse::token::InternedString;
 
+use std::gc::Gc;
+
 pub fn expand_deriving_ord(cx: &mut ExtCtxt,
                            span: Span,
-                           mitem: @MetaItem,
-                           item: @Item,
-                           push: |@Item|) {
+                           mitem: Gc<MetaItem>,
+                           item: Gc<Item>,
+                           push: |Gc<Item>|) {
     macro_rules! md (
         ($name:expr, $op:expr, $equal:expr) => { {
             let inline = cx.meta_word(span, InternedString::new("inline"));
@@ -58,7 +60,8 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt,
 }
 
 /// Strict inequality.
-fn cs_op(less: bool, equal: bool, cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
+fn cs_op(less: bool, equal: bool, cx: &mut ExtCtxt, span: Span,
+         substr: &Substructure) -> Gc<Expr> {
     let op = if less {ast::BiLt} else {ast::BiGt};
     cs_fold(
         false, // need foldr,
diff --git a/src/libsyntax/ext/deriving/cmp/totaleq.rs b/src/libsyntax/ext/deriving/cmp/totaleq.rs
index fb7be4c14b6..8b1e0498d25 100644
--- a/src/libsyntax/ext/deriving/cmp/totaleq.rs
+++ b/src/libsyntax/ext/deriving/cmp/totaleq.rs
@@ -16,12 +16,15 @@ use ext::deriving::generic::*;
 use ext::deriving::generic::ty::*;
 use parse::token::InternedString;
 
+use std::gc::Gc;
+
 pub fn expand_deriving_totaleq(cx: &mut ExtCtxt,
                                span: Span,
-                               mitem: @MetaItem,
-                               item: @Item,
-                               push: |@Item|) {
-    fn cs_total_eq_assert(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
+                               mitem: Gc<MetaItem>,
+                               item: Gc<Item>,
+                               push: |Gc<Item>|) {
+    fn cs_total_eq_assert(cx: &mut ExtCtxt, span: Span,
+                          substr: &Substructure) -> Gc<Expr> {
         cs_same_method(|cx, span, exprs| {
             // create `a.<method>(); b.<method>(); c.<method>(); ...`
             // (where method is `assert_receiver_is_total_eq`)
diff --git a/src/libsyntax/ext/deriving/cmp/totalord.rs b/src/libsyntax/ext/deriving/cmp/totalord.rs
index 03ac4c9ab03..271aa90cd24 100644
--- a/src/libsyntax/ext/deriving/cmp/totalord.rs
+++ b/src/libsyntax/ext/deriving/cmp/totalord.rs
@@ -18,12 +18,13 @@ use ext::deriving::generic::ty::*;
 use parse::token::InternedString;
 
 use std::cmp::{Ordering, Equal, Less, Greater};
+use std::gc::Gc;
 
 pub fn expand_deriving_totalord(cx: &mut ExtCtxt,
                                 span: Span,
-                                mitem: @MetaItem,
-                                item: @Item,
-                                push: |@Item|) {
+                                mitem: Gc<MetaItem>,
+                                item: Gc<Item>,
+                                push: |Gc<Item>|) {
     let inline = cx.meta_word(span, InternedString::new("inline"));
     let attrs = vec!(cx.attribute(span, inline));
     let trait_def = TraitDef {
@@ -65,7 +66,7 @@ pub fn ordering_const(cx: &mut ExtCtxt, span: Span, cnst: Ordering) -> ast::Path
 }
 
 pub fn cs_cmp(cx: &mut ExtCtxt, span: Span,
-              substr: &Substructure) -> @Expr {
+              substr: &Substructure) -> Gc<Expr> {
     let test_id = cx.ident_of("__test");
     let equals_path = ordering_const(cx, span, Equal);
 
diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs
index fe198749384..0c23d65fde0 100644
--- a/src/libsyntax/ext/deriving/decodable.rs
+++ b/src/libsyntax/ext/deriving/decodable.rs
@@ -23,11 +23,13 @@ use ext::deriving::generic::ty::*;
 use parse::token::InternedString;
 use parse::token;
 
+use std::gc::Gc;
+
 pub fn expand_deriving_decodable(cx: &mut ExtCtxt,
                                  span: Span,
-                                 mitem: @MetaItem,
-                                 item: @Item,
-                                 push: |@Item|) {
+                                 mitem: Gc<MetaItem>,
+                                 item: Gc<Item>,
+                                 push: |Gc<Item>|) {
     let trait_def = TraitDef {
         span: span,
         attributes: Vec::new(),
@@ -64,7 +66,7 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt,
 }
 
 fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
-                          substr: &Substructure) -> @Expr {
+                          substr: &Substructure) -> Gc<Expr> {
     let decoder = substr.nonself_args[0];
     let recurse = vec!(cx.ident_of("serialize"),
                     cx.ident_of("Decodable"),
@@ -159,8 +161,8 @@ fn decode_static_fields(cx: &mut ExtCtxt,
                         trait_span: Span,
                         outer_pat_ident: Ident,
                         fields: &StaticFields,
-                        getarg: |&mut ExtCtxt, Span, InternedString, uint| -> @Expr)
-                        -> @Expr {
+                        getarg: |&mut ExtCtxt, Span, InternedString, uint| -> Gc<Expr>)
+                        -> Gc<Expr> {
     match *fields {
         Unnamed(ref fields) => {
             if fields.is_empty() {
diff --git a/src/libsyntax/ext/deriving/default.rs b/src/libsyntax/ext/deriving/default.rs
index 28547a5a494..dfebc0f5e64 100644
--- a/src/libsyntax/ext/deriving/default.rs
+++ b/src/libsyntax/ext/deriving/default.rs
@@ -16,11 +16,13 @@ use ext::deriving::generic::*;
 use ext::deriving::generic::ty::*;
 use parse::token::InternedString;
 
+use std::gc::Gc;
+
 pub fn expand_deriving_default(cx: &mut ExtCtxt,
                             span: Span,
-                            mitem: @MetaItem,
-                            item: @Item,
-                            push: |@Item|) {
+                            mitem: Gc<MetaItem>,
+                            item: Gc<Item>,
+                            push: |Gc<Item>|) {
     let inline = cx.meta_word(span, InternedString::new("inline"));
     let attrs = vec!(cx.attribute(span, inline));
     let trait_def = TraitDef {
@@ -46,7 +48,8 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt,
     trait_def.expand(cx, mitem, item, push)
 }
 
-fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr {
+fn default_substructure(cx: &mut ExtCtxt, trait_span: Span,
+                        substr: &Substructure) -> Gc<Expr> {
     let default_ident = vec!(
         cx.ident_of("std"),
         cx.ident_of("default"),
diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs
index e189cc682f6..f57670af199 100644
--- a/src/libsyntax/ext/deriving/encodable.rs
+++ b/src/libsyntax/ext/deriving/encodable.rs
@@ -91,11 +91,13 @@ use ext::deriving::generic::*;
 use ext::deriving::generic::ty::*;
 use parse::token;
 
+use std::gc::Gc;
+
 pub fn expand_deriving_encodable(cx: &mut ExtCtxt,
                                  span: Span,
-                                 mitem: @MetaItem,
-                                 item: @Item,
-                                 push: |@Item|) {
+                                 mitem: Gc<MetaItem>,
+                                 item: Gc<Item>,
+                                 push: |Gc<Item>|) {
     let trait_def = TraitDef {
         span: span,
         attributes: Vec::new(),
@@ -134,7 +136,7 @@ pub fn expand_deriving_encodable(cx: &mut ExtCtxt,
 }
 
 fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
-                          substr: &Substructure) -> @Expr {
+                          substr: &Substructure) -> Gc<Expr> {
     let encoder = substr.nonself_args[0];
     // throw an underscore in front to suppress unused variable warnings
     let blkarg = cx.ident_of("_e");
diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs
index bf0da94e3e3..251eae75ee5 100644
--- a/src/libsyntax/ext/deriving/generic/mod.rs
+++ b/src/libsyntax/ext/deriving/generic/mod.rs
@@ -178,6 +178,7 @@ StaticEnum(<ast::EnumDef of C>, ~[(<ident of C0>, <span of C0>, Unnamed(~[<span
 */
 
 use std::cell::RefCell;
+use std::gc::Gc;
 
 use ast;
 use ast::{P, EnumDef, Expr, Ident, Generics, StructDef};
@@ -248,9 +249,9 @@ pub struct Substructure<'a> {
     /// ident of the method
     pub method_ident: Ident,
     /// dereferenced access to any Self or Ptr(Self, _) arguments
-    pub self_args: &'a [@Expr],
+    pub self_args: &'a [Gc<Expr>],
     /// verbatim access to any other arguments
-    pub nonself_args: &'a [@Expr],
+    pub nonself_args: &'a [Gc<Expr>],
     pub fields: &'a SubstructureFields<'a>
 }
 
@@ -262,42 +263,43 @@ pub struct FieldInfo {
     pub name: Option<Ident>,
     /// The expression corresponding to this field of `self`
     /// (specifically, a reference to it).
-    pub self_: @Expr,
+    pub self_: Gc<Expr>,
     /// The expressions corresponding to references to this field in
     /// the other Self arguments.
-    pub other: Vec<@Expr>,
+    pub other: Vec<Gc<Expr>>,
 }
 
 /// Fields for a static method
 pub enum StaticFields {
     /// Tuple structs/enum variants like this
-    Unnamed(Vec<Span> ),
+    Unnamed(Vec<Span>),
     /// Normal structs/struct variants.
-    Named(Vec<(Ident, Span)> )
+    Named(Vec<(Ident, Span)>),
 }
 
 /// A summary of the possible sets of fields. See above for details
 /// and examples
 pub enum SubstructureFields<'a> {
-    Struct(Vec<FieldInfo> ),
+    Struct(Vec<FieldInfo>),
     /**
     Matching variants of the enum: variant index, ast::Variant,
     fields: the field name is only non-`None` in the case of a struct
     variant.
     */
-    EnumMatching(uint, &'a ast::Variant, Vec<FieldInfo> ),
+    EnumMatching(uint, &'a ast::Variant, Vec<FieldInfo>),
 
     /**
     non-matching variants of the enum, [(variant index, ast::Variant,
     [field span, field ident, fields])] \(i.e. all fields for self are in the
     first tuple, for other1 are in the second tuple, etc.)
     */
-    EnumNonMatching(&'a [(uint, P<ast::Variant>, Vec<(Span, Option<Ident>, @Expr)> )]),
+    EnumNonMatching(&'a [(uint, P<ast::Variant>,
+                          Vec<(Span, Option<Ident>, Gc<Expr>)>)]),
 
     /// A static method where Self is a struct.
     StaticStruct(&'a ast::StructDef, StaticFields),
     /// A static method where Self is an enum.
-    StaticEnum(&'a ast::EnumDef, Vec<(Ident, Span, StaticFields)> )
+    StaticEnum(&'a ast::EnumDef, Vec<(Ident, Span, StaticFields)>),
 }
 
 
@@ -307,7 +309,7 @@ Combine the values of all the fields together. The last argument is
 all the fields of all the structures, see above for details.
 */
 pub type CombineSubstructureFunc<'a> =
-    |&mut ExtCtxt, Span, &Substructure|: 'a -> @Expr;
+    |&mut ExtCtxt, Span, &Substructure|: 'a -> Gc<Expr>;
 
 /**
 Deal with non-matching enum variants, the arguments are a list
@@ -317,9 +319,9 @@ representing each variant: (variant index, ast::Variant instance,
 pub type EnumNonMatchFunc<'a> =
     |&mut ExtCtxt,
            Span,
-           &[(uint, P<ast::Variant>, Vec<(Span, Option<Ident>, @Expr)> )],
-           &[@Expr]|: 'a
-           -> @Expr;
+           &[(uint, P<ast::Variant>, Vec<(Span, Option<Ident>, Gc<Expr>)>)],
+           &[Gc<Expr>]|: 'a
+           -> Gc<Expr>;
 
 pub fn combine_substructure<'a>(f: CombineSubstructureFunc<'a>)
     -> RefCell<CombineSubstructureFunc<'a>> {
@@ -330,13 +332,13 @@ pub fn combine_substructure<'a>(f: CombineSubstructureFunc<'a>)
 impl<'a> TraitDef<'a> {
     pub fn expand(&self,
                   cx: &mut ExtCtxt,
-                  _mitem: @ast::MetaItem,
-                  item: @ast::Item,
-                  push: |@ast::Item|) {
+                  _mitem: Gc<ast::MetaItem>,
+                  item: Gc<ast::Item>,
+                  push: |Gc<ast::Item>|) {
         let newitem = match item.node {
-            ast::ItemStruct(struct_def, ref generics) => {
+            ast::ItemStruct(ref struct_def, ref generics) => {
                 self.expand_struct_def(cx,
-                                       struct_def,
+                                       &**struct_def,
                                        item.ident,
                                        generics)
             }
@@ -357,7 +359,7 @@ impl<'a> TraitDef<'a> {
                 _ => false,
             }
         }).map(|a| a.clone()));
-        push(@ast::Item {
+        push(box(GC) ast::Item {
             attrs: attrs,
             ..(*newitem).clone()
         })
@@ -379,7 +381,7 @@ impl<'a> TraitDef<'a> {
                            cx: &mut ExtCtxt,
                            type_ident: Ident,
                            generics: &Generics,
-                           methods: Vec<@ast::Method> ) -> @ast::Item {
+                           methods: Vec<Gc<ast::Method>> ) -> Gc<ast::Item> {
         let trait_path = self.path.to_path(cx, self.span, type_ident, generics);
 
         let Generics { mut lifetimes, ty_params } =
@@ -435,7 +437,7 @@ impl<'a> TraitDef<'a> {
         // Just mark it now since we know that it'll end up used downstream
         attr::mark_used(&attr);
         let opt_trait_ref = Some(trait_ref);
-        let ident = ast_util::impl_pretty_name(&opt_trait_ref, self_type);
+        let ident = ast_util::impl_pretty_name(&opt_trait_ref, &*self_type);
         cx.item(
             self.span,
             ident,
@@ -448,7 +450,7 @@ impl<'a> TraitDef<'a> {
                          cx: &mut ExtCtxt,
                          struct_def: &StructDef,
                          type_ident: Ident,
-                         generics: &Generics) -> @ast::Item {
+                         generics: &Generics) -> Gc<ast::Item> {
         let methods = self.methods.iter().map(|method_def| {
             let (explicit_self, self_args, nonself_args, tys) =
                 method_def.split_self_nonself_args(
@@ -484,7 +486,7 @@ impl<'a> TraitDef<'a> {
                        cx: &mut ExtCtxt,
                        enum_def: &EnumDef,
                        type_ident: Ident,
-                       generics: &Generics) -> @ast::Item {
+                       generics: &Generics) -> Gc<ast::Item> {
         let methods = self.methods.iter().map(|method_def| {
             let (explicit_self, self_args, nonself_args, tys) =
                 method_def.split_self_nonself_args(cx, self,
@@ -522,10 +524,10 @@ impl<'a> MethodDef<'a> {
                                 cx: &mut ExtCtxt,
                                 trait_: &TraitDef,
                                 type_ident: Ident,
-                                self_args: &[@Expr],
-                                nonself_args: &[@Expr],
+                                self_args: &[Gc<Expr>],
+                                nonself_args: &[Gc<Expr>],
                                 fields: &SubstructureFields)
-        -> @Expr {
+        -> Gc<Expr> {
         let substructure = Substructure {
             type_ident: type_ident,
             method_ident: cx.ident_of(self.name),
@@ -556,7 +558,8 @@ impl<'a> MethodDef<'a> {
                                trait_: &TraitDef,
                                type_ident: Ident,
                                generics: &Generics)
-        -> (ast::ExplicitSelf, Vec<@Expr> , Vec<@Expr> , Vec<(Ident, P<ast::Ty>)> ) {
+        -> (ast::ExplicitSelf, Vec<Gc<Expr>>, Vec<Gc<Expr>>,
+            Vec<(Ident, P<ast::Ty>)>) {
 
         let mut self_args = Vec::new();
         let mut nonself_args = Vec::new();
@@ -608,7 +611,7 @@ impl<'a> MethodDef<'a> {
                      generics: &Generics,
                      explicit_self: ast::ExplicitSelf,
                      arg_types: Vec<(Ident, P<ast::Ty>)> ,
-                     body: @Expr) -> @ast::Method {
+                     body: Gc<Expr>) -> Gc<ast::Method> {
         // create the generics that aren't for Self
         let fn_generics = self.generics.to_generics(cx, trait_.span, type_ident, generics);
 
@@ -630,7 +633,7 @@ impl<'a> MethodDef<'a> {
         let body_block = cx.block_expr(body);
 
         // Create the method.
-        @ast::Method {
+        box(GC) ast::Method {
             ident: method_ident,
             attrs: self.attributes.clone(),
             generics: fn_generics,
@@ -670,9 +673,9 @@ impl<'a> MethodDef<'a> {
                                  trait_: &TraitDef,
                                  struct_def: &StructDef,
                                  type_ident: Ident,
-                                 self_args: &[@Expr],
-                                 nonself_args: &[@Expr])
-        -> @Expr {
+                                 self_args: &[Gc<Expr>],
+                                 nonself_args: &[Gc<Expr>])
+        -> Gc<Expr> {
 
         let mut raw_fields = Vec::new(); // ~[[fields of self],
                                  // [fields of next Self arg], [etc]]
@@ -737,9 +740,9 @@ impl<'a> MethodDef<'a> {
                                         trait_: &TraitDef,
                                         struct_def: &StructDef,
                                         type_ident: Ident,
-                                        self_args: &[@Expr],
-                                        nonself_args: &[@Expr])
-        -> @Expr {
+                                        self_args: &[Gc<Expr>],
+                                        nonself_args: &[Gc<Expr>])
+        -> Gc<Expr> {
         let summary = trait_.summarise_struct(cx, struct_def);
 
         self.call_substructure_method(cx,
@@ -780,9 +783,9 @@ impl<'a> MethodDef<'a> {
                                trait_: &TraitDef,
                                enum_def: &EnumDef,
                                type_ident: Ident,
-                               self_args: &[@Expr],
-                               nonself_args: &[@Expr])
-                               -> @Expr {
+                               self_args: &[Gc<Expr>],
+                               nonself_args: &[Gc<Expr>])
+                               -> Gc<Expr> {
         let mut matches = Vec::new();
         self.build_enum_match(cx, trait_, enum_def, type_ident,
                               self_args, nonself_args,
@@ -816,12 +819,12 @@ impl<'a> MethodDef<'a> {
                         trait_: &TraitDef,
                         enum_def: &EnumDef,
                         type_ident: Ident,
-                        self_args: &[@Expr],
-                        nonself_args: &[@Expr],
+                        self_args: &[Gc<Expr>],
+                        nonself_args: &[Gc<Expr>],
                         matching: Option<uint>,
                         matches_so_far: &mut Vec<(uint, P<ast::Variant>,
-                                              Vec<(Span, Option<Ident>, @Expr)> )> ,
-                        match_count: uint) -> @Expr {
+                                              Vec<(Span, Option<Ident>, Gc<Expr>)>)> ,
+                        match_count: uint) -> Gc<Expr> {
         if match_count == self_args.len() {
             // we've matched against all arguments, so make the final
             // expression at the bottom of the match tree
@@ -871,7 +874,7 @@ impl<'a> MethodDef<'a> {
                             other: (*other).clone()
                         }
                     }).collect();
-                    EnumMatching(variant_index, variant, field_tuples)
+                    EnumMatching(variant_index, &*variant, field_tuples)
                 }
                 None => {
                     EnumNonMatching(matches_so_far.as_slice())
@@ -905,7 +908,7 @@ impl<'a> MethodDef<'a> {
                 let variant = *enum_def.variants.get(index);
                 let (pattern, idents) = trait_.create_enum_variant_pattern(
                     cx,
-                    variant,
+                    &*variant,
                     current_match_str.as_slice(),
                     ast::MutImmutable);
 
@@ -938,7 +941,7 @@ impl<'a> MethodDef<'a> {
                     let (pattern, idents) =
                         trait_.create_enum_variant_pattern(
                             cx,
-                            variant,
+                            &*variant,
                             current_match_str.as_slice(),
                             ast::MutImmutable);
 
@@ -974,17 +977,17 @@ impl<'a> MethodDef<'a> {
                                       trait_: &TraitDef,
                                       enum_def: &EnumDef,
                                       type_ident: Ident,
-                                      self_args: &[@Expr],
-                                      nonself_args: &[@Expr])
-        -> @Expr {
+                                      self_args: &[Gc<Expr>],
+                                      nonself_args: &[Gc<Expr>])
+        -> Gc<Expr> {
         let summary = enum_def.variants.iter().map(|v| {
             let ident = v.node.name;
             let summary = match v.node.kind {
                 ast::TupleVariantKind(ref args) => {
                     Unnamed(args.iter().map(|va| trait_.set_expn_info(cx, va.ty.span)).collect())
                 }
-                ast::StructVariantKind(struct_def) => {
-                    trait_.summarise_struct(cx, struct_def)
+                ast::StructVariantKind(ref struct_def) => {
+                    trait_.summarise_struct(cx, &**struct_def)
                 }
             };
             (ident, v.span, summary)
@@ -1009,7 +1012,7 @@ impl<'a> TraitDef<'a> {
             None => cx.span_bug(self.span, "trait with empty path in generic `deriving`"),
             Some(name) => *name
         };
-        to_set.expn_info = Some(@codemap::ExpnInfo {
+        to_set.expn_info = Some(box(GC) codemap::ExpnInfo {
             call_site: to_set,
             callee: codemap::NameAndSpan {
                 name: format!("deriving({})", trait_name).to_string(),
@@ -1048,7 +1051,7 @@ impl<'a> TraitDef<'a> {
                           cx: &mut ExtCtxt,
                           field_paths: Vec<ast::Path> ,
                           mutbl: ast::Mutability)
-                          -> Vec<@ast::Pat> {
+                          -> Vec<Gc<ast::Pat>> {
         field_paths.iter().map(|path| {
             cx.pat(path.span,
                         ast::PatIdent(ast::BindByRef(mutbl), (*path).clone(), None))
@@ -1061,7 +1064,7 @@ impl<'a> TraitDef<'a> {
                              struct_def: &StructDef,
                              prefix: &str,
                              mutbl: ast::Mutability)
-                             -> (@ast::Pat, Vec<(Span, Option<Ident>, @Expr)> ) {
+                             -> (Gc<ast::Pat>, Vec<(Span, Option<Ident>, Gc<Expr>)>) {
         if struct_def.fields.is_empty() {
             return (
                 cx.pat_ident_binding_mode(
@@ -1126,7 +1129,7 @@ impl<'a> TraitDef<'a> {
                                    variant: &ast::Variant,
                                    prefix: &str,
                                    mutbl: ast::Mutability)
-        -> (@ast::Pat, Vec<(Span, Option<Ident>, @Expr)> ) {
+        -> (Gc<ast::Pat>, Vec<(Span, Option<Ident>, Gc<Expr>)> ) {
         let variant_ident = variant.node.name;
         match variant.node.kind {
             ast::TupleVariantKind(ref variant_args) => {
@@ -1159,8 +1162,8 @@ impl<'a> TraitDef<'a> {
                 (cx.pat_enum(variant.span, matching_path, subpats),
                  ident_expr)
             }
-            ast::StructVariantKind(struct_def) => {
-                self.create_struct_pattern(cx, variant_ident, struct_def,
+            ast::StructVariantKind(ref struct_def) => {
+                self.create_struct_pattern(cx, variant_ident, &**struct_def,
                                            prefix, mutbl)
             }
         }
@@ -1174,13 +1177,13 @@ Fold the fields. `use_foldl` controls whether this is done
 left-to-right (`true`) or right-to-left (`false`).
 */
 pub fn cs_fold(use_foldl: bool,
-               f: |&mut ExtCtxt, Span, @Expr, @Expr, &[@Expr]| -> @Expr,
-               base: @Expr,
+               f: |&mut ExtCtxt, Span, Gc<Expr>, Gc<Expr>, &[Gc<Expr>]| -> Gc<Expr>,
+               base: Gc<Expr>,
                enum_nonmatch_f: EnumNonMatchFunc,
                cx: &mut ExtCtxt,
                trait_span: Span,
                substructure: &Substructure)
-               -> @Expr {
+               -> Gc<Expr> {
     match *substructure.fields {
         EnumMatching(_, _, ref all_fields) | Struct(ref all_fields) => {
             if use_foldl {
@@ -1221,12 +1224,12 @@ f(cx, span, ~[self_1.method(__arg_1_1, __arg_2_1),
 ~~~
 */
 #[inline]
-pub fn cs_same_method(f: |&mut ExtCtxt, Span, Vec<@Expr> | -> @Expr,
+pub fn cs_same_method(f: |&mut ExtCtxt, Span, Vec<Gc<Expr>>| -> Gc<Expr>,
                       enum_nonmatch_f: EnumNonMatchFunc,
                       cx: &mut ExtCtxt,
                       trait_span: Span,
                       substructure: &Substructure)
-                      -> @Expr {
+                      -> Gc<Expr> {
     match *substructure.fields {
         EnumMatching(_, _, ref all_fields) | Struct(ref all_fields) => {
             // call self_n.method(other_1_n, other_2_n, ...)
@@ -1257,13 +1260,13 @@ fields. `use_foldl` controls whether this is done left-to-right
 */
 #[inline]
 pub fn cs_same_method_fold(use_foldl: bool,
-                           f: |&mut ExtCtxt, Span, @Expr, @Expr| -> @Expr,
-                           base: @Expr,
+                           f: |&mut ExtCtxt, Span, Gc<Expr>, Gc<Expr>| -> Gc<Expr>,
+                           base: Gc<Expr>,
                            enum_nonmatch_f: EnumNonMatchFunc,
                            cx: &mut ExtCtxt,
                            trait_span: Span,
                            substructure: &Substructure)
-                           -> @Expr {
+                           -> Gc<Expr> {
     cs_same_method(
         |cx, span, vals| {
             if use_foldl {
@@ -1285,10 +1288,10 @@ Use a given binop to combine the result of calling the derived method
 on all the fields.
 */
 #[inline]
-pub fn cs_binop(binop: ast::BinOp, base: @Expr,
+pub fn cs_binop(binop: ast::BinOp, base: Gc<Expr>,
                 enum_nonmatch_f: EnumNonMatchFunc,
                 cx: &mut ExtCtxt, trait_span: Span,
-                substructure: &Substructure) -> @Expr {
+                substructure: &Substructure) -> Gc<Expr> {
     cs_same_method_fold(
         true, // foldl is good enough
         |cx, span, old, new| {
@@ -1306,7 +1309,7 @@ pub fn cs_binop(binop: ast::BinOp, base: @Expr,
 #[inline]
 pub fn cs_or(enum_nonmatch_f: EnumNonMatchFunc,
              cx: &mut ExtCtxt, span: Span,
-             substructure: &Substructure) -> @Expr {
+             substructure: &Substructure) -> Gc<Expr> {
     cs_binop(ast::BiOr, cx.expr_bool(span, false),
              enum_nonmatch_f,
              cx, span, substructure)
@@ -1316,7 +1319,7 @@ pub fn cs_or(enum_nonmatch_f: EnumNonMatchFunc,
 #[inline]
 pub fn cs_and(enum_nonmatch_f: EnumNonMatchFunc,
               cx: &mut ExtCtxt, span: Span,
-              substructure: &Substructure) -> @Expr {
+              substructure: &Substructure) -> Gc<Expr> {
     cs_binop(ast::BiAnd, cx.expr_bool(span, true),
              enum_nonmatch_f,
              cx, span, substructure)
diff --git a/src/libsyntax/ext/deriving/generic/ty.rs b/src/libsyntax/ext/deriving/generic/ty.rs
index 602245b4c47..7501b950770 100644
--- a/src/libsyntax/ext/deriving/generic/ty.rs
+++ b/src/libsyntax/ext/deriving/generic/ty.rs
@@ -20,6 +20,7 @@ use ext::build::AstBuilder;
 use codemap::{Span,respan};
 use owned_slice::OwnedSlice;
 
+use std::gc::Gc;
 
 /// The types of pointers
 pub enum PtrTy<'a> {
@@ -81,7 +82,7 @@ impl<'a> Path<'a> {
 /// A type. Supports pointers (except for *), Self, and literals
 pub enum Ty<'a> {
     Self,
-    // &/Box/@ Ty
+    // &/Box/ Ty
     Ptr(Box<Ty<'a>>, PtrTy<'a>),
     // mod::mod::Type<[lifetime], [Params...]>, including a plain type
     // parameter, and things like `int`
@@ -244,7 +245,7 @@ impl<'a> LifetimeBounds<'a> {
 
 
 pub fn get_explicit_self(cx: &ExtCtxt, span: Span, self_ptr: &Option<PtrTy>)
-    -> (@Expr, ast::ExplicitSelf) {
+    -> (Gc<Expr>, ast::ExplicitSelf) {
     let self_path = cx.expr_self(span);
     match *self_ptr {
         None => {
diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs
index a9d5f156a99..77fb013b269 100644
--- a/src/libsyntax/ext/deriving/hash.rs
+++ b/src/libsyntax/ext/deriving/hash.rs
@@ -17,11 +17,13 @@ use ext::deriving::generic::*;
 use ext::deriving::generic::ty::*;
 use parse::token::InternedString;
 
+use std::gc::Gc;
+
 pub fn expand_deriving_hash(cx: &mut ExtCtxt,
                             span: Span,
-                            mitem: @MetaItem,
-                            item: @Item,
-                            push: |@Item|) {
+                            mitem: Gc<MetaItem>,
+                            item: Gc<Item>,
+                            push: |Gc<Item>|) {
 
     let (path, generics, args) = if cx.ecfg.deriving_hash_type_parameter {
         (Path::new_(vec!("std", "hash", "Hash"), None,
@@ -64,7 +66,8 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt,
     hash_trait_def.expand(cx, mitem, item, push);
 }
 
-fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr {
+fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span,
+                     substr: &Substructure) -> Gc<Expr> {
     let state_expr = match substr.nonself_args {
         [state_expr] => state_expr,
         _ => cx.span_bug(trait_span, "incorrect number of arguments in `deriving(Hash)`")
diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs
index 445b21551fd..1833e56dbfb 100644
--- a/src/libsyntax/ext/deriving/mod.rs
+++ b/src/libsyntax/ext/deriving/mod.rs
@@ -22,6 +22,8 @@ use ast::{Item, MetaItem, MetaList, MetaNameValue, MetaWord};
 use ext::base::ExtCtxt;
 use codemap::Span;
 
+use std::gc::Gc;
+
 pub mod bounds;
 pub mod clone;
 pub mod encodable;
@@ -47,9 +49,9 @@ pub mod generic;
 
 pub fn expand_meta_deriving(cx: &mut ExtCtxt,
                             _span: Span,
-                            mitem: @MetaItem,
-                            item: @Item,
-                            push: |@Item|) {
+                            mitem: Gc<MetaItem>,
+                            item: Gc<Item>,
+                            push: |Gc<Item>|) {
     match mitem.node {
         MetaNameValue(_, ref l) => {
             cx.span_err(l.span, "unexpected value in `deriving`");
diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs
index 0db3233c475..735497d9a2c 100644
--- a/src/libsyntax/ext/deriving/primitive.rs
+++ b/src/libsyntax/ext/deriving/primitive.rs
@@ -17,11 +17,13 @@ use ext::deriving::generic::*;
 use ext::deriving::generic::ty::*;
 use parse::token::InternedString;
 
+use std::gc::Gc;
+
 pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt,
                                       span: Span,
-                                      mitem: @MetaItem,
-                                      item: @Item,
-                                      push: |@Item|) {
+                                      mitem: Gc<MetaItem>,
+                                      item: Gc<Item>,
+                                      push: |Gc<Item>|) {
     let inline = cx.meta_word(span, InternedString::new("inline"));
     let attrs = vec!(cx.attribute(span, inline));
     let trait_def = TraitDef {
@@ -70,7 +72,8 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt,
     trait_def.expand(cx, mitem, item, push)
 }
 
-fn cs_from(name: &str, cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr {
+fn cs_from(name: &str, cx: &mut ExtCtxt, trait_span: Span,
+           substr: &Substructure) -> Gc<Expr> {
     let n = match substr.nonself_args {
         [n] => n,
         _ => cx.span_bug(trait_span, "incorrect number of arguments in `deriving(FromPrimitive)`")
diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs
index 86620f1aa1b..f6a15ea917e 100644
--- a/src/libsyntax/ext/deriving/rand.rs
+++ b/src/libsyntax/ext/deriving/rand.rs
@@ -16,11 +16,13 @@ use ext::build::{AstBuilder};
 use ext::deriving::generic::*;
 use ext::deriving::generic::ty::*;
 
+use std::gc::Gc;
+
 pub fn expand_deriving_rand(cx: &mut ExtCtxt,
                             span: Span,
-                            mitem: @MetaItem,
-                            item: @Item,
-                            push: |@Item|) {
+                            mitem: Gc<MetaItem>,
+                            item: Gc<Item>,
+                            push: |Gc<Item>|) {
     let trait_def = TraitDef {
         span: span,
         attributes: Vec::new(),
@@ -53,7 +55,8 @@ pub fn expand_deriving_rand(cx: &mut ExtCtxt,
     trait_def.expand(cx, mitem, item, push)
 }
 
-fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr {
+fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span,
+                     substr: &Substructure) -> Gc<Expr> {
     let rng = match substr.nonself_args {
         [rng] => vec!( rng ),
         _ => cx.bug("Incorrect number of arguments to `rand` in `deriving(Rand)`")
@@ -134,8 +137,8 @@ fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure)
                   trait_span: Span,
                   ctor_ident: Ident,
                   summary: &StaticFields,
-                  rand_call: |&mut ExtCtxt, Span| -> @Expr)
-                  -> @Expr {
+                  rand_call: |&mut ExtCtxt, Span| -> Gc<Expr>)
+                  -> Gc<Expr> {
         match *summary {
             Unnamed(ref fields) => {
                 if fields.is_empty() {
diff --git a/src/libsyntax/ext/deriving/show.rs b/src/libsyntax/ext/deriving/show.rs
index 1124cf6d7cb..9c5e41c8f60 100644
--- a/src/libsyntax/ext/deriving/show.rs
+++ b/src/libsyntax/ext/deriving/show.rs
@@ -20,12 +20,13 @@ use parse::token;
 
 use std::collections::HashMap;
 use std::string::String;
+use std::gc::Gc;
 
 pub fn expand_deriving_show(cx: &mut ExtCtxt,
                             span: Span,
-                            mitem: @MetaItem,
-                            item: @Item,
-                            push: |@Item|) {
+                            mitem: Gc<MetaItem>,
+                            item: Gc<Item>,
+                            push: |Gc<Item>|) {
     // &mut ::std::fmt::Formatter
     let fmtr = Ptr(box Literal(Path::new(vec!("std", "fmt", "Formatter"))),
                    Borrowed(None, ast::MutMutable));
@@ -57,7 +58,7 @@ pub fn expand_deriving_show(cx: &mut ExtCtxt,
 // we construct a format string and then defer to std::fmt, since that
 // knows what's up with formatting at so on.
 fn show_substructure(cx: &mut ExtCtxt, span: Span,
-                     substr: &Substructure) -> @Expr {
+                     substr: &Substructure) -> Gc<Expr> {
     // build `<name>`, `<name>({}, {}, ...)` or `<name> { <field>: {},
     // <field>: {}, ... }` based on the "shape".
     //
diff --git a/src/libsyntax/ext/deriving/zero.rs b/src/libsyntax/ext/deriving/zero.rs
index 0328f7b470c..93947251223 100644
--- a/src/libsyntax/ext/deriving/zero.rs
+++ b/src/libsyntax/ext/deriving/zero.rs
@@ -16,11 +16,13 @@ use ext::deriving::generic::*;
 use ext::deriving::generic::ty::*;
 use parse::token::InternedString;
 
+use std::gc::Gc;
+
 pub fn expand_deriving_zero(cx: &mut ExtCtxt,
                             span: Span,
-                            mitem: @MetaItem,
-                            item: @Item,
-                            push: |@Item|) {
+                            mitem: Gc<MetaItem>,
+                            item: Gc<Item>,
+                            push: |Gc<Item>|) {
     let inline = cx.meta_word(span, InternedString::new("inline"));
     let attrs = vec!(cx.attribute(span, inline));
     let trait_def = TraitDef {
@@ -63,7 +65,8 @@ pub fn expand_deriving_zero(cx: &mut ExtCtxt,
     trait_def.expand(cx, mitem, item, push)
 }
 
-fn zero_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr {
+fn zero_substructure(cx: &mut ExtCtxt, trait_span: Span,
+                     substr: &Substructure) -> Gc<Expr> {
     let zero_ident = vec!(
         cx.ident_of("std"),
         cx.ident_of("num"),
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index bb335e7bed0..9efcb81e844 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -29,7 +29,9 @@ use visit;
 use visit::Visitor;
 use util::small_vector::SmallVector;
 
-pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
+use std::gc::Gc;
+
+pub fn expand_expr(e: Gc<ast::Expr>, fld: &mut MacroExpander) -> Gc<ast::Expr> {
     match e.node {
         // expr_mac should really be expr_ext or something; it's the
         // entry-point for all syntax extensions.
@@ -115,7 +117,7 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
                         fld.fold_expr(marked_after).node.clone();
                     fld.cx.bt_pop();
 
-                    @ast::Expr {
+                    box(GC) ast::Expr {
                         id: ast::DUMMY_NODE_ID,
                         node: fully_expanded,
                         span: e.span,
@@ -256,7 +258,7 @@ fn expand_loop_block(loop_block: P<Block>,
             // in a block enclosed by loop head.
             fld.extsbox.push_frame();
             fld.extsbox.info().pending_renames.push(rename);
-            let expanded_block = expand_block_elts(loop_block, fld);
+            let expanded_block = expand_block_elts(&*loop_block, fld);
             fld.extsbox.pop_frame();
 
             (expanded_block, Some(renamed_ident))
@@ -277,8 +279,8 @@ macro_rules! with_exts_frame (
 )
 
 // When we enter a module, record it, for the sake of `module!`
-pub fn expand_item(it: @ast::Item, fld: &mut MacroExpander)
-                   -> SmallVector<@ast::Item> {
+pub fn expand_item(it: Gc<ast::Item>, fld: &mut MacroExpander)
+                   -> SmallVector<Gc<ast::Item>> {
     let it = expand_item_modifiers(it, fld);
 
     let mut decorator_items = SmallVector::zero();
@@ -301,7 +303,7 @@ pub fn expand_item(it: @ast::Item, fld: &mut MacroExpander)
 
                 // we'd ideally decorator_items.push_all(expand_item(item, fld)),
                 // but that double-mut-borrows fld
-                let mut items: SmallVector<@ast::Item> = SmallVector::zero();
+                let mut items: SmallVector<Gc<ast::Item>> = SmallVector::zero();
                 dec_fn(fld.cx, attr.span, attr.node.value, it,
                        |item| items.push(item));
                 decorator_items.extend(items.move_iter()
@@ -320,17 +322,17 @@ pub fn expand_item(it: @ast::Item, fld: &mut MacroExpander)
             let macro_escape = contains_macro_escape(new_attrs.as_slice());
             let result = with_exts_frame!(fld.extsbox,
                                           macro_escape,
-                                          noop_fold_item(it, fld));
+                                          noop_fold_item(&*it, fld));
             fld.cx.mod_pop();
             result
         },
         _ => {
-            let it = @ast::Item {
+            let it = box(GC) ast::Item {
                 attrs: new_attrs,
                 ..(*it).clone()
 
             };
-            noop_fold_item(it, fld)
+            noop_fold_item(&*it, fld)
         }
     };
 
@@ -338,8 +340,8 @@ pub fn expand_item(it: @ast::Item, fld: &mut MacroExpander)
     new_items
 }
 
-fn expand_item_modifiers(mut it: @ast::Item, fld: &mut MacroExpander)
-                         -> @ast::Item {
+fn expand_item_modifiers(mut it: Gc<ast::Item>, fld: &mut MacroExpander)
+                         -> Gc<ast::Item> {
     let (modifiers, attrs) = it.attrs.partitioned(|attr| {
         match fld.extsbox.find(&intern(attr.name().get())) {
             Some(&ItemModifier(_)) => true,
@@ -347,7 +349,7 @@ fn expand_item_modifiers(mut it: @ast::Item, fld: &mut MacroExpander)
         }
     });
 
-    it = @ast::Item {
+    it = box(GC) ast::Item {
         attrs: attrs,
         ..(*it).clone()
     };
@@ -388,8 +390,8 @@ pub fn contains_macro_escape(attrs: &[ast::Attribute]) -> bool {
 
 // Support for item-position macro invocations, exactly the same
 // logic as for expression-position macro invocations.
-pub fn expand_item_mac(it: @ast::Item, fld: &mut MacroExpander)
-                       -> SmallVector<@ast::Item> {
+pub fn expand_item_mac(it: Gc<ast::Item>, fld: &mut MacroExpander)
+                       -> SmallVector<Gc<ast::Item>> {
     let (pth, tts) = match it.node {
         ItemMac(codemap::Spanned {
             node: MacInvocTT(ref pth, ref tts, _),
@@ -494,7 +496,7 @@ pub fn expand_item_mac(it: @ast::Item, fld: &mut MacroExpander)
 }
 
 // expand a stmt
-pub fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<@Stmt> {
+pub fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<Gc<Stmt>> {
     // why the copying here and not in expand_expr?
     // looks like classic changed-in-only-one-place
     let (pth, tts, semi) = match s.node {
@@ -550,7 +552,7 @@ pub fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<@Stmt> {
                 }
             };
 
-            mark_stmt(expanded,fm)
+            mark_stmt(&*expanded,fm)
         }
 
         _ => {
@@ -561,20 +563,20 @@ pub fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<@Stmt> {
     };
 
     // Keep going, outside-in.
-    let fully_expanded = fld.fold_stmt(marked_after);
+    let fully_expanded = fld.fold_stmt(&*marked_after);
     if fully_expanded.is_empty() {
         fld.cx.span_err(pth.span, "macro didn't expand to a statement");
         return SmallVector::zero();
     }
     fld.cx.bt_pop();
-    let fully_expanded: SmallVector<@Stmt> = fully_expanded.move_iter()
-            .map(|s| @Spanned { span: s.span, node: s.node.clone() })
+    let fully_expanded: SmallVector<Gc<Stmt>> = fully_expanded.move_iter()
+            .map(|s| box(GC) Spanned { span: s.span, node: s.node.clone() })
             .collect();
 
     fully_expanded.move_iter().map(|s| {
         match s.node {
             StmtExpr(e, stmt_id) if semi => {
-                @Spanned {
+                box(GC) Spanned {
                     span: s.span,
                     node: StmtSemi(e, stmt_id)
                 }
@@ -587,7 +589,7 @@ pub fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<@Stmt> {
 // expand a non-macro stmt. this is essentially the fallthrough for
 // expand_stmt, above.
 fn expand_non_macro_stmt(s: &Stmt, fld: &mut MacroExpander)
-                         -> SmallVector<@Stmt> {
+                         -> SmallVector<Gc<Stmt>> {
     // is it a let?
     match s.node {
         StmtDecl(decl, node_id) => {
@@ -612,7 +614,7 @@ fn expand_non_macro_stmt(s: &Stmt, fld: &mut MacroExpander)
                     // names, as well... but that should be okay, as long as
                     // the new names are gensyms for the old ones.
                     let mut name_finder = new_name_finder(Vec::new());
-                    name_finder.visit_pat(expanded_pat,());
+                    name_finder.visit_pat(&*expanded_pat,());
                     // generate fresh names, push them to a new pending list
                     let mut new_pending_renames = Vec::new();
                     for ident in name_finder.ident_accumulator.iter() {
@@ -631,7 +633,7 @@ fn expand_non_macro_stmt(s: &Stmt, fld: &mut MacroExpander)
                     // also, don't forget to expand the init:
                     let new_init_opt = init.map(|e| fld.fold_expr(e));
                     let rewritten_local =
-                        @Local {
+                        box(GC) Local {
                             ty: local.ty,
                             pat: rewritten_pat,
                             init: new_init_opt,
@@ -639,8 +641,8 @@ fn expand_non_macro_stmt(s: &Stmt, fld: &mut MacroExpander)
                             span: span,
                             source: source
                         };
-                    SmallVector::one(@Spanned {
-                        node: StmtDecl(@Spanned {
+                    SmallVector::one(box(GC) Spanned {
+                        node: StmtDecl(box(GC) Spanned {
                                 node: DeclLocal(rewritten_local),
                                 span: stmt_span
                             },
@@ -687,7 +689,7 @@ impl Visitor<()> for NewNameFinderContext {
                 }
                 // visit optional subpattern of pat_ident:
                 for subpat in inner.iter() {
-                    self.visit_pat(*subpat, ())
+                    self.visit_pat(&**subpat, ())
                 }
             }
             // use the default traversal for non-pat_idents
@@ -725,9 +727,9 @@ pub fn expand_block_elts(b: &Block, fld: &mut MacroExpander) -> P<Block> {
             let renamed_stmt = {
                 let pending_renames = &mut fld.extsbox.info().pending_renames;
                 let mut rename_fld = renames_to_fold(pending_renames);
-                rename_fld.fold_stmt(*x).expect_one("rename_fold didn't return one value")
+                rename_fld.fold_stmt(&**x).expect_one("rename_fold didn't return one value")
             };
-            fld.fold_stmt(renamed_stmt).move_iter()
+            fld.fold_stmt(&*renamed_stmt).move_iter()
         }).collect();
     let new_expr = b.expr.map(|x| {
         let expr = {
@@ -863,24 +865,24 @@ pub struct MacroExpander<'a, 'b> {
 }
 
 impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
-    fn fold_expr(&mut self, expr: @ast::Expr) -> @ast::Expr {
+    fn fold_expr(&mut self, expr: Gc<ast::Expr>) -> Gc<ast::Expr> {
         expand_expr(expr, self)
     }
 
-    fn fold_pat(&mut self, pat: @ast::Pat) -> @ast::Pat {
+    fn fold_pat(&mut self, pat: Gc<ast::Pat>) -> Gc<ast::Pat> {
         expand_pat(pat, self)
     }
 
-    fn fold_item(&mut self, item: @ast::Item) -> SmallVector<@ast::Item> {
+    fn fold_item(&mut self, item: Gc<ast::Item>) -> SmallVector<Gc<ast::Item>> {
         expand_item(item, self)
     }
 
-    fn fold_stmt(&mut self, stmt: &ast::Stmt) -> SmallVector<@ast::Stmt> {
+    fn fold_stmt(&mut self, stmt: &ast::Stmt) -> SmallVector<Gc<ast::Stmt>> {
         expand_stmt(stmt, self)
     }
 
     fn fold_block(&mut self, block: P<Block>) -> P<Block> {
-        expand_block(block, self)
+        expand_block(&*block, self)
     }
 
     fn new_span(&mut self, span: Span) -> Span {
@@ -976,7 +978,7 @@ fn mark_tts(tts: &[TokenTree], m: Mrk) -> Vec<TokenTree> {
 }
 
 // apply a given mark to the given expr. Used following the expansion of a macro.
-fn mark_expr(expr: @ast::Expr, m: Mrk) -> @ast::Expr {
+fn mark_expr(expr: Gc<ast::Expr>, m: Mrk) -> Gc<ast::Expr> {
     new_mark_folder(m).fold_expr(expr)
 }
 
@@ -986,17 +988,17 @@ fn mark_pat(pat: @ast::Pat, m: Mrk) -> @ast::Pat {
 }
 
 // apply a given mark to the given stmt. Used following the expansion of a macro.
-fn mark_stmt(expr: &ast::Stmt, m: Mrk) -> @ast::Stmt {
+fn mark_stmt(expr: &ast::Stmt, m: Mrk) -> Gc<ast::Stmt> {
     new_mark_folder(m).fold_stmt(expr)
             .expect_one("marking a stmt didn't return a stmt")
 }
 
 // apply a given mark to the given item. Used following the expansion of a macro.
-fn mark_item(expr: @ast::Item, m: Mrk) -> SmallVector<@ast::Item> {
+fn mark_item(expr: Gc<ast::Item>, m: Mrk) -> SmallVector<Gc<ast::Item>> {
     new_mark_folder(m).fold_item(expr)
 }
 
-fn original_span(cx: &ExtCtxt) -> @codemap::ExpnInfo {
+fn original_span(cx: &ExtCtxt) -> Gc<codemap::ExpnInfo> {
     let mut relevant_info = cx.backtrace();
     let mut einfo = relevant_info.unwrap();
     loop {
@@ -1134,7 +1136,7 @@ mod test {
             node: Attribute_ {
                 id: attr::mk_attr_id(),
                 style: AttrOuter,
-                value: @Spanned {
+                value: box(GC) Spanned {
                     node: MetaWord(token::intern_and_get_ident(s)),
                     span: codemap::DUMMY_SP,
                 },
diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs
index 2db0d047942..8cf290b826b 100644
--- a/src/libsyntax/ext/format.rs
+++ b/src/libsyntax/ext/format.rs
@@ -20,6 +20,7 @@ use rsparse = parse;
 
 use parse = fmt_macros;
 use std::collections::{HashMap, HashSet};
+use std::gc::Gc;
 
 #[deriving(PartialEq)]
 enum ArgumentType {
@@ -39,20 +40,20 @@ struct Context<'a, 'b> {
 
     // Parsed argument expressions and the types that we've found so far for
     // them.
-    args: Vec<@ast::Expr>,
+    args: Vec<Gc<ast::Expr>>,
     arg_types: Vec<Option<ArgumentType>>,
     // Parsed named expressions and the types that we've found for them so far.
     // Note that we keep a side-array of the ordering of the named arguments
     // found to be sure that we can translate them in the same order that they
     // were declared in.
-    names: HashMap<String, @ast::Expr>,
+    names: HashMap<String, Gc<ast::Expr>>,
     name_types: HashMap<String, ArgumentType>,
     name_ordering: Vec<String>,
 
     // Collection of the compiled `rt::Piece` structures
-    pieces: Vec<@ast::Expr> ,
+    pieces: Vec<Gc<ast::Expr>>,
     name_positions: HashMap<String, uint>,
-    method_statics: Vec<@ast::Item> ,
+    method_statics: Vec<Gc<ast::Item>>,
 
     // Updated as arguments are consumed or methods are entered
     nest_level: uint,
@@ -60,8 +61,8 @@ struct Context<'a, 'b> {
 }
 
 pub enum Invocation {
-    Call(@ast::Expr),
-    MethodCall(@ast::Expr, ast::Ident),
+    Call(Gc<ast::Expr>),
+    MethodCall(Gc<ast::Expr>, ast::Ident),
 }
 
 /// Parses the arguments from the given list of tokens, returning None
@@ -74,10 +75,10 @@ pub enum Invocation {
 ///           named arguments))
 fn parse_args(ecx: &mut ExtCtxt, sp: Span, allow_method: bool,
               tts: &[ast::TokenTree])
-    -> (Invocation, Option<(@ast::Expr, Vec<@ast::Expr>, Vec<String>,
-                            HashMap<String, @ast::Expr>)>) {
+    -> (Invocation, Option<(Gc<ast::Expr>, Vec<Gc<ast::Expr>>, Vec<String>,
+                            HashMap<String, Gc<ast::Expr>>)>) {
     let mut args = Vec::new();
-    let mut names = HashMap::<String, @ast::Expr>::new();
+    let mut names = HashMap::<String, Gc<ast::Expr>>::new();
     let mut order = Vec::new();
 
     let mut p = rsparse::new_parser_from_tts(ecx.parse_sess(),
@@ -399,7 +400,7 @@ impl<'a, 'b> Context<'a, 'b> {
           self.ecx.ident_of("rt"), self.ecx.ident_of(s))
     }
 
-    fn none(&self) -> @ast::Expr {
+    fn none(&self) -> Gc<ast::Expr> {
         let none = self.ecx.path_global(self.fmtsp, vec!(
                 self.ecx.ident_of("std"),
                 self.ecx.ident_of("option"),
@@ -407,7 +408,7 @@ impl<'a, 'b> Context<'a, 'b> {
         self.ecx.expr_path(none)
     }
 
-    fn some(&self, e: @ast::Expr) -> @ast::Expr {
+    fn some(&self, e: Gc<ast::Expr>) -> Gc<ast::Expr> {
         let p = self.ecx.path_global(self.fmtsp, vec!(
                 self.ecx.ident_of("std"),
                 self.ecx.ident_of("option"),
@@ -416,7 +417,7 @@ impl<'a, 'b> Context<'a, 'b> {
         self.ecx.expr_call(self.fmtsp, p, vec!(e))
     }
 
-    fn trans_count(&self, c: parse::Count) -> @ast::Expr {
+    fn trans_count(&self, c: parse::Count) -> Gc<ast::Expr> {
         let sp = self.fmtsp;
         match c {
             parse::CountIs(i) => {
@@ -447,7 +448,7 @@ impl<'a, 'b> Context<'a, 'b> {
         }
     }
 
-    fn trans_method(&mut self, method: &parse::Method) -> @ast::Expr {
+    fn trans_method(&mut self, method: &parse::Method) -> Gc<ast::Expr> {
         let sp = self.fmtsp;
         let method = match *method {
             parse::Select(ref arms, ref default) => {
@@ -528,7 +529,7 @@ impl<'a, 'b> Context<'a, 'b> {
     }
 
     /// Translate a `parse::Piece` to a static `rt::Piece`
-    fn trans_piece(&mut self, piece: &parse::Piece) -> @ast::Expr {
+    fn trans_piece(&mut self, piece: &parse::Piece) -> Gc<ast::Expr> {
         let sp = self.fmtsp;
         match *piece {
             parse::String(s) => {
@@ -615,7 +616,7 @@ impl<'a, 'b> Context<'a, 'b> {
 
     /// Actually builds the expression which the iformat! block will be expanded
     /// to
-    fn to_expr(&self, invocation: Invocation) -> @ast::Expr {
+    fn to_expr(&self, invocation: Invocation) -> Gc<ast::Expr> {
         let mut lets = Vec::new();
         let mut locals = Vec::new();
         let mut names = Vec::from_fn(self.name_positions.len(), |_| None);
@@ -625,8 +626,8 @@ impl<'a, 'b> Context<'a, 'b> {
         // First, declare all of our methods that are statics
         for &method in self.method_statics.iter() {
             let decl = respan(self.fmtsp, ast::DeclItem(method));
-            lets.push(@respan(self.fmtsp,
-                              ast::StmtDecl(@decl, ast::DUMMY_NODE_ID)));
+            lets.push(box(GC) respan(self.fmtsp,
+                              ast::StmtDecl(box(GC) decl, ast::DUMMY_NODE_ID)));
         }
 
         // Next, build up the static array which will become our precompiled
@@ -653,7 +654,8 @@ impl<'a, 'b> Context<'a, 'b> {
         let item = self.ecx.item(self.fmtsp, static_name,
                                  self.static_attrs(), st);
         let decl = respan(self.fmtsp, ast::DeclItem(item));
-        lets.push(@respan(self.fmtsp, ast::StmtDecl(@decl, ast::DUMMY_NODE_ID)));
+        lets.push(box(GC) respan(self.fmtsp,
+                                 ast::StmtDecl(box(GC) decl, ast::DUMMY_NODE_ID)));
 
         // Right now there is a bug such that for the expression:
         //      foo(bar(&1))
@@ -766,8 +768,8 @@ impl<'a, 'b> Context<'a, 'b> {
         self.ecx.expr_match(self.fmtsp, head, vec!(arm))
     }
 
-    fn format_arg(&self, sp: Span, argno: Position, arg: @ast::Expr)
-                  -> @ast::Expr {
+    fn format_arg(&self, sp: Span, argno: Position, arg: Gc<ast::Expr>)
+                  -> Gc<ast::Expr> {
         let ty = match argno {
             Exact(ref i) => self.arg_types.get(*i).get_ref(),
             Named(ref s) => self.name_types.get(s)
@@ -854,9 +856,12 @@ pub fn expand_format_args_method(ecx: &mut ExtCtxt, sp: Span,
 /// expression.
 pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
                                     invocation: Invocation,
-                                    efmt: @ast::Expr, args: Vec<@ast::Expr>,
+                                    efmt: Gc<ast::Expr>,
+                                    args: Vec<Gc<ast::Expr>>,
                                     name_ordering: Vec<String>,
-                                    names: HashMap<String, @ast::Expr>) -> @ast::Expr {
+                                    names: HashMap<String, Gc<ast::Expr>>)
+    -> Gc<ast::Expr>
+{
     let arg_types = Vec::from_fn(args.len(), |_| None);
     let mut cx = Context {
         ecx: ecx,
diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs
index 0f5928ee198..5906f480d42 100644
--- a/src/libsyntax/ext/quote.rs
+++ b/src/libsyntax/ext/quote.rs
@@ -17,6 +17,7 @@ use parse::token::*;
 use parse::token;
 use parse;
 
+use std::gc::Gc;
 
 /**
 *
@@ -50,6 +51,8 @@ pub mod rt {
     pub use parse::new_parser_from_tts;
     pub use codemap::{BytePos, Span, dummy_spanned};
 
+    use std::gc::Gc;
+
     pub trait ToTokens {
         fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> ;
     }
@@ -85,13 +88,13 @@ pub mod rt {
         }
     }
 
-    impl ToSource for @ast::Item {
+    impl ToSource for Gc<ast::Item> {
         fn to_source(&self) -> String {
             pprust::item_to_str(*self)
         }
     }
 
-    impl<'a> ToSource for &'a [@ast::Item] {
+    impl<'a> ToSource for &'a [Gc<ast::Item>] {
         fn to_source(&self) -> String {
             self.iter()
                 .map(|i| i.to_source())
@@ -123,7 +126,7 @@ pub mod rt {
         }
     }
 
-    impl ToSource for @ast::Expr {
+    impl ToSource for Gc<ast::Expr> {
         fn to_source(&self) -> String {
             pprust::expr_to_str(*self)
         }
@@ -263,12 +266,12 @@ pub mod rt {
     )
 
     impl_to_tokens!(ast::Ident)
-    impl_to_tokens!(@ast::Item)
-    impl_to_tokens_self!(&'a [@ast::Item])
+    impl_to_tokens!(Gc<ast::Item>)
+    impl_to_tokens_self!(&'a [Gc<ast::Item>])
     impl_to_tokens!(ast::Ty)
     impl_to_tokens_self!(&'a [ast::Ty])
     impl_to_tokens!(Generics)
-    impl_to_tokens!(@ast::Expr)
+    impl_to_tokens!(Gc<ast::Expr>)
     impl_to_tokens!(ast::Block)
     impl_to_tokens!(ast::Arg)
     impl_to_tokens_self!(&'a str)
@@ -287,15 +290,15 @@ pub mod rt {
     impl_to_tokens!(u64)
 
     pub trait ExtParseUtils {
-        fn parse_item(&self, s: String) -> @ast::Item;
-        fn parse_expr(&self, s: String) -> @ast::Expr;
-        fn parse_stmt(&self, s: String) -> @ast::Stmt;
+        fn parse_item(&self, s: String) -> Gc<ast::Item>;
+        fn parse_expr(&self, s: String) -> Gc<ast::Expr>;
+        fn parse_stmt(&self, s: String) -> Gc<ast::Stmt>;
         fn parse_tts(&self, s: String) -> Vec<ast::TokenTree> ;
     }
 
     impl<'a> ExtParseUtils for ExtCtxt<'a> {
 
-        fn parse_item(&self, s: String) -> @ast::Item {
+        fn parse_item(&self, s: String) -> Gc<ast::Item> {
             let res = parse::parse_item_from_source_str(
                 "<quote expansion>".to_string(),
                 s,
@@ -310,7 +313,7 @@ pub mod rt {
             }
         }
 
-        fn parse_stmt(&self, s: String) -> @ast::Stmt {
+        fn parse_stmt(&self, s: String) -> Gc<ast::Stmt> {
             parse::parse_stmt_from_source_str("<quote expansion>".to_string(),
                                               s,
                                               self.cfg(),
@@ -318,7 +321,7 @@ pub mod rt {
                                               self.parse_sess())
         }
 
-        fn parse_expr(&self, s: String) -> @ast::Expr {
+        fn parse_expr(&self, s: String) -> Gc<ast::Expr> {
             parse::parse_expr_from_source_str("<quote expansion>".to_string(),
                                               s,
                                               self.cfg(),
@@ -400,7 +403,7 @@ fn id_ext(str: &str) -> ast::Ident {
 }
 
 // Lift an ident to the expr that evaluates to that ident.
-fn mk_ident(cx: &ExtCtxt, sp: Span, ident: ast::Ident) -> @ast::Expr {
+fn mk_ident(cx: &ExtCtxt, sp: Span, ident: ast::Ident) -> Gc<ast::Expr> {
     let e_str = cx.expr_str(sp, token::get_ident(ident));
     cx.expr_method_call(sp,
                         cx.expr_ident(sp, id_ext("ext_cx")),
@@ -408,17 +411,17 @@ fn mk_ident(cx: &ExtCtxt, sp: Span, ident: ast::Ident) -> @ast::Expr {
                         vec!(e_str))
 }
 
-fn mk_ast_path(cx: &ExtCtxt, sp: Span, name: &str) -> @ast::Expr {
+fn mk_ast_path(cx: &ExtCtxt, sp: Span, name: &str) -> Gc<ast::Expr> {
     let idents = vec!(id_ext("syntax"), id_ext("ast"), id_ext(name));
     cx.expr_path(cx.path_global(sp, idents))
 }
 
-fn mk_token_path(cx: &ExtCtxt, sp: Span, name: &str) -> @ast::Expr {
+fn mk_token_path(cx: &ExtCtxt, sp: Span, name: &str) -> Gc<ast::Expr> {
     let idents = vec!(id_ext("syntax"), id_ext("parse"), id_ext("token"), id_ext(name));
     cx.expr_path(cx.path_global(sp, idents))
 }
 
-fn mk_binop(cx: &ExtCtxt, sp: Span, bop: token::BinOp) -> @ast::Expr {
+fn mk_binop(cx: &ExtCtxt, sp: Span, bop: token::BinOp) -> Gc<ast::Expr> {
     let name = match bop {
         PLUS => "PLUS",
         MINUS => "MINUS",
@@ -434,7 +437,7 @@ fn mk_binop(cx: &ExtCtxt, sp: Span, bop: token::BinOp) -> @ast::Expr {
     mk_token_path(cx, sp, name)
 }
 
-fn mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> @ast::Expr {
+fn mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> Gc<ast::Expr> {
 
     match *tok {
         BINOP(binop) => {
@@ -565,7 +568,8 @@ fn mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> @ast::Expr {
     mk_token_path(cx, sp, name)
 }
 
-fn mk_tt(cx: &ExtCtxt, sp: Span, tt: &ast::TokenTree) -> Vec<@ast::Stmt> {
+
+fn mk_tt(cx: &ExtCtxt, sp: Span, tt: &ast::TokenTree) -> Vec<Gc<ast::Stmt>> {
     match *tt {
         ast::TTTok(sp, ref tok) => {
             let e_sp = cx.expr_ident(sp, id_ext("_sp"));
@@ -605,7 +609,7 @@ fn mk_tt(cx: &ExtCtxt, sp: Span, tt: &ast::TokenTree) -> Vec<@ast::Stmt> {
 }
 
 fn mk_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-    -> Vec<@ast::Stmt> {
+    -> Vec<Gc<ast::Stmt>> {
     let mut ss = Vec::new();
     for tt in tts.iter() {
         ss.push_all_move(mk_tt(cx, sp, tt));
@@ -614,7 +618,7 @@ fn mk_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree])
 }
 
 fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-              -> (@ast::Expr, @ast::Expr) {
+              -> (Gc<ast::Expr>, Gc<ast::Expr>) {
     // NB: It appears that the main parser loses its mind if we consider
     // $foo as a TTNonterminal during the main parse, so we have to re-parse
     // under quote_depth > 0. This is silly and should go away; the _guess_ is
@@ -686,8 +690,8 @@ fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree])
 
 fn expand_wrapper(cx: &ExtCtxt,
                   sp: Span,
-                  cx_expr: @ast::Expr,
-                  expr: @ast::Expr) -> @ast::Expr {
+                  cx_expr: Gc<ast::Expr>,
+                  expr: Gc<ast::Expr>) -> Gc<ast::Expr> {
     let uses = [
         &["syntax", "ext", "quote", "rt"],
     ].iter().map(|path| {
@@ -703,8 +707,8 @@ fn expand_wrapper(cx: &ExtCtxt,
 fn expand_parse_call(cx: &ExtCtxt,
                      sp: Span,
                      parse_method: &str,
-                     arg_exprs: Vec<@ast::Expr> ,
-                     tts: &[ast::TokenTree]) -> @ast::Expr {
+                     arg_exprs: Vec<Gc<ast::Expr>>,
+                     tts: &[ast::TokenTree]) -> Gc<ast::Expr> {
     let (cx_expr, tts_expr) = expand_tts(cx, sp, tts);
 
     let cfg_call = || cx.expr_method_call(
diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs
index 93b66ede267..915fc16c156 100644
--- a/src/libsyntax/ext/source_util.rs
+++ b/src/libsyntax/ext/source_util.rs
@@ -19,6 +19,7 @@ use parse;
 use parse::token;
 use print::pprust;
 
+use std::gc::Gc;
 use std::io::File;
 use std::rc::Rc;
 use std::str;
@@ -163,7 +164,7 @@ pub fn expand_include_bin(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
 }
 
 // recur along an ExpnInfo chain to find the original expression
-fn topmost_expn_info(expn_info: @codemap::ExpnInfo) -> @codemap::ExpnInfo {
+fn topmost_expn_info(expn_info: Gc<codemap::ExpnInfo>) -> Gc<codemap::ExpnInfo> {
     match *expn_info {
         ExpnInfo { call_site: ref call_site, .. } => {
             match call_site.expn_info {
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs
index e74861f6efe..85035a8d38e 100644
--- a/src/libsyntax/ext/tt/macro_parser.rs
+++ b/src/libsyntax/ext/tt/macro_parser.rs
@@ -452,7 +452,7 @@ pub fn parse_nt(p: &mut Parser, name: &str) -> Nonterminal {
       "meta" => token::NtMeta(p.parse_meta_item()),
       "tt" => {
         p.quote_depth += 1u; //but in theory, non-quoted tts might be useful
-        let res = token::NtTT(@p.parse_token_tree());
+        let res = token::NtTT(box(GC) p.parse_token_tree());
         p.quote_depth -= 1u;
         res
       }
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index c78d4d258f6..6607b6451c0 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -29,6 +29,7 @@ use util::small_vector::SmallVector;
 
 use std::cell::RefCell;
 use std::rc::Rc;
+use std::gc::Gc;
 
 struct ParserAnyMacro<'a> {
     parser: RefCell<Parser<'a>>,
@@ -58,17 +59,17 @@ impl<'a> ParserAnyMacro<'a> {
 }
 
 impl<'a> MacResult for ParserAnyMacro<'a> {
-    fn make_expr(&self) -> Option<@ast::Expr> {
+    fn make_expr(&self) -> Option<Gc<ast::Expr>> {
         let ret = self.parser.borrow_mut().parse_expr();
         self.ensure_complete_parse(true);
         Some(ret)
     }
-    fn make_pat(&self) -> Option<@ast::Pat> {
+    fn make_pat(&self) -> Option<Gc<ast::Pat>> {
         let ret = self.parser.borrow_mut().parse_pat();
         self.ensure_complete_parse(false);
         Some(ret)
     }
-    fn make_items(&self) -> Option<SmallVector<@ast::Item>> {
+    fn make_items(&self) -> Option<SmallVector<Gc<ast::Item>>> {
         let mut ret = SmallVector::zero();
         loop {
             let mut parser = self.parser.borrow_mut();
@@ -81,7 +82,7 @@ impl<'a> MacResult for ParserAnyMacro<'a> {
         self.ensure_complete_parse(false);
         Some(ret)
     }
-    fn make_stmt(&self) -> Option<@ast::Stmt> {
+    fn make_stmt(&self) -> Option<Gc<ast::Stmt>> {
         let attrs = self.parser.borrow_mut().parse_outer_attributes();
         let ret = self.parser.borrow_mut().parse_stmt(attrs);
         self.ensure_complete_parse(true);
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 03d0c283bcc..c20d1b70996 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -17,6 +17,7 @@ use owned_slice::OwnedSlice;
 use util::small_vector::SmallVector;
 
 use std::rc::Rc;
+use std::gc::Gc;
 
 // We may eventually want to be able to fold over type parameters, too.
 pub trait Folder {
@@ -24,11 +25,11 @@ pub trait Folder {
         noop_fold_crate(c, self)
     }
 
-    fn fold_meta_items(&mut self, meta_items: &[@MetaItem]) -> Vec<@MetaItem> {
+    fn fold_meta_items(&mut self, meta_items: &[Gc<MetaItem>]) -> Vec<Gc<MetaItem>> {
         meta_items.iter().map(|x| fold_meta_item_(*x, self)).collect()
     }
 
-    fn fold_view_path(&mut self, view_path: @ViewPath) -> @ViewPath {
+    fn fold_view_path(&mut self, view_path: Gc<ViewPath>) -> Gc<ViewPath> {
         let inner_view_path = match view_path.node {
             ViewPathSimple(ref ident, ref path, node_id) => {
                 let id = self.new_id(node_id);
@@ -60,7 +61,7 @@ pub trait Folder {
                              id)
             }
         };
-        @Spanned {
+        box(GC) Spanned {
             node: inner_view_path,
             span: self.new_span(view_path.span),
         }
@@ -70,12 +71,12 @@ pub trait Folder {
         noop_fold_view_item(vi, self)
     }
 
-    fn fold_foreign_item(&mut self, ni: @ForeignItem) -> @ForeignItem {
-        noop_fold_foreign_item(ni, self)
+    fn fold_foreign_item(&mut self, ni: Gc<ForeignItem>) -> Gc<ForeignItem> {
+        noop_fold_foreign_item(&*ni, self)
     }
 
-    fn fold_item(&mut self, i: @Item) -> SmallVector<@Item> {
-        noop_fold_item(i, self)
+    fn fold_item(&mut self, i: Gc<Item>) -> SmallVector<Gc<Item>> {
+        noop_fold_item(&*i, self)
     }
 
     fn fold_struct_field(&mut self, sf: &StructField) -> StructField {
@@ -103,15 +104,15 @@ pub trait Folder {
         noop_fold_type_method(m, self)
     }
 
-    fn fold_method(&mut self, m: @Method) -> @Method {
-        noop_fold_method(m, self)
+    fn fold_method(&mut self, m: Gc<Method>) -> Gc<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<@Stmt> {
+    fn fold_stmt(&mut self, s: &Stmt) -> SmallVector<Gc<Stmt>> {
         noop_fold_stmt(s, self)
     }
 
@@ -124,11 +125,11 @@ pub trait Folder {
         }
     }
 
-    fn fold_pat(&mut self, p: @Pat) -> @Pat {
+    fn fold_pat(&mut self, p: Gc<Pat>) -> Gc<Pat> {
         noop_fold_pat(p, self)
     }
 
-    fn fold_decl(&mut self, d: @Decl) -> SmallVector<@Decl> {
+    fn fold_decl(&mut self, d: Gc<Decl>) -> SmallVector<Gc<Decl>> {
         let node = match d.node {
             DeclLocal(ref l) => SmallVector::one(DeclLocal(self.fold_local(*l))),
             DeclItem(it) => {
@@ -137,14 +138,14 @@ pub trait Folder {
         };
 
         node.move_iter().map(|node| {
-            @Spanned {
+            box(GC) Spanned {
                 node: node,
                 span: self.new_span(d.span),
             }
         }).collect()
     }
 
-    fn fold_expr(&mut self, e: @Expr) -> @Expr {
+    fn fold_expr(&mut self, e: Gc<Expr>) -> Gc<Expr> {
         noop_fold_expr(e, self)
     }
 
@@ -160,29 +161,29 @@ pub trait Folder {
                 TyRptr(fold_opt_lifetime(region, self), fold_mt(mt, self))
             }
             TyClosure(ref f, ref region) => {
-                TyClosure(@ClosureTy {
+                TyClosure(box(GC) ClosureTy {
                     fn_style: f.fn_style,
                     onceness: f.onceness,
                     bounds: fold_opt_bounds(&f.bounds, self),
-                    decl: self.fold_fn_decl(f.decl),
+                    decl: self.fold_fn_decl(&*f.decl),
                     lifetimes: f.lifetimes.iter().map(|l| self.fold_lifetime(l)).collect(),
                 }, fold_opt_lifetime(region, self))
             }
             TyProc(ref f) => {
-                TyProc(@ClosureTy {
+                TyProc(box(GC) ClosureTy {
                     fn_style: f.fn_style,
                     onceness: f.onceness,
                     bounds: fold_opt_bounds(&f.bounds, self),
-                    decl: self.fold_fn_decl(f.decl),
+                    decl: self.fold_fn_decl(&*f.decl),
                     lifetimes: f.lifetimes.iter().map(|l| self.fold_lifetime(l)).collect(),
                 })
             }
             TyBareFn(ref f) => {
-                TyBareFn(@BareFnTy {
+                TyBareFn(box(GC) BareFnTy {
                     lifetimes: f.lifetimes.iter().map(|l| self.fold_lifetime(l)).collect(),
                     fn_style: f.fn_style,
                     abi: f.abi,
-                    decl: self.fold_fn_decl(f.decl)
+                    decl: self.fold_fn_decl(&*f.decl)
                 })
             }
             TyUnboxedFn(ref f) => {
@@ -236,7 +237,7 @@ pub trait Folder {
                     fold_variant_arg_(x, self)).collect())
             }
             StructVariantKind(ref struct_def) => {
-                kind = StructVariantKind(@ast::StructDef {
+                kind = StructVariantKind(box(GC) ast::StructDef {
                     fields: struct_def.fields.iter()
                         .map(|f| self.fold_struct_field(f)).collect(),
                     ctor_id: struct_def.ctor_id.map(|c| self.new_id(c)),
@@ -285,9 +286,9 @@ pub trait Folder {
         }
     }
 
-    fn fold_local(&mut self, l: @Local) -> @Local {
+    fn fold_local(&mut self, l: Gc<Local>) -> Gc<Local> {
         let id = self.new_id(l.id); // Needs to be first, for ast_map.
-        @Local {
+        box(GC) Local {
             id: id,
             ty: self.fold_ty(l.ty),
             pat: self.fold_pat(l.pat),
@@ -310,7 +311,8 @@ pub trait Folder {
         }
     }
 
-    fn map_exprs(&self, f: |@Expr| -> @Expr, es: &[@Expr]) -> Vec<@Expr> {
+    fn map_exprs(&self, f: |Gc<Expr>| -> Gc<Expr>,
+                 es: &[Gc<Expr>]) -> Vec<Gc<Expr>> {
         es.iter().map(|x| f(*x)).collect()
     }
 
@@ -346,8 +348,8 @@ pub trait Folder {
 /* some little folds that probably aren't useful to have in Folder itself*/
 
 //used in noop_fold_item and noop_fold_crate and noop_fold_crate_directive
-fn fold_meta_item_<T: Folder>(mi: @MetaItem, fld: &mut T) -> @MetaItem {
-    @Spanned {
+fn fold_meta_item_<T: Folder>(mi: Gc<MetaItem>, fld: &mut T) -> Gc<MetaItem> {
+    box(GC) Spanned {
         node:
             match mi.node {
                 MetaWord(ref id) => MetaWord((*id).clone()),
@@ -495,8 +497,9 @@ pub fn fold_generics<T: Folder>(generics: &Generics, fld: &mut T) -> Generics {
               lifetimes: fold_lifetimes(&generics.lifetimes, fld)}
 }
 
-fn fold_struct_def<T: Folder>(struct_def: @StructDef, fld: &mut T) -> @StructDef {
-    @ast::StructDef {
+fn 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| fold_struct_field(f, fld)).collect(),
         ctor_id: struct_def.ctor_id.map(|cid| fld.new_id(cid)),
         super_struct: match struct_def.super_struct {
@@ -583,7 +586,7 @@ pub fn noop_fold_view_item<T: Folder>(vi: &ViewItem, folder: &mut T)
 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();
+    let stmts = b.stmts.iter().flat_map(|s| folder.fold_stmt(&**s).move_iter()).collect();
     P(Block {
         id: id,
         view_items: view_items,
@@ -601,7 +604,7 @@ pub fn noop_fold_item_underscore<T: Folder>(i: &Item_, folder: &mut T) -> Item_
         }
         ItemFn(decl, fn_style, abi, ref generics, body) => {
             ItemFn(
-                folder.fold_fn_decl(decl),
+                folder.fold_fn_decl(&*decl),
                 fn_style,
                 abi,
                 fold_generics(generics, folder),
@@ -617,7 +620,7 @@ pub fn noop_fold_item_underscore<T: Folder>(i: &Item_, folder: &mut T) -> Item_
             ItemEnum(
                 ast::EnumDef {
                     variants: enum_definition.variants.iter().map(|&x| {
-                        folder.fold_variant(x)
+                        folder.fold_variant(&*x)
                     }).collect(),
                 },
                 fold_generics(generics, folder))
@@ -656,7 +659,7 @@ pub fn noop_fold_type_method<T: Folder>(m: &TypeMethod, fld: &mut T) -> TypeMeth
         ident: fld.fold_ident(m.ident),
         attrs: m.attrs.iter().map(|a| fold_attribute_(*a, fld)).collect(),
         fn_style: m.fn_style,
-        decl: fld.fold_fn_decl(m.decl),
+        decl: fld.fold_fn_decl(&*m.decl),
         generics: fold_generics(&m.generics, fld),
         explicit_self: fld.fold_explicit_self(&m.explicit_self),
         span: fld.new_span(m.span),
@@ -683,18 +686,19 @@ pub fn noop_fold_crate<T: Folder>(c: Crate, folder: &mut T) -> Crate {
     }
 }
 
-pub fn noop_fold_item<T: Folder>(i: &Item, folder: &mut T) -> SmallVector<@Item> {
+pub fn noop_fold_item<T: Folder>(i: &Item,
+                                 folder: &mut T) -> SmallVector<Gc<Item>> {
     let id = folder.new_id(i.id); // Needs to be first, for ast_map.
     let node = folder.fold_item_underscore(&i.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)
+            ast_util::impl_pretty_name(maybe_trait, &*ty)
         }
         _ => i.ident
     };
 
-    SmallVector::one(@Item {
+    SmallVector::one(box(GC) Item {
         id: id,
         ident: folder.fold_ident(ident),
         attrs: i.attrs.iter().map(|e| fold_attribute_(*e, folder)).collect(),
@@ -704,9 +708,10 @@ pub fn noop_fold_item<T: Folder>(i: &Item, folder: &mut T) -> SmallVector<@Item>
     })
 }
 
-pub fn noop_fold_foreign_item<T: Folder>(ni: &ForeignItem, folder: &mut T) -> @ForeignItem {
+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.
-    @ForeignItem {
+    box(GC) ForeignItem {
         id: id,
         ident: folder.fold_ident(ni.ident),
         attrs: ni.attrs.iter().map(|x| fold_attribute_(*x, folder)).collect(),
@@ -728,23 +733,23 @@ pub fn noop_fold_foreign_item<T: Folder>(ni: &ForeignItem, folder: &mut T) -> @F
     }
 }
 
-pub fn noop_fold_method<T: Folder>(m: &Method, folder: &mut T) -> @Method {
+pub fn noop_fold_method<T: Folder>(m: &Method, folder: &mut T) -> Gc<Method> {
     let id = folder.new_id(m.id); // Needs to be first, for ast_map.
-    @Method {
+    box(GC) Method {
         id: id,
         ident: folder.fold_ident(m.ident),
         attrs: m.attrs.iter().map(|a| fold_attribute_(*a, folder)).collect(),
         generics: fold_generics(&m.generics, folder),
         explicit_self: folder.fold_explicit_self(&m.explicit_self),
         fn_style: m.fn_style,
-        decl: folder.fold_fn_decl(m.decl),
+        decl: folder.fold_fn_decl(&*m.decl),
         body: folder.fold_block(m.body),
         span: folder.new_span(m.span),
         vis: m.vis
     }
 }
 
-pub fn noop_fold_pat<T: Folder>(p: @Pat, folder: &mut T) -> @Pat {
+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 => PatWild,
@@ -783,14 +788,14 @@ pub fn noop_fold_pat<T: Folder>(p: @Pat, folder: &mut T) -> @Pat {
         PatMac(ref mac) => PatMac(folder.fold_mac(mac)),
     };
 
-    @Pat {
+    box(GC) Pat {
         id: id,
         span: folder.new_span(p.span),
         node: node,
     }
 }
 
-pub fn noop_fold_expr<T: Folder>(e: @Expr, folder: &mut T) -> @Expr {
+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 {
         ExprVstore(e, v) => {
@@ -851,13 +856,15 @@ pub fn noop_fold_expr<T: Folder>(e: @Expr, folder: &mut T) -> @Expr {
             ExprMatch(folder.fold_expr(expr),
                       arms.iter().map(|x| folder.fold_arm(x)).collect())
         }
-        ExprFnBlock(decl, body) => {
-            ExprFnBlock(folder.fold_fn_decl(decl), folder.fold_block(body))
+        ExprFnBlock(ref decl, ref body) => {
+            ExprFnBlock(folder.fold_fn_decl(&**decl),
+                        folder.fold_block(body.clone()))
         }
-        ExprProc(decl, body) => {
-            ExprProc(folder.fold_fn_decl(decl), folder.fold_block(body))
+        ExprProc(ref decl, ref body) => {
+            ExprProc(folder.fold_fn_decl(&**decl),
+                     folder.fold_block(body.clone()))
         }
-        ExprBlock(blk) => ExprBlock(folder.fold_block(blk)),
+        ExprBlock(ref blk) => ExprBlock(folder.fold_block(blk.clone())),
         ExprAssign(el, er) => {
             ExprAssign(folder.fold_expr(el), folder.fold_expr(er))
         }
@@ -900,14 +907,15 @@ pub fn noop_fold_expr<T: Folder>(e: @Expr, folder: &mut T) -> @Expr {
         ExprParen(ex) => ExprParen(folder.fold_expr(ex))
     };
 
-    @Expr {
+    box(GC) Expr {
         id: id,
         node: node,
         span: folder.new_span(e.span),
     }
 }
 
-pub fn noop_fold_stmt<T: Folder>(s: &Stmt, folder: &mut T) -> SmallVector<@Stmt> {
+pub fn noop_fold_stmt<T: Folder>(s: &Stmt,
+                                 folder: &mut T) -> SmallVector<Gc<Stmt>> {
     let nodes = match s.node {
         StmtDecl(d, id) => {
             let id = folder.new_id(id);
@@ -926,7 +934,7 @@ pub fn noop_fold_stmt<T: Folder>(s: &Stmt, folder: &mut T) -> SmallVector<@Stmt>
         StmtMac(ref mac, semi) => SmallVector::one(StmtMac(folder.fold_mac(mac), semi))
     };
 
-    nodes.move_iter().map(|node| @Spanned {
+    nodes.move_iter().map(|node| box(GC) Spanned {
         node: node,
         span: folder.new_span(s.span),
     }).collect()
diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs
index 52e3693c31f..64766b5013c 100644
--- a/src/libsyntax/parse/attr.rs
+++ b/src/libsyntax/parse/attr.rs
@@ -16,15 +16,17 @@ use parse::token;
 use parse::parser::Parser;
 use parse::token::INTERPOLATED;
 
+use std::gc::Gc;
+
 // a parser that can parse attributes.
 pub trait ParserAttr {
-    fn parse_outer_attributes(&mut self) -> Vec<ast::Attribute> ;
+    fn parse_outer_attributes(&mut self) -> Vec<ast::Attribute>;
     fn parse_attribute(&mut self, permit_inner: bool) -> ast::Attribute;
     fn parse_inner_attrs_and_next(&mut self)
-                                  -> (Vec<ast::Attribute> , Vec<ast::Attribute> );
-    fn parse_meta_item(&mut self) -> @ast::MetaItem;
-    fn parse_meta_seq(&mut self) -> Vec<@ast::MetaItem> ;
-    fn parse_optional_meta(&mut self) -> Vec<@ast::MetaItem> ;
+                                  -> (Vec<ast::Attribute>, Vec<ast::Attribute>);
+    fn parse_meta_item(&mut self) -> Gc<ast::MetaItem>;
+    fn parse_meta_seq(&mut self) -> Vec<Gc<ast::MetaItem>>;
+    fn parse_optional_meta(&mut self) -> Vec<Gc<ast::MetaItem>>;
 }
 
 impl<'a> ParserAttr for Parser<'a> {
@@ -157,7 +159,7 @@ impl<'a> ParserAttr for Parser<'a> {
     // matches meta_item = IDENT
     // | IDENT = lit
     // | IDENT meta_seq
-    fn parse_meta_item(&mut self) -> @ast::MetaItem {
+    fn parse_meta_item(&mut self) -> Gc<ast::MetaItem> {
         match self.token {
             token::INTERPOLATED(token::NtMeta(e)) => {
                 self.bump();
@@ -184,29 +186,29 @@ impl<'a> ParserAttr for Parser<'a> {
                     }
                 }
                 let hi = self.span.hi;
-                @spanned(lo, hi, ast::MetaNameValue(name, lit))
+                box(GC) spanned(lo, hi, ast::MetaNameValue(name, lit))
             }
             token::LPAREN => {
                 let inner_items = self.parse_meta_seq();
                 let hi = self.span.hi;
-                @spanned(lo, hi, ast::MetaList(name, inner_items))
+                box(GC) spanned(lo, hi, ast::MetaList(name, inner_items))
             }
             _ => {
                 let hi = self.last_span.hi;
-                @spanned(lo, hi, ast::MetaWord(name))
+                box(GC) spanned(lo, hi, ast::MetaWord(name))
             }
         }
     }
 
     // matches meta_seq = ( COMMASEP(meta_item) )
-    fn parse_meta_seq(&mut self) -> Vec<@ast::MetaItem> {
+    fn parse_meta_seq(&mut self) -> Vec<Gc<ast::MetaItem>> {
         self.parse_seq(&token::LPAREN,
                        &token::RPAREN,
                        seq_sep_trailing_disallowed(token::COMMA),
                        |p| p.parse_meta_item()).node
     }
 
-    fn parse_optional_meta(&mut self) -> Vec<@ast::MetaItem> {
+    fn parse_optional_meta(&mut self) -> Vec<Gc<ast::MetaItem>> {
         match self.token {
             token::LPAREN => self.parse_meta_seq(),
             _ => Vec::new()
diff --git a/src/libsyntax/parse/classify.rs b/src/libsyntax/parse/classify.rs
index b160593b049..8d9cc305c26 100644
--- a/src/libsyntax/parse/classify.rs
+++ b/src/libsyntax/parse/classify.rs
@@ -13,6 +13,7 @@
 // Predicates on exprs and stmts that the pretty-printer and parser use
 
 use ast;
+use std::gc::Gc;
 
 // does this expression require a semicolon to be treated
 // as a statement? The negation of this: 'can this expression
@@ -21,7 +22,7 @@ use ast;
 // 'if true {...} else {...}
 //  |x| 5 '
 // isn't parsed as (if true {...} else {...} | x) | 5
-pub fn expr_requires_semi_to_be_stmt(e: @ast::Expr) -> bool {
+pub fn expr_requires_semi_to_be_stmt(e: Gc<ast::Expr>) -> bool {
     match e.node {
         ast::ExprIf(..)
         | ast::ExprMatch(..)
@@ -33,7 +34,7 @@ pub fn expr_requires_semi_to_be_stmt(e: @ast::Expr) -> bool {
     }
 }
 
-pub fn expr_is_simple_block(e: @ast::Expr) -> bool {
+pub fn expr_is_simple_block(e: Gc<ast::Expr>) -> bool {
     match e.node {
         ast::ExprBlock(block) => block.rules == ast::DefaultBlock,
       _ => false
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 2231b7a78e1..88746d145b6 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -18,6 +18,7 @@ use parse::attr::ParserAttr;
 use parse::parser::Parser;
 
 use std::cell::RefCell;
+use std::gc::Gc;
 use std::io::File;
 use std::rc::Rc;
 use std::str;
@@ -105,7 +106,7 @@ pub fn parse_expr_from_source_str(name: String,
                                   source: String,
                                   cfg: ast::CrateConfig,
                                   sess: &ParseSess)
-                                  -> @ast::Expr {
+                                  -> Gc<ast::Expr> {
     let mut p = new_parser_from_source_str(sess, cfg, name, source);
     maybe_aborted(p.parse_expr(), p)
 }
@@ -114,7 +115,7 @@ pub fn parse_item_from_source_str(name: String,
                                   source: String,
                                   cfg: ast::CrateConfig,
                                   sess: &ParseSess)
-                                  -> Option<@ast::Item> {
+                                  -> Option<Gc<ast::Item>> {
     let mut p = new_parser_from_source_str(sess, cfg, name, source);
     let attrs = p.parse_outer_attributes();
     maybe_aborted(p.parse_item(attrs),p)
@@ -124,7 +125,7 @@ pub fn parse_meta_from_source_str(name: String,
                                   source: String,
                                   cfg: ast::CrateConfig,
                                   sess: &ParseSess)
-                                  -> @ast::MetaItem {
+                                  -> Gc<ast::MetaItem> {
     let mut p = new_parser_from_source_str(sess, cfg, name, source);
     maybe_aborted(p.parse_meta_item(),p)
 }
@@ -134,7 +135,7 @@ pub fn parse_stmt_from_source_str(name: String,
                                   cfg: ast::CrateConfig,
                                   attrs: Vec<ast::Attribute> ,
                                   sess: &ParseSess)
-                                  -> @ast::Stmt {
+                                  -> Gc<ast::Stmt> {
     let mut p = new_parser_from_source_str(
         sess,
         cfg,
@@ -306,7 +307,7 @@ mod test {
 
     #[test] fn path_exprs_1() {
         assert!(string_to_expr("a".to_string()) ==
-                   @ast::Expr{
+                   box(GC) ast::Expr{
                     id: ast::DUMMY_NODE_ID,
                     node: ast::ExprPath(ast::Path {
                         span: sp(0, 1),
@@ -325,7 +326,7 @@ mod test {
 
     #[test] fn path_exprs_2 () {
         assert!(string_to_expr("::a::b".to_string()) ==
-                   @ast::Expr {
+                   box(GC) ast::Expr {
                     id: ast::DUMMY_NODE_ID,
                     node: ast::ExprPath(ast::Path {
                             span: sp(0, 6),
@@ -537,9 +538,9 @@ mod test {
 
     #[test] fn ret_expr() {
         assert!(string_to_expr("return d".to_string()) ==
-                   @ast::Expr{
+                   box(GC) ast::Expr{
                     id: ast::DUMMY_NODE_ID,
-                    node:ast::ExprRet(Some(@ast::Expr{
+                    node:ast::ExprRet(Some(box(GC) ast::Expr{
                         id: ast::DUMMY_NODE_ID,
                         node:ast::ExprPath(ast::Path{
                             span: sp(7, 8),
@@ -560,8 +561,8 @@ mod test {
 
     #[test] fn parse_stmt_1 () {
         assert!(string_to_stmt("b;".to_string()) ==
-                   @Spanned{
-                       node: ast::StmtExpr(@ast::Expr {
+                   box(GC) Spanned{
+                       node: ast::StmtExpr(box(GC) ast::Expr {
                            id: ast::DUMMY_NODE_ID,
                            node: ast::ExprPath(ast::Path {
                                span:sp(0,1),
@@ -588,7 +589,7 @@ mod test {
         let sess = new_parse_sess();
         let mut parser = string_to_parser(&sess, "b".to_string());
         assert!(parser.parse_pat() ==
-                   @ast::Pat{id: ast::DUMMY_NODE_ID,
+                   box(GC) ast::Pat{id: ast::DUMMY_NODE_ID,
                              node: ast::PatIdent(
                                 ast::BindByValue(ast::MutImmutable),
                                 ast::Path {
@@ -612,7 +613,7 @@ mod test {
         // this test depends on the intern order of "fn" and "int"
         assert!(string_to_item("fn a (b : int) { b; }".to_string()) ==
                   Some(
-                      @ast::Item{ident:str_to_ident("a"),
+                      box(GC) ast::Item{ident:str_to_ident("a"),
                             attrs:Vec::new(),
                             id: ast::DUMMY_NODE_ID,
                             node: ast::ItemFn(ast::P(ast::FnDecl {
@@ -632,7 +633,7 @@ mod test {
                                         }, None, ast::DUMMY_NODE_ID),
                                         span:sp(10,13)
                                     }),
-                                    pat: @ast::Pat {
+                                    pat: box(GC) ast::Pat {
                                         id: ast::DUMMY_NODE_ID,
                                         node: ast::PatIdent(
                                             ast::BindByValue(ast::MutImmutable),
@@ -668,8 +669,8 @@ mod test {
                                     },
                                     ast::P(ast::Block {
                                         view_items: Vec::new(),
-                                        stmts: vec!(@Spanned{
-                                            node: ast::StmtSemi(@ast::Expr{
+                                        stmts: vec!(box(GC) Spanned{
+                                            node: ast::StmtSemi(box(GC) ast::Expr{
                                                 id: ast::DUMMY_NODE_ID,
                                                 node: ast::ExprPath(
                                                       ast::Path{
@@ -703,12 +704,12 @@ mod test {
     #[test] fn parse_exprs () {
         // just make sure that they parse....
         string_to_expr("3 + 4".to_string());
-        string_to_expr("a::z.froob(b,@(987+3))".to_string());
+        string_to_expr("a::z.froob(b,box(GC)(987+3))".to_string());
     }
 
     #[test] fn attrs_fix_bug () {
         string_to_item("pub fn mk_file_writer(path: &Path, flags: &[FileFlag])
-                   -> Result<@Writer, String> {
+                   -> Result<Gc<Writer>, String> {
     #[cfg(windows)]
     fn wb() -> c_int {
       (O_WRONLY | libc::consts::os::extra::O_BINARY) as c_int
diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs
index bba400742b5..9706176ca8b 100644
--- a/src/libsyntax/parse/obsolete.rs
+++ b/src/libsyntax/parse/obsolete.rs
@@ -22,6 +22,8 @@ use codemap::{Span, respan};
 use parse::parser;
 use parse::token;
 
+use std::gc::Gc;
+
 /// The specific types of unsupported syntax
 #[deriving(PartialEq, Eq, Hash)]
 pub enum ObsoleteSyntax {
@@ -35,7 +37,7 @@ pub trait ParserObsoleteMethods {
     fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax);
     // Reports an obsolete syntax non-fatal error, and returns
     // a placeholder expression
-    fn obsolete_expr(&mut self, sp: Span, kind: ObsoleteSyntax) -> @Expr;
+    fn obsolete_expr(&mut self, sp: Span, kind: ObsoleteSyntax) -> Gc<Expr>;
     fn report(&mut self,
               sp: Span,
               kind: ObsoleteSyntax,
@@ -68,9 +70,9 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> {
 
     // Reports an obsolete syntax non-fatal error, and returns
     // a placeholder expression
-    fn obsolete_expr(&mut self, sp: Span, kind: ObsoleteSyntax) -> @Expr {
+    fn obsolete_expr(&mut self, sp: Span, kind: ObsoleteSyntax) -> Gc<Expr> {
         self.obsolete(sp, kind);
-        self.mk_expr(sp.lo, sp.hi, ExprLit(@respan(sp, LitNil)))
+        self.mk_expr(sp.lo, sp.hi, ExprLit(box(GC) respan(sp, LitNil)))
     }
 
     fn report(&mut self,
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index de5f533a96e..fad75ef9278 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -79,7 +79,7 @@ use owned_slice::OwnedSlice;
 use std::collections::HashSet;
 use std::mem::replace;
 use std::rc::Rc;
-use std::string::String;
+use std::gc::Gc;
 
 #[allow(non_camel_case_types)]
 #[deriving(PartialEq)]
@@ -119,9 +119,9 @@ pub struct PathAndBounds {
 enum ItemOrViewItem {
     // Indicates a failure to parse any kind of item. The attributes are
     // returned.
-    IoviNone(Vec<Attribute> ),
-    IoviItem(@Item),
-    IoviForeignItem(@ForeignItem),
+    IoviNone(Vec<Attribute>),
+    IoviItem(Gc<Item>),
+    IoviForeignItem(Gc<ForeignItem>),
     IoviViewItem(ViewItem)
 }
 
@@ -275,9 +275,9 @@ fn maybe_append(lhs: Vec<Attribute> , rhs: Option<Vec<Attribute> >)
 
 
 struct ParsedItemsAndViewItems {
-    attrs_remaining: Vec<Attribute> ,
-    view_items: Vec<ViewItem> ,
-    items: Vec<@Item> ,
+    attrs_remaining: Vec<Attribute>,
+    view_items: Vec<ViewItem>,
+    items: Vec<@Item>,
     foreign_items: Vec<@ForeignItem>
 }
 
@@ -454,7 +454,8 @@ impl<'a> Parser<'a> {
     // Commit to parsing a complete expression `e` expected to be
     // followed by some token from the set edible + inedible.  Recover
     // from anticipated input errors, discarding erroneous characters.
-    pub fn commit_expr(&mut self, e: @Expr, edible: &[token::Token], inedible: &[token::Token]) {
+    pub fn commit_expr(&mut self, e: Gc<Expr>, edible: &[token::Token],
+                       inedible: &[token::Token]) {
         debug!("commit_expr {:?}", e);
         match e.node {
             ExprPath(..) => {
@@ -469,14 +470,15 @@ impl<'a> Parser<'a> {
         self.expect_one_of(edible, inedible)
     }
 
-    pub fn commit_expr_expecting(&mut self, e: @Expr, edible: token::Token) {
+    pub fn commit_expr_expecting(&mut self, e: Gc<Expr>, edible: token::Token) {
         self.commit_expr(e, &[edible], &[])
     }
 
     // Commit to parsing a complete statement `s`, which expects to be
     // followed by some token from the set edible + inedible.  Check
     // for recoverable input errors, discarding erroneous characters.
-    pub fn commit_stmt(&mut self, s: @Stmt, edible: &[token::Token], inedible: &[token::Token]) {
+    pub fn commit_stmt(&mut self, s: Gc<Stmt>, edible: &[token::Token],
+                       inedible: &[token::Token]) {
         debug!("commit_stmt {:?}", s);
         let _s = s; // unused, but future checks might want to inspect `s`.
         if self.last_token.as_ref().map_or(false, |t| is_ident_or_path(*t)) {
@@ -488,7 +490,7 @@ impl<'a> Parser<'a> {
         self.expect_one_of(edible, inedible)
     }
 
-    pub fn commit_stmt_expecting(&mut self, s: @Stmt, edible: token::Token) {
+    pub fn commit_stmt_expecting(&mut self, s: Gc<Stmt>, edible: token::Token) {
         self.commit_stmt(s, &[edible], &[])
     }
 
@@ -980,7 +982,7 @@ impl<'a> Parser<'a> {
 
         self.expect_keyword(keywords::Fn);
         let (decl, lifetimes) = self.parse_ty_fn_decl(true);
-        return TyBareFn(@BareFnTy {
+        return TyBareFn(box(GC) BareFnTy {
             abi: abi,
             fn_style: fn_style,
             lifetimes: lifetimes,
@@ -1021,7 +1023,7 @@ impl<'a> Parser<'a> {
             cf: ret_style,
             variadic: variadic
         });
-        TyProc(@ClosureTy {
+        TyProc(box(GC) ClosureTy {
             fn_style: NormalFn,
             onceness: Once,
             bounds: bounds,
@@ -1092,11 +1094,11 @@ impl<'a> Parser<'a> {
         });
 
         if is_unboxed {
-            TyUnboxedFn(@UnboxedFnTy {
+            TyUnboxedFn(box(GC) UnboxedFnTy {
                 decl: decl,
             })
         } else {
-            TyClosure(@ClosureTy {
+            TyClosure(box(GC) ClosureTy {
                 fn_style: fn_style,
                 onceness: onceness,
                 bounds: bounds,
@@ -1192,7 +1194,7 @@ impl<'a> Parser<'a> {
                 let (inner_attrs, body) =
                     p.parse_inner_attrs_and_block();
                 let attrs = attrs.append(inner_attrs.as_slice());
-                Provided(@ast::Method {
+                Provided(box(GC) ast::Method {
                     ident: ident,
                     attrs: attrs,
                     generics: generics,
@@ -1465,7 +1467,7 @@ impl<'a> Parser<'a> {
         }
     }
 
-    pub fn maybe_parse_fixed_vstore(&mut self) -> Option<@ast::Expr> {
+    pub fn maybe_parse_fixed_vstore(&mut self) -> Option<Gc<ast::Expr>> {
         if self.token == token::COMMA &&
                 self.look_ahead(1, |t| *t == token::DOTDOT) {
             self.bump();
@@ -1516,12 +1518,12 @@ impl<'a> Parser<'a> {
     }
 
     // matches '-' lit | lit
-    pub fn parse_literal_maybe_minus(&mut self) -> @Expr {
+    pub fn parse_literal_maybe_minus(&mut self) -> Gc<Expr> {
         let minus_lo = self.span.lo;
         let minus_present = self.eat(&token::BINOP(token::MINUS));
 
         let lo = self.span.lo;
-        let literal = @self.parse_lit();
+        let literal = box(GC) self.parse_lit();
         let hi = self.span.hi;
         let expr = self.mk_expr(lo, hi, ExprLit(literal));
 
@@ -1723,62 +1725,65 @@ impl<'a> Parser<'a> {
         }
     }
 
-    pub fn mk_expr(&mut self, lo: BytePos, hi: BytePos, node: Expr_) -> @Expr {
-        @Expr {
+    pub fn mk_expr(&mut self, lo: BytePos, hi: BytePos, node: Expr_) -> Gc<Expr> {
+        box(GC) Expr {
             id: ast::DUMMY_NODE_ID,
             node: node,
             span: mk_sp(lo, hi),
         }
     }
 
-    pub fn mk_unary(&mut self, unop: ast::UnOp, expr: @Expr) -> ast::Expr_ {
+    pub fn mk_unary(&mut self, unop: ast::UnOp, expr: Gc<Expr>) -> ast::Expr_ {
         ExprUnary(unop, expr)
     }
 
-    pub fn mk_binary(&mut self, binop: ast::BinOp, lhs: @Expr, rhs: @Expr) -> ast::Expr_ {
+    pub fn mk_binary(&mut self, binop: ast::BinOp,
+                     lhs: Gc<Expr>, rhs: Gc<Expr>) -> ast::Expr_ {
         ExprBinary(binop, lhs, rhs)
     }
 
-    pub fn mk_call(&mut self, f: @Expr, args: Vec<@Expr> ) -> ast::Expr_ {
+    pub fn mk_call(&mut self, f: Gc<Expr>, args: Vec<Gc<Expr>>) -> ast::Expr_ {
         ExprCall(f, args)
     }
 
     fn mk_method_call(&mut self,
                       ident: ast::SpannedIdent,
                       tps: Vec<P<Ty>>,
-                      args: Vec<@Expr>)
+                      args: Vec<Gc<Expr>>)
                       -> ast::Expr_ {
         ExprMethodCall(ident, tps, args)
     }
 
-    pub fn mk_index(&mut self, expr: @Expr, idx: @Expr) -> ast::Expr_ {
+    pub fn mk_index(&mut self, expr: Gc<Expr>, idx: Gc<Expr>) -> ast::Expr_ {
         ExprIndex(expr, idx)
     }
 
-    pub fn mk_field(&mut self, expr: @Expr, ident: Ident, tys: Vec<P<Ty>> ) -> ast::Expr_ {
+    pub fn mk_field(&mut self, expr: Gc<Expr>, ident: Ident,
+                    tys: Vec<P<Ty>>) -> ast::Expr_ {
         ExprField(expr, ident, tys)
     }
 
-    pub fn mk_assign_op(&mut self, binop: ast::BinOp, lhs: @Expr, rhs: @Expr) -> ast::Expr_ {
+    pub fn mk_assign_op(&mut self, binop: ast::BinOp,
+                        lhs: Gc<Expr>, rhs: Gc<Expr>) -> ast::Expr_ {
         ExprAssignOp(binop, lhs, rhs)
     }
 
-    pub fn mk_mac_expr(&mut self, lo: BytePos, hi: BytePos, m: Mac_) -> @Expr {
-        @Expr {
+    pub fn mk_mac_expr(&mut self, lo: BytePos, hi: BytePos, m: Mac_) -> Gc<Expr> {
+        box(GC) Expr {
             id: ast::DUMMY_NODE_ID,
             node: ExprMac(codemap::Spanned {node: m, span: mk_sp(lo, hi)}),
             span: mk_sp(lo, hi),
         }
     }
 
-    pub fn mk_lit_u32(&mut self, i: u32) -> @Expr {
+    pub fn mk_lit_u32(&mut self, i: u32) -> Gc<Expr> {
         let span = &self.span;
-        let lv_lit = @codemap::Spanned {
+        let lv_lit = box(GC) codemap::Spanned {
             node: LitUint(i as u64, TyU32),
             span: *span
         };
 
-        @Expr {
+        box(GC) Expr {
             id: ast::DUMMY_NODE_ID,
             node: ExprLit(lv_lit),
             span: *span,
@@ -1788,7 +1793,7 @@ impl<'a> Parser<'a> {
     // at the bottom (top?) of the precedence hierarchy,
     // parse things like parenthesized exprs,
     // macros, return, etc.
-    pub fn parse_bottom_expr(&mut self) -> @Expr {
+    pub fn parse_bottom_expr(&mut self) -> Gc<Expr> {
         maybe_whole_expr!(self);
 
         let lo = self.span.lo;
@@ -1804,7 +1809,7 @@ impl<'a> Parser<'a> {
             if self.token == token::RPAREN {
                 hi = self.span.hi;
                 self.bump();
-                let lit = @spanned(lo, hi, LitNil);
+                let lit = box(GC) spanned(lo, hi, LitNil);
                 return self.mk_expr(lo, hi, ExprLit(lit));
             }
             let mut es = vec!(self.parse_expr());
@@ -1991,7 +1996,7 @@ impl<'a> Parser<'a> {
             // other literal expression
             let lit = self.parse_lit();
             hi = lit.span.hi;
-            ex = ExprLit(@lit);
+            ex = ExprLit(box(GC) lit);
         }
 
         return self.mk_expr(lo, hi, ex);
@@ -1999,19 +2004,19 @@ impl<'a> Parser<'a> {
 
     // parse a block or unsafe block
     pub fn parse_block_expr(&mut self, lo: BytePos, blk_mode: BlockCheckMode)
-                            -> @Expr {
+                            -> Gc<Expr> {
         self.expect(&token::LBRACE);
         let blk = self.parse_block_tail(lo, blk_mode);
         return self.mk_expr(blk.span.lo, blk.span.hi, ExprBlock(blk));
     }
 
     // parse a.b or a(13) or a[4] or just a
-    pub fn parse_dot_or_call_expr(&mut self) -> @Expr {
+    pub fn parse_dot_or_call_expr(&mut self) -> Gc<Expr> {
         let b = self.parse_bottom_expr();
         self.parse_dot_or_call_expr_with(b)
     }
 
-    pub fn parse_dot_or_call_expr_with(&mut self, e0: @Expr) -> @Expr {
+    pub fn parse_dot_or_call_expr_with(&mut self, e0: Gc<Expr>) -> Gc<Expr> {
         let mut e = e0;
         let lo = e.span.lo;
         let mut hi;
@@ -2282,7 +2287,7 @@ impl<'a> Parser<'a> {
     }
 
     // parse a prefix-operator expr
-    pub fn parse_prefix_expr(&mut self) -> @Expr {
+    pub fn parse_prefix_expr(&mut self) -> Gc<Expr> {
         let lo = self.span.lo;
         let hi;
 
@@ -2384,13 +2389,14 @@ impl<'a> Parser<'a> {
     }
 
     // parse an expression of binops
-    pub fn parse_binops(&mut self) -> @Expr {
+    pub fn parse_binops(&mut self) -> Gc<Expr> {
         let prefix_expr = self.parse_prefix_expr();
         self.parse_more_binops(prefix_expr, 0)
     }
 
     // parse an expression of binops of at least min_prec precedence
-    pub fn parse_more_binops(&mut self, lhs: @Expr, min_prec: uint) -> @Expr {
+    pub fn parse_more_binops(&mut self, lhs: Gc<Expr>,
+                             min_prec: uint) -> Gc<Expr> {
         if self.expr_is_complete(lhs) { return lhs; }
 
         // Prevent dynamic borrow errors later on by limiting the
@@ -2439,7 +2445,7 @@ impl<'a> Parser<'a> {
     // parse an assignment expression....
     // actually, this seems to be the main entry point for
     // parsing an arbitrary expression.
-    pub fn parse_assign_expr(&mut self) -> @Expr {
+    pub fn parse_assign_expr(&mut self) -> Gc<Expr> {
         let lo = self.span.lo;
         let lhs = self.parse_binops();
         match self.token {
@@ -2473,11 +2479,11 @@ impl<'a> Parser<'a> {
     }
 
     // parse an 'if' expression ('if' token already eaten)
-    pub fn parse_if_expr(&mut self) -> @Expr {
+    pub fn parse_if_expr(&mut self) -> Gc<Expr> {
         let lo = self.last_span.lo;
         let cond = self.parse_expr();
         let thn = self.parse_block();
-        let mut els: Option<@Expr> = None;
+        let mut els: Option<Gc<Expr>> = None;
         let mut hi = thn.span.hi;
         if self.eat_keyword(keywords::Else) {
             let elexpr = self.parse_else_expr();
@@ -2488,7 +2494,7 @@ impl<'a> Parser<'a> {
     }
 
     // `|args| { ... }` or `{ ...}` like in `do` expressions
-    pub fn parse_lambda_block_expr(&mut self) -> @Expr {
+    pub fn parse_lambda_block_expr(&mut self) -> Gc<Expr> {
         self.parse_lambda_expr_(
             |p| {
                 match p.token {
@@ -2517,7 +2523,7 @@ impl<'a> Parser<'a> {
     }
 
     // `|args| expr`
-    pub fn parse_lambda_expr(&mut self) -> @Expr {
+    pub fn parse_lambda_expr(&mut self) -> Gc<Expr> {
         self.parse_lambda_expr_(|p| p.parse_fn_block_decl(),
                                 |p| p.parse_expr())
     }
@@ -2527,8 +2533,8 @@ impl<'a> Parser<'a> {
     // and in parsing a block expr as e.g. in for...
     pub fn parse_lambda_expr_(&mut self,
                               parse_decl: |&mut Parser| -> P<FnDecl>,
-                              parse_body: |&mut Parser| -> @Expr)
-                              -> @Expr {
+                              parse_body: |&mut Parser| -> Gc<Expr>)
+                              -> Gc<Expr> {
         let lo = self.span.lo;
         let decl = parse_decl(self);
         let body = parse_body(self);
@@ -2544,7 +2550,7 @@ impl<'a> Parser<'a> {
         return self.mk_expr(lo, body.span.hi, ExprFnBlock(decl, fakeblock));
     }
 
-    pub fn parse_else_expr(&mut self) -> @Expr {
+    pub fn parse_else_expr(&mut self) -> Gc<Expr> {
         if self.eat_keyword(keywords::If) {
             return self.parse_if_expr();
         } else {
@@ -2554,7 +2560,7 @@ impl<'a> Parser<'a> {
     }
 
     // parse a 'for' .. 'in' expression ('for' token already eaten)
-    pub fn parse_for_expr(&mut self, opt_ident: Option<ast::Ident>) -> @Expr {
+    pub fn parse_for_expr(&mut self, opt_ident: Option<ast::Ident>) -> Gc<Expr> {
         // Parse: `for <src_pat> in <src_expr> <src_loop_block>`
 
         let lo = self.last_span.lo;
@@ -2567,7 +2573,7 @@ impl<'a> Parser<'a> {
         self.mk_expr(lo, hi, ExprForLoop(pat, expr, loop_block, opt_ident))
     }
 
-    pub fn parse_while_expr(&mut self) -> @Expr {
+    pub fn parse_while_expr(&mut self) -> Gc<Expr> {
         let lo = self.last_span.lo;
         let cond = self.parse_expr();
         let body = self.parse_block();
@@ -2575,7 +2581,7 @@ impl<'a> Parser<'a> {
         return self.mk_expr(lo, hi, ExprWhile(cond, body));
     }
 
-    pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::Ident>) -> @Expr {
+    pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::Ident>) -> Gc<Expr> {
         let lo = self.last_span.lo;
         let body = self.parse_block();
         let hi = body.span.hi;
@@ -2590,7 +2596,7 @@ impl<'a> Parser<'a> {
          || self.look_ahead(1, |t| *t == token::DOTDOT))
     }
 
-    fn parse_match_expr(&mut self) -> @Expr {
+    fn parse_match_expr(&mut self) -> Gc<Expr> {
         let lo = self.last_span.lo;
         let discriminant = self.parse_expr();
         self.commit_expr_expecting(discriminant, token::LBRACE);
@@ -2628,12 +2634,12 @@ impl<'a> Parser<'a> {
     }
 
     // parse an expression
-    pub fn parse_expr(&mut self) -> @Expr {
+    pub fn parse_expr(&mut self) -> Gc<Expr> {
         return self.parse_expr_res(UNRESTRICTED);
     }
 
     // parse an expression, subject to the given restriction
-    fn parse_expr_res(&mut self, r: restriction) -> @Expr {
+    fn parse_expr_res(&mut self, r: restriction) -> Gc<Expr> {
         let old = self.restriction;
         self.restriction = r;
         let e = self.parse_assign_expr();
@@ -2642,7 +2648,7 @@ impl<'a> Parser<'a> {
     }
 
     // parse the RHS of a local variable declaration (e.g. '= 14;')
-    fn parse_initializer(&mut self) -> Option<@Expr> {
+    fn parse_initializer(&mut self) -> Option<Gc<Expr>> {
         if self.token == token::EQ {
             self.bump();
             Some(self.parse_expr())
@@ -2652,7 +2658,7 @@ impl<'a> Parser<'a> {
     }
 
     // parse patterns, separated by '|' s
-    fn parse_pats(&mut self) -> Vec<@Pat> {
+    fn parse_pats(&mut self) -> Vec<Gc<Pat>> {
         let mut pats = Vec::new();
         loop {
             pats.push(self.parse_pat());
@@ -2663,7 +2669,7 @@ impl<'a> Parser<'a> {
 
     fn parse_pat_vec_elements(
         &mut self,
-    ) -> (Vec<@Pat> , Option<@Pat>, Vec<@Pat> ) {
+    ) -> (Vec<Gc<Pat>> , Option<Gc<Pat>>, Vec<Gc<Pat>> ) {
         let mut before = Vec::new();
         let mut slice = None;
         let mut after = Vec::new();
@@ -2685,7 +2691,7 @@ impl<'a> Parser<'a> {
 
             if is_slice {
                 if self.token == token::COMMA || self.token == token::RBRACKET {
-                    slice = Some(@ast::Pat {
+                    slice = Some(box(GC) ast::Pat {
                         id: ast::DUMMY_NODE_ID,
                         node: PatWildMulti,
                         span: self.span,
@@ -2764,7 +2770,7 @@ impl<'a> Parser<'a> {
             } else {
                 let fieldpath = ast_util::ident_to_path(self.last_span,
                                                         fieldname);
-                @ast::Pat {
+                box(GC) ast::Pat {
                     id: ast::DUMMY_NODE_ID,
                     node: PatIdent(bind_type, fieldpath, None),
                     span: self.last_span
@@ -2776,7 +2782,7 @@ impl<'a> Parser<'a> {
     }
 
     // parse a pattern.
-    pub fn parse_pat(&mut self) -> @Pat {
+    pub fn parse_pat(&mut self) -> Gc<Pat> {
         maybe_whole!(self, NtPat);
 
         let lo = self.span.lo;
@@ -2788,7 +2794,7 @@ impl<'a> Parser<'a> {
             self.bump();
             pat = PatWild;
             hi = self.last_span.hi;
-            return @ast::Pat {
+            return box(GC) ast::Pat {
                 id: ast::DUMMY_NODE_ID,
                 node: pat,
                 span: mk_sp(lo, hi)
@@ -2801,7 +2807,7 @@ impl<'a> Parser<'a> {
             pat = PatBox(sub);
             hi = self.last_span.hi;
             self.obsolete(self.last_span, ObsoleteOwnedPattern);
-            return @ast::Pat {
+            return box(GC) ast::Pat {
                 id: ast::DUMMY_NODE_ID,
                 node: pat,
                 span: mk_sp(lo, hi)
@@ -2814,7 +2820,7 @@ impl<'a> Parser<'a> {
             let sub = self.parse_pat();
             pat = PatRegion(sub);
             hi = self.last_span.hi;
-            return @ast::Pat {
+            return box(GC) ast::Pat {
                 id: ast::DUMMY_NODE_ID,
                 node: pat,
                 span: mk_sp(lo, hi)
@@ -2826,7 +2832,7 @@ impl<'a> Parser<'a> {
             if self.token == token::RPAREN {
                 hi = self.span.hi;
                 self.bump();
-                let lit = @codemap::Spanned {
+                let lit = box(GC) codemap::Spanned {
                     node: LitNil,
                     span: mk_sp(lo, hi)};
                 let expr = self.mk_expr(lo, hi, ExprLit(lit));
@@ -2845,7 +2851,7 @@ impl<'a> Parser<'a> {
                 pat = PatTup(fields);
             }
             hi = self.last_span.hi;
-            return @ast::Pat {
+            return box(GC) ast::Pat {
                 id: ast::DUMMY_NODE_ID,
                 node: pat,
                 span: mk_sp(lo, hi)
@@ -2860,7 +2866,7 @@ impl<'a> Parser<'a> {
             self.expect(&token::RBRACKET);
             pat = ast::PatVec(before, slice, after);
             hi = self.last_span.hi;
-            return @ast::Pat {
+            return box(GC) ast::Pat {
                 id: ast::DUMMY_NODE_ID,
                 node: pat,
                 span: mk_sp(lo, hi)
@@ -2904,7 +2910,7 @@ impl<'a> Parser<'a> {
             let sub = self.parse_pat();
             pat = PatBox(sub);
             hi = self.last_span.hi;
-            return @ast::Pat {
+            return box(GC) ast::Pat {
                 id: ast::DUMMY_NODE_ID,
                 node: pat,
                 span: mk_sp(lo, hi)
@@ -2960,7 +2966,7 @@ impl<'a> Parser<'a> {
                         pat = PatStruct(enum_path, fields, etc);
                     }
                     _ => {
-                        let mut args: Vec<@Pat> = Vec::new();
+                        let mut args: Vec<Gc<Pat>> = Vec::new();
                         match self.token {
                           token::LPAREN => {
                             let is_dotdot = self.look_ahead(1, |t| {
@@ -3003,7 +3009,7 @@ impl<'a> Parser<'a> {
             }
         }
         hi = self.last_span.hi;
-        @ast::Pat {
+        box(GC) ast::Pat {
             id: ast::DUMMY_NODE_ID,
             node: pat,
             span: mk_sp(lo, hi),
@@ -3044,7 +3050,7 @@ impl<'a> Parser<'a> {
     }
 
     // parse a local variable declaration
-    fn parse_local(&mut self) -> @Local {
+    fn parse_local(&mut self) -> Gc<Local> {
         let lo = self.span.lo;
         let pat = self.parse_pat();
 
@@ -3055,7 +3061,7 @@ impl<'a> Parser<'a> {
         });
         if self.eat(&token::COLON) { ty = self.parse_ty(false); }
         let init = self.parse_initializer();
-        @ast::Local {
+        box(GC) ast::Local {
             ty: ty,
             pat: pat,
             init: init,
@@ -3066,10 +3072,10 @@ impl<'a> Parser<'a> {
     }
 
     // parse a "let" stmt
-    fn parse_let(&mut self) -> @Decl {
+    fn parse_let(&mut self) -> Gc<Decl> {
         let lo = self.span.lo;
         let local = self.parse_local();
-        return @spanned(lo, self.last_span.hi, DeclLocal(local));
+        box(GC) spanned(lo, self.last_span.hi, DeclLocal(local))
     }
 
     // parse a structure field
@@ -3092,7 +3098,7 @@ impl<'a> Parser<'a> {
 
     // parse a statement. may include decl.
     // precondition: any attributes are parsed already
-    pub fn parse_stmt(&mut self, item_attrs: Vec<Attribute> ) -> @Stmt {
+    pub fn parse_stmt(&mut self, item_attrs: Vec<Attribute>) -> Gc<Stmt> {
         maybe_whole!(self, NtStmt);
 
         fn check_expected_item(p: &mut Parser, found_attrs: bool) {
@@ -3107,7 +3113,7 @@ impl<'a> Parser<'a> {
             check_expected_item(self, !item_attrs.is_empty());
             self.expect_keyword(keywords::Let);
             let decl = self.parse_let();
-            return @spanned(lo, decl.span.hi, StmtDecl(decl, ast::DUMMY_NODE_ID));
+            return box(GC) spanned(lo, decl.span.hi, StmtDecl(decl, ast::DUMMY_NODE_ID));
         } else if is_ident(&self.token)
             && !token::is_any_keyword(&self.token)
             && self.look_ahead(1, |t| *t == token::NOT) {
@@ -3166,12 +3172,12 @@ impl<'a> Parser<'a> {
             let hi = self.span.hi;
 
             if id == token::special_idents::invalid {
-                return @spanned(lo, hi, StmtMac(
+                return box(GC) spanned(lo, hi, StmtMac(
                     spanned(lo, hi, MacInvocTT(pth, tts, EMPTY_CTXT)), false));
             } else {
                 // if it has a special ident, it's definitely an item
-                return @spanned(lo, hi, StmtDecl(
-                    @spanned(lo, hi, DeclItem(
+                return box(GC) spanned(lo, hi, StmtDecl(
+                    box(GC) spanned(lo, hi, DeclItem(
                         self.mk_item(
                             lo, hi, id /*id is good here*/,
                             ItemMac(spanned(lo, hi, MacInvocTT(pth, tts, EMPTY_CTXT))),
@@ -3184,8 +3190,8 @@ impl<'a> Parser<'a> {
             match self.parse_item_or_view_item(item_attrs, false) {
                 IoviItem(i) => {
                     let hi = i.span.hi;
-                    let decl = @spanned(lo, hi, DeclItem(i));
-                    return @spanned(lo, hi, StmtDecl(decl, ast::DUMMY_NODE_ID));
+                    let decl = box(GC) spanned(lo, hi, DeclItem(i));
+                    return box(GC) spanned(lo, hi, StmtDecl(decl, ast::DUMMY_NODE_ID));
                 }
                 IoviViewItem(vi) => {
                     self.span_fatal(vi.span,
@@ -3201,12 +3207,12 @@ impl<'a> Parser<'a> {
 
             // Remainder are line-expr stmts.
             let e = self.parse_expr_res(RESTRICT_STMT_EXPR);
-            return @spanned(lo, e.span.hi, StmtExpr(e, ast::DUMMY_NODE_ID));
+            return box(GC) spanned(lo, e.span.hi, StmtExpr(e, ast::DUMMY_NODE_ID));
         }
     }
 
     // is this expression a successfully-parsed statement?
-    fn expr_is_complete(&mut self, e: @Expr) -> bool {
+    fn expr_is_complete(&mut self, e: Gc<Expr>) -> bool {
         return self.restriction == RESTRICT_STMT_EXPR &&
             !classify::expr_requires_semi_to_be_stmt(e);
     }
@@ -3258,8 +3264,8 @@ impl<'a> Parser<'a> {
                                             false, false);
 
         for item in items.iter() {
-            let decl = @spanned(item.span.lo, item.span.hi, DeclItem(*item));
-            stmts.push(@spanned(item.span.lo, item.span.hi,
+            let decl = box(GC) spanned(item.span.lo, item.span.hi, DeclItem(*item));
+            stmts.push(box(GC) spanned(item.span.lo, item.span.hi,
                                 StmtDecl(decl, ast::DUMMY_NODE_ID)));
         }
 
@@ -3286,7 +3292,7 @@ impl<'a> Parser<'a> {
                     match stmt.node {
                         StmtExpr(e, stmt_id) => {
                             // expression without semicolon
-                            if classify::stmt_ends_with_semi(stmt) {
+                            if classify::stmt_ends_with_semi(&*stmt) {
                                 // Just check for errors and recover; do not eat semicolon yet.
                                 self.commit_stmt(stmt, &[], &[token::SEMI, token::RBRACE]);
                             }
@@ -3299,7 +3305,7 @@ impl<'a> Parser<'a> {
                                         hi: self.last_span.hi,
                                         expn_info: stmt.span.expn_info,
                                     };
-                                    stmts.push(@codemap::Spanned {
+                                    stmts.push(box(GC) codemap::Spanned {
                                         node: StmtSemi(e, stmt_id),
                                         span: span_with_semi,
                                     });
@@ -3317,7 +3323,7 @@ impl<'a> Parser<'a> {
                             match self.token {
                                 token::SEMI => {
                                     self.bump();
-                                    stmts.push(@codemap::Spanned {
+                                    stmts.push(box(GC) codemap::Spanned {
                                         node: StmtMac((*m).clone(), true),
                                         span: stmt.span,
                                     });
@@ -3336,9 +3342,9 @@ impl<'a> Parser<'a> {
                             }
                         }
                         _ => { // all other kinds of statements:
-                            stmts.push(stmt);
+                            stmts.push(stmt.clone());
 
-                            if classify::stmt_ends_with_semi(stmt) {
+                            if classify::stmt_ends_with_semi(&*stmt) {
                                 self.commit_stmt_expecting(stmt, token::SEMI);
                             }
                         }
@@ -3827,8 +3833,8 @@ impl<'a> Parser<'a> {
 
     fn mk_item(&mut self, lo: BytePos, hi: BytePos, ident: Ident,
                node: Item_, vis: Visibility,
-               attrs: Vec<Attribute> ) -> @Item {
-        @Item {
+               attrs: Vec<Attribute>) -> Gc<Item> {
+        box(GC) Item {
             ident: ident,
             attrs: attrs,
             id: ast::DUMMY_NODE_ID,
@@ -3847,7 +3853,8 @@ impl<'a> Parser<'a> {
     }
 
     // parse a method in a trait impl, starting with `attrs` attributes.
-    fn parse_method(&mut self, already_parsed_attrs: Option<Vec<Attribute> >) -> @Method {
+    fn parse_method(&mut self,
+                    already_parsed_attrs: Option<Vec<Attribute>>) -> Gc<Method> {
         let next_attrs = self.parse_outer_attributes();
         let attrs = match already_parsed_attrs {
             Some(mut a) => { a.push_all_move(next_attrs); a }
@@ -3867,7 +3874,7 @@ impl<'a> Parser<'a> {
         let (inner_attrs, body) = self.parse_inner_attrs_and_block();
         let hi = body.span.hi;
         let attrs = attrs.append(inner_attrs.as_slice());
-        @ast::Method {
+        box(GC) ast::Method {
             ident: ident,
             attrs: attrs,
             generics: generics,
@@ -3950,7 +3957,7 @@ impl<'a> Parser<'a> {
             method_attrs = None;
         }
 
-        let ident = ast_util::impl_pretty_name(&opt_trait, ty);
+        let ident = ast_util::impl_pretty_name(&opt_trait, &*ty);
 
         (ident, ItemImpl(generics, opt_trait, ty, meths), Some(inner_attrs))
     }
@@ -4041,7 +4048,7 @@ impl<'a> Parser<'a> {
         let _ = ast::DUMMY_NODE_ID;  // FIXME: Workaround for crazy bug.
         let new_id = ast::DUMMY_NODE_ID;
         (class_name,
-         ItemStruct(@ast::StructDef {
+         ItemStruct(box(GC) ast::StructDef {
              fields: fields,
              ctor_id: if is_tuple_like { Some(new_id) } else { None },
              super_struct: super_struct,
@@ -4121,7 +4128,7 @@ impl<'a> Parser<'a> {
             items: starting_items,
             ..
         } = self.parse_items_and_view_items(first_item_attrs, true, true);
-        let mut items: Vec<@Item> = starting_items;
+        let mut items: Vec<Gc<Item>> = starting_items;
         let attrs_remaining_len = attrs_remaining.len();
 
         // don't think this other loop is even necessary....
@@ -4322,7 +4329,7 @@ impl<'a> Parser<'a> {
 
     // parse a function declaration from a foreign module
     fn parse_item_foreign_fn(&mut self, vis: ast::Visibility,
-                             attrs: Vec<Attribute> ) -> @ForeignItem {
+                             attrs: Vec<Attribute>) -> Gc<ForeignItem> {
         let lo = self.span.lo;
         self.expect_keyword(keywords::Fn);
 
@@ -4330,17 +4337,17 @@ impl<'a> Parser<'a> {
         let decl = self.parse_fn_decl(true);
         let hi = self.span.hi;
         self.expect(&token::SEMI);
-        @ast::ForeignItem { ident: ident,
-                            attrs: attrs,
-                            node: ForeignItemFn(decl, generics),
-                            id: ast::DUMMY_NODE_ID,
-                            span: mk_sp(lo, hi),
-                            vis: vis }
+        box(GC) ast::ForeignItem { ident: ident,
+                                   attrs: attrs,
+                                   node: ForeignItemFn(decl, generics),
+                                   id: ast::DUMMY_NODE_ID,
+                                   span: mk_sp(lo, hi),
+                                   vis: vis }
     }
 
     // parse a static item from a foreign module
     fn parse_item_foreign_static(&mut self, vis: ast::Visibility,
-                                 attrs: Vec<Attribute> ) -> @ForeignItem {
+                                 attrs: Vec<Attribute> ) -> Gc<ForeignItem> {
         let lo = self.span.lo;
 
         self.expect_keyword(keywords::Static);
@@ -4351,7 +4358,7 @@ impl<'a> Parser<'a> {
         let ty = self.parse_ty(false);
         let hi = self.span.hi;
         self.expect(&token::SEMI);
-        @ast::ForeignItem {
+        box(GC) ast::ForeignItem {
             ident: ident,
             attrs: attrs,
             node: ForeignItemStatic(ty, mutbl),
@@ -4483,14 +4490,14 @@ impl<'a> Parser<'a> {
 
     // parse a structure-like enum variant definition
     // this should probably be renamed or refactored...
-    fn parse_struct_def(&mut self) -> @StructDef {
+    fn parse_struct_def(&mut self) -> Gc<StructDef> {
         let mut fields: Vec<StructField> = Vec::new();
         while self.token != token::RBRACE {
             fields.push(self.parse_struct_decl_field());
         }
         self.bump();
 
-        return @ast::StructDef {
+        return box(GC) ast::StructDef {
             fields: fields,
             ctor_id: None,
             super_struct: None,
@@ -4617,7 +4624,7 @@ impl<'a> Parser<'a> {
             INTERPOLATED(token::NtItem(item)) => {
                 self.bump();
                 let new_attrs = attrs.append(item.attrs.as_slice());
-                return IoviItem(@Item {
+                return IoviItem(box(GC) Item {
                     attrs: new_attrs,
                     ..(*item).clone()
                 });
@@ -4892,7 +4899,7 @@ impl<'a> Parser<'a> {
         return IoviNone(attrs);
     }
 
-    pub fn parse_item(&mut self, attrs: Vec<Attribute> ) -> Option<@Item> {
+    pub fn parse_item(&mut self, attrs: Vec<Attribute> ) -> Option<Gc<Item>> {
         match self.parse_item_or_view_item(attrs, true) {
             IoviNone(_) => None,
             IoviViewItem(_) =>
@@ -4914,7 +4921,7 @@ impl<'a> Parser<'a> {
     // | MOD? non_global_path MOD_SEP LBRACE ident_seq RBRACE
     // | MOD? non_global_path MOD_SEP STAR
     // | MOD? non_global_path
-    fn parse_view_path(&mut self) -> @ViewPath {
+    fn parse_view_path(&mut self) -> Gc<ViewPath> {
         let lo = self.span.lo;
 
         if self.token == token::LBRACE {
@@ -4928,7 +4935,7 @@ impl<'a> Parser<'a> {
                 global: false,
                 segments: Vec::new()
             };
-            return @spanned(lo, self.span.hi,
+            return box(GC) spanned(lo, self.span.hi,
                             ViewPathList(path, idents, ast::DUMMY_NODE_ID));
         }
 
@@ -4956,7 +4963,7 @@ impl<'a> Parser<'a> {
                     }
                 }).collect()
             };
-            return @spanned(lo, self.span.hi,
+            return box(GC) spanned(lo, self.span.hi,
                             ViewPathSimple(first_ident, path,
                                            ast::DUMMY_NODE_ID));
           }
@@ -4991,7 +4998,7 @@ impl<'a> Parser<'a> {
                             }
                         }).collect()
                     };
-                    return @spanned(lo, self.span.hi,
+                    return box(GC) spanned(lo, self.span.hi,
                                     ViewPathList(path, idents, ast::DUMMY_NODE_ID));
                   }
 
@@ -5009,7 +5016,7 @@ impl<'a> Parser<'a> {
                             }
                         }).collect()
                     };
-                    return @spanned(lo, self.span.hi,
+                    return box(GC) spanned(lo, self.span.hi,
                                     ViewPathGlob(path, ast::DUMMY_NODE_ID));
                   }
 
@@ -5031,7 +5038,7 @@ impl<'a> Parser<'a> {
                 }
             }).collect()
         };
-        return @spanned(lo,
+        return box(GC) spanned(lo,
                         self.last_span.hi,
                         ViewPathSimple(last, path, ast::DUMMY_NODE_ID));
     }
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 129ea5fdf6d..fa70261a7d7 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -18,10 +18,10 @@ use util::interner;
 
 use serialize::{Decodable, Decoder, Encodable, Encoder};
 use std::fmt;
-use std::path::BytesContainer;
+use std::gc::Gc;
 use std::mem;
+use std::path::BytesContainer;
 use std::rc::Rc;
-use std::string::String;
 
 #[allow(non_camel_case_types)]
 #[deriving(Clone, Encodable, Decodable, PartialEq, Eq, Hash, Show)]
@@ -105,16 +105,16 @@ pub enum Token {
 #[deriving(Clone, Encodable, Decodable, PartialEq, Eq, Hash)]
 /// For interpolation during macro expansion.
 pub enum Nonterminal {
-    NtItem(@ast::Item),
+    NtItem(Gc<ast::Item>),
     NtBlock(P<ast::Block>),
-    NtStmt(@ast::Stmt),
-    NtPat( @ast::Pat),
-    NtExpr(@ast::Expr),
+    NtStmt(Gc<ast::Stmt>),
+    NtPat( Gc<ast::Pat>),
+    NtExpr(Gc<ast::Expr>),
     NtTy(  P<ast::Ty>),
     NtIdent(Box<ast::Ident>, bool),
-    NtMeta(@ast::MetaItem), // stuff inside brackets for attributes
+    NtMeta(Gc<ast::MetaItem>), // stuff inside brackets for attributes
     NtPath(Box<ast::Path>),
-    NtTT(  @ast::TokenTree), // needs @ed to break a circularity
+    NtTT(  Gc<ast::TokenTree>), // needs @ed to break a circularity
     NtMatchers(Vec<ast::Matcher> )
 }
 
@@ -241,8 +241,8 @@ pub fn to_str(t: &Token) -> String {
       EOF => "<eof>".to_string(),
       INTERPOLATED(ref nt) => {
         match nt {
-            &NtExpr(e) => ::print::pprust::expr_to_str(e),
-            &NtMeta(e) => ::print::pprust::meta_item_to_str(e),
+            &NtExpr(ref e) => ::print::pprust::expr_to_str(&**e),
+            &NtMeta(ref e) => ::print::pprust::meta_item_to_str(&**e),
             _ => {
                 let mut s = "an interpolated ".to_string();
                 match *nt {
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 7cdc93c7314..82d74ff07f3 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -26,11 +26,11 @@ use print::pp::{break_offset, word, space, zerobreak, hardbreak};
 use print::pp::{Breaks, Consistent, Inconsistent, eof};
 use print::pp;
 
+use std::gc::Gc;
 use std::io::{IoResult, MemWriter};
 use std::io;
 use std::mem;
 use std::str;
-use std::string::String;
 
 pub enum AnnNode<'a> {
     NodeBlock(&'a ast::Block),
@@ -421,8 +421,8 @@ impl<'a> State<'a> {
     }
 
     pub fn commasep_exprs(&mut self, b: Breaks,
-                          exprs: &[@ast::Expr]) -> IoResult<()> {
-        self.commasep_cmnt(b, exprs, |s, &e| s.print_expr(e), |e| e.span)
+                          exprs: &[Gc<ast::Expr>]) -> IoResult<()> {
+        self.commasep_cmnt(b, exprs, |s, e| s.print_expr(&**e), |e| e.span)
     }
 
     pub fn print_mod(&mut self, _mod: &ast::Mod,
@@ -432,7 +432,7 @@ impl<'a> State<'a> {
             try!(self.print_view_item(vitem));
         }
         for item in _mod.items.iter() {
-            try!(self.print_item(*item));
+            try!(self.print_item(&**item));
         }
         Ok(())
     }
@@ -444,7 +444,7 @@ impl<'a> State<'a> {
             try!(self.print_view_item(vitem));
         }
         for item in nmod.items.iter() {
-            try!(self.print_foreign_item(*item));
+            try!(self.print_foreign_item(&**item));
         }
         Ok(())
     }
@@ -464,17 +464,17 @@ impl<'a> State<'a> {
         match ty.node {
             ast::TyNil => try!(word(&mut self.s, "()")),
             ast::TyBot => try!(word(&mut self.s, "!")),
-            ast::TyBox(ty) => {
+            ast::TyBox(ref ty) => {
                 try!(word(&mut self.s, "@"));
-                try!(self.print_type(ty));
+                try!(self.print_type(&**ty));
             }
-            ast::TyUniq(ty) => {
+            ast::TyUniq(ref ty) => {
                 try!(word(&mut self.s, "~"));
-                try!(self.print_type(ty));
+                try!(self.print_type(&**ty));
             }
-            ast::TyVec(ty) => {
+            ast::TyVec(ref ty) => {
                 try!(word(&mut self.s, "["));
-                try!(self.print_type(ty));
+                try!(self.print_type(&**ty));
                 try!(word(&mut self.s, "]"));
             }
             ast::TyPtr(ref mt) => {
@@ -505,7 +505,7 @@ impl<'a> State<'a> {
                                       &None,
                                       f.fn_style,
                                       ast::Many,
-                                      f.decl,
+                                      &*f.decl,
                                       None,
                                       &None,
                                       Some(&generics),
@@ -522,14 +522,14 @@ impl<'a> State<'a> {
                                       region,
                                       f.fn_style,
                                       f.onceness,
-                                      f.decl,
+                                      &*f.decl,
                                       None,
                                       &f.bounds,
                                       Some(&generics),
                                       None,
                                       false));
             }
-            ast::TyProc(f) => {
+            ast::TyProc(ref f) => {
                 let generics = ast::Generics {
                     lifetimes: f.lifetimes.clone(),
                     ty_params: OwnedSlice::empty()
@@ -539,7 +539,7 @@ impl<'a> State<'a> {
                                       &None,
                                       f.fn_style,
                                       f.onceness,
-                                      f.decl,
+                                      &*f.decl,
                                       None,
                                       &f.bounds,
                                       Some(&generics),
@@ -552,7 +552,7 @@ impl<'a> State<'a> {
                                       &None,
                                       ast::NormalFn,
                                       ast::Many,
-                                      f.decl,
+                                      &*f.decl,
                                       None,
                                       &None,
                                       None,
@@ -562,16 +562,16 @@ impl<'a> State<'a> {
             ast::TyPath(ref path, ref bounds, _) => {
                 try!(self.print_bounded_path(path, bounds));
             }
-            ast::TyFixedLengthVec(ty, v) => {
+            ast::TyFixedLengthVec(ref ty, ref v) => {
                 try!(word(&mut self.s, "["));
-                try!(self.print_type(ty));
+                try!(self.print_type(&**ty));
                 try!(word(&mut self.s, ", .."));
-                try!(self.print_expr(v));
+                try!(self.print_expr(&**v));
                 try!(word(&mut self.s, "]"));
             }
-            ast::TyTypeof(e) => {
+            ast::TyTypeof(ref e) => {
                 try!(word(&mut self.s, "typeof("));
-                try!(self.print_expr(e));
+                try!(self.print_expr(&**e));
                 try!(word(&mut self.s, ")"));
             }
             ast::TyInfer => {
@@ -582,7 +582,7 @@ impl<'a> State<'a> {
     }
 
     pub fn print_type_ref(&mut self, ty: &P<ast::Ty>) -> IoResult<()> {
-        self.print_type(*ty)
+        self.print_type(&**ty)
     }
 
     pub fn print_foreign_item(&mut self,
@@ -591,14 +591,14 @@ impl<'a> State<'a> {
         try!(self.maybe_print_comment(item.span.lo));
         try!(self.print_outer_attributes(item.attrs.as_slice()));
         match item.node {
-            ast::ForeignItemFn(decl, ref generics) => {
-                try!(self.print_fn(decl, None, abi::Rust, item.ident, generics,
-                None, item.vis));
+            ast::ForeignItemFn(ref decl, ref generics) => {
+                try!(self.print_fn(&**decl, None, abi::Rust, item.ident, generics,
+                                   None, item.vis));
                 try!(self.end()); // end head-ibox
                 try!(word(&mut self.s, ";"));
                 self.end() // end the outer fn box
             }
-            ast::ForeignItemStatic(t, m) => {
+            ast::ForeignItemStatic(ref t, m) => {
                 try!(self.head(visibility_qualified(item.vis,
                                                     "static").as_slice()));
                 if m {
@@ -606,7 +606,7 @@ impl<'a> State<'a> {
                 }
                 try!(self.print_ident(item.ident));
                 try!(self.word_space(":"));
-                try!(self.print_type(t));
+                try!(self.print_type(&**t));
                 try!(word(&mut self.s, ";"));
                 try!(self.end()); // end the head-ibox
                 self.end() // end the outer cbox
@@ -620,7 +620,7 @@ impl<'a> State<'a> {
         try!(self.print_outer_attributes(item.attrs.as_slice()));
         try!(self.ann.pre(self, NodeItem(item)));
         match item.node {
-            ast::ItemStatic(ty, m, expr) => {
+            ast::ItemStatic(ref ty, m, ref expr) => {
                 try!(self.head(visibility_qualified(item.vis,
                                                     "static").as_slice()));
                 if m == ast::MutMutable {
@@ -628,18 +628,18 @@ impl<'a> State<'a> {
                 }
                 try!(self.print_ident(item.ident));
                 try!(self.word_space(":"));
-                try!(self.print_type(ty));
+                try!(self.print_type(&**ty));
                 try!(space(&mut self.s));
                 try!(self.end()); // end the head-ibox
 
                 try!(self.word_space("="));
-                try!(self.print_expr(expr));
+                try!(self.print_expr(&**expr));
                 try!(word(&mut self.s, ";"));
                 try!(self.end()); // end the outer cbox
             }
-            ast::ItemFn(decl, fn_style, abi, ref typarams, body) => {
+            ast::ItemFn(ref decl, fn_style, abi, ref typarams, ref body) => {
                 try!(self.print_fn(
-                    decl,
+                    &**decl,
                     Some(fn_style),
                     abi,
                     item.ident,
@@ -648,7 +648,7 @@ impl<'a> State<'a> {
                     item.vis
                 ));
                 try!(word(&mut self.s, " "));
-                try!(self.print_block_with_attrs(body, item.attrs.as_slice()));
+                try!(self.print_block_with_attrs(&**body, item.attrs.as_slice()));
             }
             ast::ItemMod(ref _mod) => {
                 try!(self.head(visibility_qualified(item.vis,
@@ -666,7 +666,7 @@ impl<'a> State<'a> {
                 try!(self.print_foreign_mod(nmod, item.attrs.as_slice()));
                 try!(self.bclose(item.span));
             }
-            ast::ItemTy(ty, ref params) => {
+            ast::ItemTy(ref ty, ref params) => {
                 try!(self.ibox(indent_unit));
                 try!(self.ibox(0u));
                 try!(self.word_nbsp(visibility_qualified(item.vis,
@@ -677,7 +677,7 @@ impl<'a> State<'a> {
 
                 try!(space(&mut self.s));
                 try!(self.word_space("="));
-                try!(self.print_type(ty));
+                try!(self.print_type(&**ty));
                 try!(word(&mut self.s, ";"));
                 try!(self.end()); // end the outer ibox
             }
@@ -690,16 +690,17 @@ impl<'a> State<'a> {
                     item.vis
                 ));
             }
-            ast::ItemStruct(struct_def, ref generics) => {
+            ast::ItemStruct(ref struct_def, ref generics) => {
                 if struct_def.is_virtual {
                     try!(self.word_space("virtual"));
                 }
                 try!(self.head(visibility_qualified(item.vis,
                                                     "struct").as_slice()));
-                try!(self.print_struct(struct_def, generics, item.ident, item.span));
+                try!(self.print_struct(&**struct_def, generics, item.ident,
+                                       item.span));
             }
 
-            ast::ItemImpl(ref generics, ref opt_trait, ty, ref methods) => {
+            ast::ItemImpl(ref generics, ref opt_trait, ref ty, ref methods) => {
                 try!(self.head(visibility_qualified(item.vis,
                                                     "impl").as_slice()));
                 if generics.is_parameterized() {
@@ -716,13 +717,13 @@ impl<'a> State<'a> {
                     &None => {}
                 }
 
-                try!(self.print_type(ty));
+                try!(self.print_type(&**ty));
 
                 try!(space(&mut self.s));
                 try!(self.bopen());
                 try!(self.print_inner_attributes(item.attrs.as_slice()));
                 for meth in methods.iter() {
-                    try!(self.print_method(*meth));
+                    try!(self.print_method(&**meth));
                 }
                 try!(self.bclose(item.span));
             }
@@ -788,12 +789,12 @@ impl<'a> State<'a> {
                           variants: &[P<ast::Variant>],
                           span: codemap::Span) -> IoResult<()> {
         try!(self.bopen());
-        for &v in variants.iter() {
+        for v in variants.iter() {
             try!(self.space_if_not_bol());
             try!(self.maybe_print_comment(v.span.lo));
             try!(self.print_outer_attributes(v.node.attrs.as_slice()));
             try!(self.ibox(indent_unit));
-            try!(self.print_variant(v));
+            try!(self.print_variant(&**v));
             try!(word(&mut self.s, ","));
             try!(self.end());
             try!(self.maybe_print_trailing_comment(v.span, None));
@@ -816,9 +817,9 @@ impl<'a> State<'a> {
         try!(self.print_ident(ident));
         try!(self.print_generics(generics));
         match struct_def.super_struct {
-            Some(t) => {
+            Some(ref t) => {
                 try!(self.word_space(":"));
-                try!(self.print_type(t));
+                try!(self.print_type(&**t));
             },
             None => {},
         }
@@ -833,7 +834,7 @@ impl<'a> State<'a> {
                             ast::UnnamedField(vis) => {
                                 try!(s.print_visibility(vis));
                                 try!(s.maybe_print_comment(field.span.lo));
-                                s.print_type(field.node.ty)
+                                s.print_type(&*field.node.ty)
                             }
                         }
                     }
@@ -858,7 +859,7 @@ impl<'a> State<'a> {
                         try!(self.print_visibility(visibility));
                         try!(self.print_ident(ident));
                         try!(self.word_nbsp(":"));
-                        try!(self.print_type(field.node.ty));
+                        try!(self.print_type(&*field.node.ty));
                         try!(word(&mut self.s, ","));
                     }
                 }
@@ -929,21 +930,21 @@ impl<'a> State<'a> {
                     try!(self.popen());
                     try!(self.commasep(Consistent,
                                        args.as_slice(),
-                                       |s, arg| s.print_type(arg.ty)));
+                                       |s, arg| s.print_type(&*arg.ty)));
                     try!(self.pclose());
                 }
             }
-            ast::StructVariantKind(struct_def) => {
+            ast::StructVariantKind(ref struct_def) => {
                 try!(self.head(""));
                 let generics = ast_util::empty_generics();
-                try!(self.print_struct(struct_def, &generics, v.node.name, v.span));
+                try!(self.print_struct(&**struct_def, &generics, v.node.name, v.span));
             }
         }
         match v.node.disr_expr {
-            Some(d) => {
+            Some(ref d) => {
                 try!(space(&mut self.s));
                 try!(self.word_space("="));
-                self.print_expr(d)
+                self.print_expr(&**d)
             }
             _ => Ok(())
         }
@@ -958,7 +959,7 @@ impl<'a> State<'a> {
                               &None,
                               m.fn_style,
                               ast::Many,
-                              m.decl,
+                              &*m.decl,
                               Some(m.ident),
                               &None,
                               Some(&m.generics),
@@ -971,7 +972,7 @@ impl<'a> State<'a> {
                               m: &ast::TraitMethod) -> IoResult<()> {
         match *m {
             Required(ref ty_m) => self.print_ty_method(ty_m),
-            Provided(m) => self.print_method(m)
+            Provided(ref m) => self.print_method(&**m)
         }
     }
 
@@ -979,11 +980,11 @@ impl<'a> State<'a> {
         try!(self.hardbreak_if_not_bol());
         try!(self.maybe_print_comment(meth.span.lo));
         try!(self.print_outer_attributes(meth.attrs.as_slice()));
-        try!(self.print_fn(meth.decl, Some(meth.fn_style), abi::Rust,
+        try!(self.print_fn(&*meth.decl, Some(meth.fn_style), abi::Rust,
                         meth.ident, &meth.generics, Some(meth.explicit_self.node),
                         meth.vis));
         try!(word(&mut self.s, " "));
-        self.print_block_with_attrs(meth.body, meth.attrs.as_slice())
+        self.print_block_with_attrs(&*meth.body, meth.attrs.as_slice())
     }
 
     pub fn print_outer_attributes(&mut self,
@@ -1032,7 +1033,7 @@ impl<'a> State<'a> {
                 ast::AttrInner => try!(word(&mut self.s, "#![")),
                 ast::AttrOuter => try!(word(&mut self.s, "#[")),
             }
-            try!(self.print_meta_item(attr.meta()));
+            try!(self.print_meta_item(&*attr.meta()));
             word(&mut self.s, "]")
         }
     }
@@ -1041,16 +1042,16 @@ impl<'a> State<'a> {
     pub fn print_stmt(&mut self, st: &ast::Stmt) -> IoResult<()> {
         try!(self.maybe_print_comment(st.span.lo));
         match st.node {
-            ast::StmtDecl(decl, _) => {
-                try!(self.print_decl(decl));
+            ast::StmtDecl(ref decl, _) => {
+                try!(self.print_decl(&**decl));
             }
-            ast::StmtExpr(expr, _) => {
+            ast::StmtExpr(ref expr, _) => {
                 try!(self.space_if_not_bol());
-                try!(self.print_expr(expr));
+                try!(self.print_expr(&**expr));
             }
-            ast::StmtSemi(expr, _) => {
+            ast::StmtSemi(ref expr, _) => {
                 try!(self.space_if_not_bol());
-                try!(self.print_expr(expr));
+                try!(self.print_expr(&**expr));
                 try!(word(&mut self.s, ";"));
             }
             ast::StmtMac(ref mac, semi) => {
@@ -1105,12 +1106,12 @@ impl<'a> State<'a> {
             try!(self.print_view_item(vi));
         }
         for st in blk.stmts.iter() {
-            try!(self.print_stmt(*st));
+            try!(self.print_stmt(&**st));
         }
         match blk.expr {
-            Some(expr) => {
+            Some(ref expr) => {
                 try!(self.space_if_not_bol());
-                try!(self.print_expr(expr));
+                try!(self.print_expr(&**expr));
                 try!(self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi)));
             }
             _ => ()
@@ -1119,26 +1120,26 @@ impl<'a> State<'a> {
         self.ann.post(self, NodeBlock(blk))
     }
 
-    fn print_else(&mut self, els: Option<@ast::Expr>) -> IoResult<()> {
+    fn print_else(&mut self, els: Option<Gc<ast::Expr>>) -> IoResult<()> {
         match els {
             Some(_else) => {
                 match _else.node {
                     // "another else-if"
-                    ast::ExprIf(i, t, e) => {
+                    ast::ExprIf(ref i, ref t, e) => {
                         try!(self.cbox(indent_unit - 1u));
                         try!(self.ibox(0u));
                         try!(word(&mut self.s, " else if "));
-                        try!(self.print_expr(i));
+                        try!(self.print_expr(&**i));
                         try!(space(&mut self.s));
-                        try!(self.print_block(t));
+                        try!(self.print_block(&**t));
                         self.print_else(e)
                     }
                     // "final else"
-                    ast::ExprBlock(b) => {
+                    ast::ExprBlock(ref b) => {
                         try!(self.cbox(indent_unit - 1u));
                         try!(self.ibox(0u));
                         try!(word(&mut self.s, " else "));
-                        self.print_block(b)
+                        self.print_block(&**b)
                     }
                     // BLEAH, constraints would be great here
                     _ => {
@@ -1151,7 +1152,7 @@ impl<'a> State<'a> {
     }
 
     pub fn print_if(&mut self, test: &ast::Expr, blk: &ast::Block,
-                    elseopt: Option<@ast::Expr>, chk: bool) -> IoResult<()> {
+                    elseopt: Option<Gc<ast::Expr>>, chk: bool) -> IoResult<()> {
         try!(self.head("if"));
         if chk { try!(self.word_nbsp("check")); }
         try!(self.print_expr(test));
@@ -1184,7 +1185,7 @@ impl<'a> State<'a> {
         }
     }
 
-    fn print_call_post(&mut self, args: &[@ast::Expr]) -> IoResult<()> {
+    fn print_call_post(&mut self, args: &[Gc<ast::Expr>]) -> IoResult<()> {
         try!(self.popen());
         try!(self.commasep_exprs(Inconsistent, args));
         self.pclose()
@@ -1207,16 +1208,16 @@ impl<'a> State<'a> {
         try!(self.ibox(indent_unit));
         try!(self.ann.pre(self, NodeExpr(expr)));
         match expr.node {
-            ast::ExprVstore(e, v) => {
+            ast::ExprVstore(ref e, v) => {
                 try!(self.print_expr_vstore(v));
-                try!(self.print_expr(e));
+                try!(self.print_expr(&**e));
             },
-            ast::ExprBox(p, e) => {
+            ast::ExprBox(ref p, ref e) => {
                 try!(word(&mut self.s, "box"));
                 try!(word(&mut self.s, "("));
-                try!(self.print_expr(p));
+                try!(self.print_expr(&**p));
                 try!(self.word_space(")"));
-                try!(self.print_expr(e));
+                try!(self.print_expr(&**e));
             }
             ast::ExprVec(ref exprs) => {
                 try!(self.ibox(indent_unit));
@@ -1226,13 +1227,13 @@ impl<'a> State<'a> {
                 try!(self.end());
             }
 
-            ast::ExprRepeat(element, count) => {
+            ast::ExprRepeat(ref element, ref count) => {
                 try!(self.ibox(indent_unit));
                 try!(word(&mut self.s, "["));
-                try!(self.print_expr(element));
+                try!(self.print_expr(&**element));
                 try!(word(&mut self.s, ","));
                 try!(word(&mut self.s, ".."));
-                try!(self.print_expr(count));
+                try!(self.print_expr(&**count));
                 try!(word(&mut self.s, "]"));
                 try!(self.end());
             }
@@ -1247,19 +1248,19 @@ impl<'a> State<'a> {
                         try!(s.ibox(indent_unit));
                         try!(s.print_ident(field.ident.node));
                         try!(s.word_space(":"));
-                        try!(s.print_expr(field.expr));
+                        try!(s.print_expr(&*field.expr));
                         s.end()
                     },
                     |f| f.span));
                 match wth {
-                    Some(expr) => {
+                    Some(ref expr) => {
                         try!(self.ibox(indent_unit));
                         if !fields.is_empty() {
                             try!(word(&mut self.s, ","));
                             try!(space(&mut self.s));
                         }
                         try!(word(&mut self.s, ".."));
-                        try!(self.print_expr(expr));
+                        try!(self.print_expr(&**expr));
                         try!(self.end());
                     }
                     _ => try!(word(&mut self.s, ","))
@@ -1274,13 +1275,13 @@ impl<'a> State<'a> {
                 }
                 try!(self.pclose());
             }
-            ast::ExprCall(func, ref args) => {
-                try!(self.print_expr_maybe_paren(func));
+            ast::ExprCall(ref func, ref args) => {
+                try!(self.print_expr_maybe_paren(&**func));
                 try!(self.print_call_post(args.as_slice()));
             }
             ast::ExprMethodCall(ident, ref tys, ref args) => {
                 let base_args = args.slice_from(1);
-                try!(self.print_expr(*args.get(0)));
+                try!(self.print_expr(&**args.get(0)));
                 try!(word(&mut self.s, "."));
                 try!(self.print_ident(ident.node));
                 if tys.len() > 0u {
@@ -1291,52 +1292,52 @@ impl<'a> State<'a> {
                 }
                 try!(self.print_call_post(base_args));
             }
-            ast::ExprBinary(op, lhs, rhs) => {
-                try!(self.print_expr(lhs));
+            ast::ExprBinary(op, ref lhs, ref rhs) => {
+                try!(self.print_expr(&**lhs));
                 try!(space(&mut self.s));
                 try!(self.word_space(ast_util::binop_to_str(op)));
-                try!(self.print_expr(rhs));
+                try!(self.print_expr(&**rhs));
             }
-            ast::ExprUnary(op, expr) => {
+            ast::ExprUnary(op, ref expr) => {
                 try!(word(&mut self.s, ast_util::unop_to_str(op)));
-                try!(self.print_expr_maybe_paren(expr));
+                try!(self.print_expr_maybe_paren(&**expr));
             }
-            ast::ExprAddrOf(m, expr) => {
+            ast::ExprAddrOf(m, ref expr) => {
                 try!(word(&mut self.s, "&"));
                 try!(self.print_mutability(m));
-                try!(self.print_expr_maybe_paren(expr));
+                try!(self.print_expr_maybe_paren(&**expr));
             }
-            ast::ExprLit(lit) => try!(self.print_literal(lit)),
-            ast::ExprCast(expr, ty) => {
-                try!(self.print_expr(expr));
+            ast::ExprLit(ref lit) => try!(self.print_literal(&**lit)),
+            ast::ExprCast(ref expr, ref ty) => {
+                try!(self.print_expr(&**expr));
                 try!(space(&mut self.s));
                 try!(self.word_space("as"));
-                try!(self.print_type(ty));
+                try!(self.print_type(&**ty));
             }
-            ast::ExprIf(test, blk, elseopt) => {
-                try!(self.print_if(test, blk, elseopt, false));
+            ast::ExprIf(ref test, ref blk, elseopt) => {
+                try!(self.print_if(&**test, &**blk, elseopt, false));
             }
-            ast::ExprWhile(test, blk) => {
+            ast::ExprWhile(ref test, ref blk) => {
                 try!(self.head("while"));
-                try!(self.print_expr(test));
+                try!(self.print_expr(&**test));
                 try!(space(&mut self.s));
-                try!(self.print_block(blk));
+                try!(self.print_block(&**blk));
             }
-            ast::ExprForLoop(pat, iter, blk, opt_ident) => {
+            ast::ExprForLoop(ref pat, ref iter, ref blk, opt_ident) => {
                 for ident in opt_ident.iter() {
                     try!(word(&mut self.s, "'"));
                     try!(self.print_ident(*ident));
                     try!(self.word_space(":"));
                 }
                 try!(self.head("for"));
-                try!(self.print_pat(pat));
+                try!(self.print_pat(&**pat));
                 try!(space(&mut self.s));
                 try!(self.word_space("in"));
-                try!(self.print_expr(iter));
+                try!(self.print_expr(&**iter));
                 try!(space(&mut self.s));
-                try!(self.print_block(blk));
+                try!(self.print_block(&**blk));
             }
-            ast::ExprLoop(blk, opt_ident) => {
+            ast::ExprLoop(ref blk, opt_ident) => {
                 for ident in opt_ident.iter() {
                     try!(word(&mut self.s, "'"));
                     try!(self.print_ident(*ident));
@@ -1344,13 +1345,13 @@ impl<'a> State<'a> {
                 }
                 try!(self.head("loop"));
                 try!(space(&mut self.s));
-                try!(self.print_block(blk));
+                try!(self.print_block(&**blk));
             }
-            ast::ExprMatch(expr, ref arms) => {
+            ast::ExprMatch(ref expr, ref arms) => {
                 try!(self.cbox(indent_unit));
                 try!(self.ibox(4));
                 try!(self.word_nbsp("match"));
-                try!(self.print_expr(expr));
+                try!(self.print_expr(&**expr));
                 try!(space(&mut self.s));
                 try!(self.bopen());
                 let len = arms.len();
@@ -1371,13 +1372,13 @@ impl<'a> State<'a> {
                             try!(space(&mut self.s));
                             try!(self.word_space("|"));
                         }
-                        try!(self.print_pat(*p));
+                        try!(self.print_pat(&**p));
                     }
                     try!(space(&mut self.s));
                     match arm.guard {
-                        Some(e) => {
+                        Some(ref e) => {
                             try!(self.word_space("if"));
-                            try!(self.print_expr(e));
+                            try!(self.print_expr(&**e));
                             try!(space(&mut self.s));
                         }
                         None => ()
@@ -1385,16 +1386,17 @@ impl<'a> State<'a> {
                     try!(self.word_space("=>"));
 
                     match arm.body.node {
-                        ast::ExprBlock(blk) => {
+                        ast::ExprBlock(ref blk) => {
                             // the block will close the pattern's ibox
-                            try!(self.print_block_unclosed_indent(blk, indent_unit));
+                            try!(self.print_block_unclosed_indent(&**blk,
+                                                                  indent_unit));
                         }
                         _ => {
                             try!(self.end()); // close the ibox for the pattern
-                            try!(self.print_expr(arm.body));
+                            try!(self.print_expr(&*arm.body));
                         }
                     }
-                    if !expr_is_simple_block(expr)
+                    if !expr_is_simple_block(expr.clone())
                         && i < len - 1 {
                         try!(word(&mut self.s, ","));
                     }
@@ -1402,27 +1404,27 @@ impl<'a> State<'a> {
                 }
                 try!(self.bclose_(expr.span, indent_unit));
             }
-            ast::ExprFnBlock(decl, body) => {
+            ast::ExprFnBlock(ref decl, ref body) => {
                 // in do/for blocks we don't want to show an empty
                 // argument list, but at this point we don't know which
                 // we are inside.
                 //
                 // if !decl.inputs.is_empty() {
-                try!(self.print_fn_block_args(decl));
+                try!(self.print_fn_block_args(&**decl));
                 try!(space(&mut self.s));
                 // }
 
                 if !body.stmts.is_empty() || !body.expr.is_some() {
-                    try!(self.print_block_unclosed(body));
+                    try!(self.print_block_unclosed(&**body));
                 } else {
                     // we extract the block, so as not to create another set of boxes
                     match body.expr.unwrap().node {
-                        ast::ExprBlock(blk) => {
-                            try!(self.print_block_unclosed(blk));
+                        ast::ExprBlock(ref blk) => {
+                            try!(self.print_block_unclosed(&**blk));
                         }
                         _ => {
                             // this is a bare expression
-                            try!(self.print_expr(body.expr.unwrap()));
+                            try!(self.print_expr(&*body.expr.unwrap()));
                             try!(self.end()); // need to close a box
                         }
                     }
@@ -1432,25 +1434,25 @@ impl<'a> State<'a> {
                 // empty box to satisfy the close.
                 try!(self.ibox(0));
             }
-            ast::ExprProc(decl, body) => {
+            ast::ExprProc(ref decl, ref body) => {
                 // in do/for blocks we don't want to show an empty
                 // argument list, but at this point we don't know which
                 // we are inside.
                 //
                 // if !decl.inputs.is_empty() {
-                try!(self.print_proc_args(decl));
+                try!(self.print_proc_args(&**decl));
                 try!(space(&mut self.s));
                 // }
                 assert!(body.stmts.is_empty());
                 assert!(body.expr.is_some());
                 // we extract the block, so as not to create another set of boxes
                 match body.expr.unwrap().node {
-                    ast::ExprBlock(blk) => {
-                        try!(self.print_block_unclosed(blk));
+                    ast::ExprBlock(ref blk) => {
+                        try!(self.print_block_unclosed(&**blk));
                     }
                     _ => {
                         // this is a bare expression
-                        try!(self.print_expr(body.expr.unwrap()));
+                        try!(self.print_expr(&*body.expr.unwrap()));
                         try!(self.end()); // need to close a box
                     }
                 }
@@ -1459,28 +1461,28 @@ impl<'a> State<'a> {
                 // empty box to satisfy the close.
                 try!(self.ibox(0));
             }
-            ast::ExprBlock(blk) => {
+            ast::ExprBlock(ref blk) => {
                 // containing cbox, will be closed by print-block at }
                 try!(self.cbox(indent_unit));
                 // head-box, will be closed by print-block after {
                 try!(self.ibox(0u));
-                try!(self.print_block(blk));
+                try!(self.print_block(&**blk));
             }
-            ast::ExprAssign(lhs, rhs) => {
-                try!(self.print_expr(lhs));
+            ast::ExprAssign(ref lhs, ref rhs) => {
+                try!(self.print_expr(&**lhs));
                 try!(space(&mut self.s));
                 try!(self.word_space("="));
-                try!(self.print_expr(rhs));
+                try!(self.print_expr(&**rhs));
             }
-            ast::ExprAssignOp(op, lhs, rhs) => {
-                try!(self.print_expr(lhs));
+            ast::ExprAssignOp(op, ref lhs, ref rhs) => {
+                try!(self.print_expr(&**lhs));
                 try!(space(&mut self.s));
                 try!(word(&mut self.s, ast_util::binop_to_str(op)));
                 try!(self.word_space("="));
-                try!(self.print_expr(rhs));
+                try!(self.print_expr(&**rhs));
             }
-            ast::ExprField(expr, id, ref tys) => {
-                try!(self.print_expr(expr));
+            ast::ExprField(ref expr, id, ref tys) => {
+                try!(self.print_expr(&**expr));
                 try!(word(&mut self.s, "."));
                 try!(self.print_ident(id));
                 if tys.len() > 0u {
@@ -1491,10 +1493,10 @@ impl<'a> State<'a> {
                     try!(word(&mut self.s, ">"));
                 }
             }
-            ast::ExprIndex(expr, index) => {
-                try!(self.print_expr(expr));
+            ast::ExprIndex(ref expr, ref index) => {
+                try!(self.print_expr(&**expr));
                 try!(word(&mut self.s, "["));
-                try!(self.print_expr(index));
+                try!(self.print_expr(&**index));
                 try!(word(&mut self.s, "]"));
             }
             ast::ExprPath(ref path) => try!(self.print_path(path, true)),
@@ -1516,12 +1518,12 @@ impl<'a> State<'a> {
                     try!(space(&mut self.s))
                 }
             }
-            ast::ExprRet(result) => {
+            ast::ExprRet(ref result) => {
                 try!(word(&mut self.s, "return"));
-                match result {
-                    Some(expr) => {
+                match *result {
+                    Some(ref expr) => {
                         try!(word(&mut self.s, " "));
-                        try!(self.print_expr(expr));
+                        try!(self.print_expr(&**expr));
                     }
                     _ => ()
                 }
@@ -1536,20 +1538,22 @@ impl<'a> State<'a> {
                 try!(self.print_string(a.asm.get(), a.asm_str_style));
                 try!(self.word_space(":"));
 
-                try!(self.commasep(Inconsistent, a.outputs.as_slice(), |s, &(ref co, o)| {
+                try!(self.commasep(Inconsistent, a.outputs.as_slice(),
+                                   |s, &(ref co, ref o)| {
                     try!(s.print_string(co.get(), ast::CookedStr));
                     try!(s.popen());
-                    try!(s.print_expr(o));
+                    try!(s.print_expr(&**o));
                     try!(s.pclose());
                     Ok(())
                 }));
                 try!(space(&mut self.s));
                 try!(self.word_space(":"));
 
-                try!(self.commasep(Inconsistent, a.inputs.as_slice(), |s, &(ref co, o)| {
+                try!(self.commasep(Inconsistent, a.inputs.as_slice(),
+                                   |s, &(ref co, ref o)| {
                     try!(s.print_string(co.get(), ast::CookedStr));
                     try!(s.popen());
-                    try!(s.print_expr(o));
+                    try!(s.print_expr(&**o));
                     try!(s.pclose());
                     Ok(())
                 }));
@@ -1560,9 +1564,9 @@ impl<'a> State<'a> {
                 try!(self.pclose());
             }
             ast::ExprMac(ref m) => try!(self.print_mac(m)),
-            ast::ExprParen(e) => {
+            ast::ExprParen(ref e) => {
                 try!(self.popen());
-                try!(self.print_expr(e));
+                try!(self.print_expr(&**e));
                 try!(self.pclose());
             }
         }
@@ -1571,12 +1575,12 @@ impl<'a> State<'a> {
     }
 
     pub fn print_local_decl(&mut self, loc: &ast::Local) -> IoResult<()> {
-        try!(self.print_pat(loc.pat));
+        try!(self.print_pat(&*loc.pat));
         match loc.ty.node {
             ast::TyInfer => Ok(()),
             _ => {
                 try!(self.word_space(":"));
-                self.print_type(loc.ty)
+                self.print_type(&*loc.ty)
             }
         }
     }
@@ -1584,25 +1588,25 @@ impl<'a> State<'a> {
     pub fn print_decl(&mut self, decl: &ast::Decl) -> IoResult<()> {
         try!(self.maybe_print_comment(decl.span.lo));
         match decl.node {
-            ast::DeclLocal(loc) => {
+            ast::DeclLocal(ref loc) => {
                 try!(self.space_if_not_bol());
                 try!(self.ibox(indent_unit));
                 try!(self.word_nbsp("let"));
 
                 try!(self.ibox(indent_unit));
-                try!(self.print_local_decl(loc));
+                try!(self.print_local_decl(&**loc));
                 try!(self.end());
                 match loc.init {
-                    Some(init) => {
+                    Some(ref init) => {
                         try!(self.nbsp());
                         try!(self.word_space("="));
-                        try!(self.print_expr(init));
+                        try!(self.print_expr(&**init));
                     }
                     _ => {}
                 }
                 self.end()
             }
-            ast::DeclItem(item) => self.print_item(item)
+            ast::DeclItem(ref item) => self.print_item(&**item)
         }
     }
 
@@ -1709,9 +1713,9 @@ impl<'a> State<'a> {
                 }
                 try!(self.print_path(path, true));
                 match sub {
-                    Some(p) => {
+                    Some(ref p) => {
                         try!(word(&mut self.s, "@"));
-                        try!(self.print_pat(p));
+                        try!(self.print_pat(&**p));
                     }
                     None => ()
                 }
@@ -1724,7 +1728,7 @@ impl<'a> State<'a> {
                         if !args.is_empty() {
                             try!(self.popen());
                             try!(self.commasep(Inconsistent, args.as_slice(),
-                                              |s, &p| s.print_pat(p)));
+                                              |s, p| s.print_pat(&**p)));
                             try!(self.pclose());
                         }
                     }
@@ -1739,7 +1743,7 @@ impl<'a> State<'a> {
                         try!(s.cbox(indent_unit));
                         try!(s.print_ident(f.ident));
                         try!(s.word_space(":"));
-                        try!(s.print_pat(f.pat));
+                        try!(s.print_pat(&*f.pat));
                         s.end()
                     },
                     |f| f.pat.span));
@@ -1753,46 +1757,46 @@ impl<'a> State<'a> {
                 try!(self.popen());
                 try!(self.commasep(Inconsistent,
                                    elts.as_slice(),
-                                   |s, &p| s.print_pat(p)));
+                                   |s, p| s.print_pat(&**p)));
                 if elts.len() == 1 {
                     try!(word(&mut self.s, ","));
                 }
                 try!(self.pclose());
             }
-            ast::PatBox(inner) => {
+            ast::PatBox(ref inner) => {
                 try!(word(&mut self.s, "box "));
-                try!(self.print_pat(inner));
+                try!(self.print_pat(&**inner));
             }
-            ast::PatRegion(inner) => {
+            ast::PatRegion(ref inner) => {
                 try!(word(&mut self.s, "&"));
-                try!(self.print_pat(inner));
+                try!(self.print_pat(&**inner));
             }
-            ast::PatLit(e) => try!(self.print_expr(e)),
-            ast::PatRange(begin, end) => {
-                try!(self.print_expr(begin));
+            ast::PatLit(ref e) => try!(self.print_expr(&**e)),
+            ast::PatRange(ref begin, ref end) => {
+                try!(self.print_expr(&**begin));
                 try!(space(&mut self.s));
                 try!(word(&mut self.s, ".."));
-                try!(self.print_expr(end));
+                try!(self.print_expr(&**end));
             }
             ast::PatVec(ref before, slice, ref after) => {
                 try!(word(&mut self.s, "["));
                 try!(self.commasep(Inconsistent,
                                    before.as_slice(),
-                                   |s, &p| s.print_pat(p)));
-                for &p in slice.iter() {
+                                   |s, p| s.print_pat(&**p)));
+                for p in slice.iter() {
                     if !before.is_empty() { try!(self.word_space(",")); }
-                    match *p {
+                    match **p {
                         ast::Pat { node: ast::PatWildMulti, .. } => {
                             // this case is handled by print_pat
                         }
                         _ => try!(word(&mut self.s, "..")),
                     }
-                    try!(self.print_pat(p));
+                    try!(self.print_pat(&**p));
                     if !after.is_empty() { try!(self.word_space(",")); }
                 }
                 try!(self.commasep(Inconsistent,
                                    after.as_slice(),
-                                   |s, &p| s.print_pat(p)));
+                                   |s, p| s.print_pat(&**p)));
                 try!(word(&mut self.s, "]"));
             }
             ast::PatMac(ref m) => try!(self.print_mac(m)),
@@ -1888,7 +1892,7 @@ impl<'a> State<'a> {
             _ => {
                 try!(self.space_if_not_bol());
                 try!(self.word_space("->"));
-                self.print_type(decl.output)
+                self.print_type(&*decl.output)
             }
         }
     }
@@ -1904,7 +1908,7 @@ impl<'a> State<'a> {
             _ => {
                 try!(self.space_if_not_bol());
                 try!(self.word_space("->"));
-                try!(self.print_type(decl.output));
+                try!(self.print_type(&*decl.output));
             }
         }
 
@@ -1922,7 +1926,7 @@ impl<'a> State<'a> {
             _ => {
                 try!(self.space_if_not_bol());
                 try!(self.word_space("->"));
-                try!(self.print_type(decl.output));
+                try!(self.print_type(&*decl.output));
             }
         }
 
@@ -2014,10 +2018,10 @@ impl<'a> State<'a> {
                         try!(s.print_ident(param.ident));
                         try!(s.print_bounds(&None, &param.bounds, false));
                         match param.default {
-                            Some(default) => {
+                            Some(ref default) => {
                                 try!(space(&mut s.s));
                                 try!(s.word_space("="));
-                                s.print_type(default)
+                                s.print_type(&**default)
                             }
                             _ => Ok(())
                         }
@@ -2045,7 +2049,7 @@ impl<'a> State<'a> {
                 try!(self.popen());
                 try!(self.commasep(Consistent,
                                    items.as_slice(),
-                                   |s, &i| s.print_meta_item(i)));
+                                   |s, i| s.print_meta_item(&**i)));
                 try!(self.pclose());
             }
         }
@@ -2103,7 +2107,7 @@ impl<'a> State<'a> {
 
             ast::ViewItemUse(ref vp) => {
                 try!(self.head("use"));
-                try!(self.print_view_path(*vp));
+                try!(self.print_view_path(&**vp));
             }
         }
         try!(word(&mut self.s, ";"));
@@ -2121,13 +2125,13 @@ impl<'a> State<'a> {
 
     pub fn print_mt(&mut self, mt: &ast::MutTy) -> IoResult<()> {
         try!(self.print_mutability(mt.mutbl));
-        self.print_type(mt.ty)
+        self.print_type(&*mt.ty)
     }
 
     pub fn print_arg(&mut self, input: &ast::Arg) -> IoResult<()> {
         try!(self.ibox(indent_unit));
         match input.ty.node {
-            ast::TyInfer => try!(self.print_pat(input.pat)),
+            ast::TyInfer => try!(self.print_pat(&*input.pat)),
             _ => {
                 match input.pat.node {
                     ast::PatIdent(_, ref path, _) if
@@ -2137,12 +2141,12 @@ impl<'a> State<'a> {
                         // Do nothing.
                     }
                     _ => {
-                        try!(self.print_pat(input.pat));
+                        try!(self.print_pat(&*input.pat));
                         try!(word(&mut self.s, ":"));
                         try!(space(&mut self.s));
                     }
                 }
-                try!(self.print_type(input.ty));
+                try!(self.print_type(&*input.ty));
             }
         }
         self.end()
@@ -2229,7 +2233,7 @@ impl<'a> State<'a> {
                 if decl.cf == ast::NoReturn {
                     try!(self.word_nbsp("!"));
                 } else {
-                    try!(self.print_type(decl.output));
+                    try!(self.print_type(&*decl.output));
                 }
                 try!(self.end());
             }
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index a306ebba96a..40f237d3267 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -15,6 +15,8 @@ use codemap::Span;
 use parse;
 use owned_slice::OwnedSlice;
 
+use std::gc::Gc;
+
 // Context-passing AST walker. Each overridden visit method has full control
 // over what happens with its node, it can do its own traversal of the node's
 // children (potentially passing in different contexts to each), call
@@ -135,9 +137,9 @@ pub fn walk_inlined_item<E: Clone, V: Visitor<E>>(visitor: &mut V,
                                                   item: &ast::InlinedItem,
                                                   env: E) {
     match *item {
-        IIItem(i) => visitor.visit_item(i, env),
-        IIForeign(i) => visitor.visit_foreign_item(i, env),
-        IIMethod(_, _, m) => walk_method_helper(visitor, m, env),
+        IIItem(i) => visitor.visit_item(&*i, env),
+        IIForeign(i) => visitor.visit_foreign_item(&*i, env),
+        IIMethod(_, _, m) => walk_method_helper(visitor, &*m, env),
     }
 }
 
@@ -155,7 +157,7 @@ pub fn walk_mod<E: Clone, V: Visitor<E>>(visitor: &mut V, module: &Mod, env: E)
     }
 
     for item in module.items.iter() {
-        visitor.visit_item(*item, env.clone())
+        visitor.visit_item(&**item, env.clone())
     }
 }
 
@@ -188,11 +190,11 @@ pub fn walk_view_item<E: Clone, V: Visitor<E>>(visitor: &mut V, vi: &ViewItem, e
 }
 
 pub fn walk_local<E: Clone, V: Visitor<E>>(visitor: &mut V, local: &Local, env: E) {
-    visitor.visit_pat(local.pat, env.clone());
-    visitor.visit_ty(local.ty, env.clone());
+    visitor.visit_pat(&*local.pat, env.clone());
+    visitor.visit_ty(&*local.ty, env.clone());
     match local.init {
         None => {}
-        Some(initializer) => visitor.visit_expr(initializer, env),
+        Some(initializer) => visitor.visit_expr(&*initializer, env),
     }
 }
 
@@ -219,13 +221,13 @@ pub fn walk_item<E: Clone, V: Visitor<E>>(visitor: &mut V, item: &Item, env: E)
     visitor.visit_ident(item.span, item.ident, env.clone());
     match item.node {
         ItemStatic(typ, _, expr) => {
-            visitor.visit_ty(typ, env.clone());
-            visitor.visit_expr(expr, env.clone());
+            visitor.visit_ty(&*typ, env.clone());
+            visitor.visit_expr(&*expr, env);
         }
         ItemFn(declaration, fn_style, abi, ref generics, body) => {
             visitor.visit_fn(&FkItemFn(item.ident, generics, fn_style, abi),
-                             declaration,
-                             body,
+                             &*declaration,
+                             &*body,
                              item.span,
                              item.id,
                              env.clone())
@@ -238,12 +240,12 @@ pub fn walk_item<E: Clone, V: Visitor<E>>(visitor: &mut V, item: &Item, env: E)
                 visitor.visit_view_item(view_item, env.clone())
             }
             for foreign_item in foreign_module.items.iter() {
-                visitor.visit_foreign_item(*foreign_item, env.clone())
+                visitor.visit_foreign_item(&**foreign_item, env.clone())
             }
         }
         ItemTy(typ, ref type_parameters) => {
-            visitor.visit_ty(typ, env.clone());
-            visitor.visit_generics(type_parameters, env.clone())
+            visitor.visit_ty(&*typ, env.clone());
+            visitor.visit_generics(type_parameters, env)
         }
         ItemEnum(ref enum_definition, ref type_parameters) => {
             visitor.visit_generics(type_parameters, env.clone());
@@ -259,14 +261,14 @@ pub fn walk_item<E: Clone, V: Visitor<E>>(visitor: &mut V, item: &Item, env: E)
                                                                    trait_reference, env.clone()),
                 None => ()
             }
-            visitor.visit_ty(typ, env.clone());
+            visitor.visit_ty(&*typ, env.clone());
             for method in methods.iter() {
-                walk_method_helper(visitor, *method, env.clone())
+                walk_method_helper(visitor, &**method, env.clone())
             }
         }
-        ItemStruct(struct_definition, ref generics) => {
+        ItemStruct(ref struct_definition, ref generics) => {
             visitor.visit_generics(generics, env.clone());
-            visitor.visit_struct_def(struct_definition,
+            visitor.visit_struct_def(&**struct_definition,
                                      item.ident,
                                      generics,
                                      item.id,
@@ -295,7 +297,7 @@ pub fn walk_enum_def<E: Clone, V:Visitor<E>>(visitor: &mut V,
                                              generics: &Generics,
                                              env: E) {
     for &variant in enum_definition.variants.iter() {
-        visitor.visit_variant(variant, generics, env.clone());
+        visitor.visit_variant(&*variant, generics, env.clone());
     }
 }
 
@@ -308,11 +310,11 @@ pub fn walk_variant<E: Clone, V: Visitor<E>>(visitor: &mut V,
     match variant.node.kind {
         TupleVariantKind(ref variant_arguments) => {
             for variant_argument in variant_arguments.iter() {
-                visitor.visit_ty(variant_argument.ty, env.clone())
+                visitor.visit_ty(&*variant_argument.ty, env.clone())
             }
         }
-        StructVariantKind(struct_definition) => {
-            visitor.visit_struct_def(struct_definition,
+        StructVariantKind(ref struct_definition) => {
+            visitor.visit_struct_def(&**struct_definition,
                                      variant.node.name,
                                      generics,
                                      variant.node.id,
@@ -320,7 +322,7 @@ pub fn walk_variant<E: Clone, V: Visitor<E>>(visitor: &mut V,
         }
     }
     match variant.node.disr_expr {
-        Some(expr) => visitor.visit_expr(expr, env.clone()),
+        Some(ref expr) => visitor.visit_expr(&**expr, env.clone()),
         None => ()
     }
     for attr in variant.node.attrs.iter() {
@@ -335,25 +337,25 @@ pub fn skip_ty<E, V: Visitor<E>>(_: &mut V, _: &Ty, _: E) {
 pub fn walk_ty<E: Clone, V: Visitor<E>>(visitor: &mut V, typ: &Ty, env: E) {
     match typ.node {
         TyUniq(ty) | TyVec(ty) | TyBox(ty) => {
-            visitor.visit_ty(ty, env)
+            visitor.visit_ty(&*ty, env)
         }
         TyPtr(ref mutable_type) => {
-            visitor.visit_ty(mutable_type.ty, env)
+            visitor.visit_ty(&*mutable_type.ty, env)
         }
         TyRptr(ref lifetime, ref mutable_type) => {
             visitor.visit_opt_lifetime_ref(typ.span, lifetime, env.clone());
-            visitor.visit_ty(mutable_type.ty, env)
+            visitor.visit_ty(&*mutable_type.ty, env)
         }
         TyTup(ref tuple_element_types) => {
             for &tuple_element_type in tuple_element_types.iter() {
-                visitor.visit_ty(tuple_element_type, env.clone())
+                visitor.visit_ty(&*tuple_element_type, env.clone())
             }
         }
         TyClosure(ref function_declaration, ref region) => {
             for argument in function_declaration.decl.inputs.iter() {
-                visitor.visit_ty(argument.ty, env.clone())
+                visitor.visit_ty(&*argument.ty, env.clone())
             }
-            visitor.visit_ty(function_declaration.decl.output, env.clone());
+            visitor.visit_ty(&*function_declaration.decl.output, env.clone());
             for bounds in function_declaration.bounds.iter() {
                 walk_ty_param_bounds(visitor, bounds, env.clone())
             }
@@ -366,9 +368,9 @@ pub fn walk_ty<E: Clone, V: Visitor<E>>(visitor: &mut V, typ: &Ty, env: E) {
         }
         TyProc(ref function_declaration) => {
             for argument in function_declaration.decl.inputs.iter() {
-                visitor.visit_ty(argument.ty, env.clone())
+                visitor.visit_ty(&*argument.ty, env.clone())
             }
-            visitor.visit_ty(function_declaration.decl.output, env.clone());
+            visitor.visit_ty(&*function_declaration.decl.output, env.clone());
             for bounds in function_declaration.bounds.iter() {
                 walk_ty_param_bounds(visitor, bounds, env.clone())
             }
@@ -377,9 +379,9 @@ pub fn walk_ty<E: Clone, V: Visitor<E>>(visitor: &mut V, typ: &Ty, env: E) {
         }
         TyBareFn(ref function_declaration) => {
             for argument in function_declaration.decl.inputs.iter() {
-                visitor.visit_ty(argument.ty, env.clone())
+                visitor.visit_ty(&*argument.ty, env.clone())
             }
-            visitor.visit_ty(function_declaration.decl.output, env.clone());
+            visitor.visit_ty(&*function_declaration.decl.output, env.clone());
             walk_lifetime_decls(visitor, &function_declaration.lifetimes,
                                 env.clone());
         }
@@ -395,12 +397,12 @@ pub fn walk_ty<E: Clone, V: Visitor<E>>(visitor: &mut V, typ: &Ty, env: E) {
                 walk_ty_param_bounds(visitor, bounds, env.clone())
             }
         }
-        TyFixedLengthVec(ty, expression) => {
-            visitor.visit_ty(ty, env.clone());
-            visitor.visit_expr(expression, env)
+        TyFixedLengthVec(ref ty, ref expression) => {
+            visitor.visit_ty(&**ty, env.clone());
+            visitor.visit_expr(&**expression, env)
         }
-        TyTypeof(expression) => {
-            visitor.visit_expr(expression, env)
+        TyTypeof(ref expression) => {
+            visitor.visit_expr(&**expression, env)
         }
         TyNil | TyBot | TyInfer => {}
     }
@@ -418,8 +420,8 @@ pub fn walk_path<E: Clone, V: Visitor<E>>(visitor: &mut V, path: &Path, env: E)
     for segment in path.segments.iter() {
         visitor.visit_ident(path.span, segment.identifier, env.clone());
 
-        for &typ in segment.types.iter() {
-            visitor.visit_ty(typ, env.clone());
+        for typ in segment.types.iter() {
+            visitor.visit_ty(&**typ, env.clone());
         }
         for lifetime in segment.lifetimes.iter() {
             visitor.visit_lifetime_ref(lifetime, env.clone());
@@ -433,47 +435,47 @@ pub fn walk_pat<E: Clone, V: Visitor<E>>(visitor: &mut V, pattern: &Pat, env: E)
             visitor.visit_path(path, pattern.id, env.clone());
             for children in children.iter() {
                 for child in children.iter() {
-                    visitor.visit_pat(*child, env.clone())
+                    visitor.visit_pat(&**child, env.clone())
                 }
             }
         }
         PatStruct(ref path, ref fields, _) => {
             visitor.visit_path(path, pattern.id, env.clone());
             for field in fields.iter() {
-                visitor.visit_pat(field.pat, env.clone())
+                visitor.visit_pat(&*field.pat, env.clone())
             }
         }
         PatTup(ref tuple_elements) => {
             for tuple_element in tuple_elements.iter() {
-                visitor.visit_pat(*tuple_element, env.clone())
+                visitor.visit_pat(&**tuple_element, env.clone())
             }
         }
-        PatBox(subpattern) |
-        PatRegion(subpattern) => {
-            visitor.visit_pat(subpattern, env)
+        PatBox(ref subpattern) |
+        PatRegion(ref subpattern) => {
+            visitor.visit_pat(&**subpattern, env)
         }
         PatIdent(_, ref path, ref optional_subpattern) => {
             visitor.visit_path(path, pattern.id, env.clone());
             match *optional_subpattern {
                 None => {}
-                Some(subpattern) => visitor.visit_pat(subpattern, env),
+                Some(ref subpattern) => visitor.visit_pat(&**subpattern, env),
             }
         }
-        PatLit(expression) => visitor.visit_expr(expression, env),
-        PatRange(lower_bound, upper_bound) => {
-            visitor.visit_expr(lower_bound, env.clone());
-            visitor.visit_expr(upper_bound, env)
+        PatLit(ref expression) => visitor.visit_expr(&**expression, env),
+        PatRange(ref lower_bound, ref upper_bound) => {
+            visitor.visit_expr(&**lower_bound, env.clone());
+            visitor.visit_expr(&**upper_bound, env)
         }
         PatWild | PatWildMulti => (),
         PatVec(ref prepattern, ref slice_pattern, ref postpatterns) => {
             for prepattern in prepattern.iter() {
-                visitor.visit_pat(*prepattern, env.clone())
+                visitor.visit_pat(&**prepattern, env.clone())
             }
             for slice_pattern in slice_pattern.iter() {
-                visitor.visit_pat(*slice_pattern, env.clone())
+                visitor.visit_pat(&**slice_pattern, env.clone())
             }
             for postpattern in postpatterns.iter() {
-                visitor.visit_pat(*postpattern, env.clone())
+                visitor.visit_pat(&**postpattern, env.clone())
             }
         }
         PatMac(ref macro) => visitor.visit_mac(macro, env),
@@ -486,8 +488,8 @@ pub fn walk_foreign_item<E: Clone, V: Visitor<E>>(visitor: &mut V,
     visitor.visit_ident(foreign_item.span, foreign_item.ident, env.clone());
 
     match foreign_item.node {
-        ForeignItemFn(function_declaration, ref generics) => {
-            walk_fn_decl(visitor, function_declaration, env.clone());
+        ForeignItemFn(ref function_declaration, ref generics) => {
+            walk_fn_decl(visitor, &**function_declaration, env.clone());
             visitor.visit_generics(generics, env.clone())
         }
         ForeignItemStatic(typ, _) => visitor.visit_ty(typ, env.clone()),
@@ -525,7 +527,7 @@ pub fn walk_generics<E: Clone, V: Visitor<E>>(visitor: &mut V,
     for type_parameter in generics.ty_params.iter() {
         walk_ty_param_bounds(visitor, &type_parameter.bounds, env.clone());
         match type_parameter.default {
-            Some(ty) => visitor.visit_ty(ty, env.clone()),
+            Some(ref ty) => visitor.visit_ty(&**ty, env.clone()),
             None => {}
         }
     }
@@ -536,10 +538,10 @@ pub fn walk_fn_decl<E: Clone, V: Visitor<E>>(visitor: &mut V,
                                              function_declaration: &FnDecl,
                                              env: E) {
     for argument in function_declaration.inputs.iter() {
-        visitor.visit_pat(argument.pat, env.clone());
-        visitor.visit_ty(argument.ty, env.clone())
+        visitor.visit_pat(&*argument.pat, env.clone());
+        visitor.visit_ty(&*argument.ty, env.clone())
     }
-    visitor.visit_ty(function_declaration.output, env)
+    visitor.visit_ty(&*function_declaration.output, env)
 }
 
 // Note: there is no visit_method() method in the visitor, instead override
@@ -551,8 +553,8 @@ pub fn walk_method_helper<E: Clone, V: Visitor<E>>(visitor: &mut V,
                                                    env: E) {
     visitor.visit_ident(method.span, method.ident, env.clone());
     visitor.visit_fn(&FkMethod(method.ident, &method.generics, method),
-                     method.decl,
-                     method.body,
+                     &*method.decl,
+                     &*method.body,
                      method.span,
                      method.id,
                      env.clone());
@@ -590,7 +592,7 @@ pub fn walk_ty_method<E: Clone, V: Visitor<E>>(visitor: &mut V,
     visitor.visit_ident(method_type.span, method_type.ident, env.clone());
     visitor.visit_explicit_self(&method_type.explicit_self, env.clone());
     for argument_type in method_type.decl.inputs.iter() {
-        visitor.visit_ty(argument_type.ty, env.clone())
+        visitor.visit_ty(&*argument_type.ty, env.clone())
     }
     visitor.visit_generics(&method_type.generics, env.clone());
     visitor.visit_ty(method_type.decl.output, env.clone());
@@ -606,7 +608,7 @@ pub fn walk_trait_method<E: Clone, V: Visitor<E>>(visitor: &mut V,
         Required(ref method_type) => {
             visitor.visit_ty_method(method_type, env)
         }
-        Provided(method) => walk_method_helper(visitor, method, env),
+        Provided(ref method) => walk_method_helper(visitor, &**method, env),
     }
 }
 
@@ -614,7 +616,7 @@ pub fn walk_struct_def<E: Clone, V: Visitor<E>>(visitor: &mut V,
                                                 struct_definition: &StructDef,
                                                 env: E) {
     match struct_definition.super_struct {
-        Some(t) => visitor.visit_ty(t, env.clone()),
+        Some(ref t) => visitor.visit_ty(&**t, env.clone()),
         None => {},
     }
     for field in struct_definition.fields.iter() {
@@ -644,16 +646,16 @@ pub fn walk_block<E: Clone, V: Visitor<E>>(visitor: &mut V, block: &Block, env:
         visitor.visit_view_item(view_item, env.clone())
     }
     for statement in block.stmts.iter() {
-        visitor.visit_stmt(*statement, env.clone())
+        visitor.visit_stmt(&**statement, env.clone())
     }
     walk_expr_opt(visitor, block.expr, env)
 }
 
 pub fn walk_stmt<E: Clone, V: Visitor<E>>(visitor: &mut V, statement: &Stmt, env: E) {
     match statement.node {
-        StmtDecl(declaration, _) => visitor.visit_decl(declaration, env),
-        StmtExpr(expression, _) | StmtSemi(expression, _) => {
-            visitor.visit_expr(expression, env)
+        StmtDecl(ref declaration, _) => visitor.visit_decl(&**declaration, env),
+        StmtExpr(ref expression, _) | StmtSemi(ref expression, _) => {
+            visitor.visit_expr(&**expression, env)
         }
         StmtMac(ref macro, _) => visitor.visit_mac(macro, env),
     }
@@ -661,25 +663,25 @@ pub fn walk_stmt<E: Clone, V: Visitor<E>>(visitor: &mut V, statement: &Stmt, env
 
 pub fn walk_decl<E: Clone, V: Visitor<E>>(visitor: &mut V, declaration: &Decl, env: E) {
     match declaration.node {
-        DeclLocal(ref local) => visitor.visit_local(*local, env),
-        DeclItem(item) => visitor.visit_item(item, env),
+        DeclLocal(ref local) => visitor.visit_local(&**local, env),
+        DeclItem(ref item) => visitor.visit_item(&**item, env),
     }
 }
 
 pub fn walk_expr_opt<E: Clone, V: Visitor<E>>(visitor: &mut V,
-                                              optional_expression: Option<@Expr>,
+                                              optional_expression: Option<Gc<Expr>>,
                                               env: E) {
     match optional_expression {
         None => {}
-        Some(expression) => visitor.visit_expr(expression, env),
+        Some(ref expression) => visitor.visit_expr(&**expression, env),
     }
 }
 
 pub fn walk_exprs<E: Clone, V: Visitor<E>>(visitor: &mut V,
-                                           expressions: &[@Expr],
+                                           expressions: &[Gc<Expr>],
                                            env: E) {
     for expression in expressions.iter() {
-        visitor.visit_expr(*expression, env.clone())
+        visitor.visit_expr(&**expression, env.clone())
     }
 }
 
@@ -689,111 +691,111 @@ pub fn walk_mac<E, V: Visitor<E>>(_: &mut V, _: &Mac, _: E) {
 
 pub fn walk_expr<E: Clone, V: Visitor<E>>(visitor: &mut V, expression: &Expr, env: E) {
     match expression.node {
-        ExprVstore(subexpression, _) => {
-            visitor.visit_expr(subexpression, env.clone())
+        ExprVstore(ref subexpression, _) => {
+            visitor.visit_expr(&**subexpression, env.clone())
         }
-        ExprBox(place, subexpression) => {
-            visitor.visit_expr(place, env.clone());
-            visitor.visit_expr(subexpression, env.clone())
+        ExprBox(ref place, ref subexpression) => {
+            visitor.visit_expr(&**place, env.clone());
+            visitor.visit_expr(&**subexpression, env.clone())
         }
         ExprVec(ref subexpressions) => {
             walk_exprs(visitor, subexpressions.as_slice(), env.clone())
         }
-        ExprRepeat(element, count) => {
-            visitor.visit_expr(element, env.clone());
-            visitor.visit_expr(count, env.clone())
+        ExprRepeat(ref element, ref count) => {
+            visitor.visit_expr(&**element, env.clone());
+            visitor.visit_expr(&**count, env.clone())
         }
         ExprStruct(ref path, ref fields, optional_base) => {
             visitor.visit_path(path, expression.id, env.clone());
             for field in fields.iter() {
-                visitor.visit_expr(field.expr, env.clone())
+                visitor.visit_expr(&*field.expr, env.clone())
             }
             walk_expr_opt(visitor, optional_base, env.clone())
         }
         ExprTup(ref subexpressions) => {
             for subexpression in subexpressions.iter() {
-                visitor.visit_expr(*subexpression, env.clone())
+                visitor.visit_expr(&**subexpression, env.clone())
             }
         }
-        ExprCall(callee_expression, ref arguments) => {
+        ExprCall(ref callee_expression, ref arguments) => {
             for argument in arguments.iter() {
-                visitor.visit_expr(*argument, env.clone())
+                visitor.visit_expr(&**argument, env.clone())
             }
-            visitor.visit_expr(callee_expression, env.clone())
+            visitor.visit_expr(&**callee_expression, env.clone())
         }
         ExprMethodCall(_, ref types, ref arguments) => {
             walk_exprs(visitor, arguments.as_slice(), env.clone());
-            for &typ in types.iter() {
-                visitor.visit_ty(typ, env.clone())
+            for typ in types.iter() {
+                visitor.visit_ty(&**typ, env.clone())
             }
         }
-        ExprBinary(_, left_expression, right_expression) => {
-            visitor.visit_expr(left_expression, env.clone());
-            visitor.visit_expr(right_expression, env.clone())
+        ExprBinary(_, ref left_expression, ref right_expression) => {
+            visitor.visit_expr(&**left_expression, env.clone());
+            visitor.visit_expr(&**right_expression, env.clone())
         }
-        ExprAddrOf(_, subexpression) | ExprUnary(_, subexpression) => {
-            visitor.visit_expr(subexpression, env.clone())
+        ExprAddrOf(_, ref subexpression) | ExprUnary(_, ref subexpression) => {
+            visitor.visit_expr(&**subexpression, env.clone())
         }
         ExprLit(_) => {}
-        ExprCast(subexpression, typ) => {
-            visitor.visit_expr(subexpression, env.clone());
-            visitor.visit_ty(typ, env.clone())
+        ExprCast(ref subexpression, ref typ) => {
+            visitor.visit_expr(&**subexpression, env.clone());
+            visitor.visit_ty(&**typ, env.clone())
         }
-        ExprIf(head_expression, if_block, optional_else) => {
-            visitor.visit_expr(head_expression, env.clone());
-            visitor.visit_block(if_block, env.clone());
+        ExprIf(ref head_expression, ref if_block, optional_else) => {
+            visitor.visit_expr(&**head_expression, env.clone());
+            visitor.visit_block(&**if_block, env.clone());
             walk_expr_opt(visitor, optional_else, env.clone())
         }
-        ExprWhile(subexpression, block) => {
-            visitor.visit_expr(subexpression, env.clone());
-            visitor.visit_block(block, env.clone())
+        ExprWhile(ref subexpression, ref block) => {
+            visitor.visit_expr(&**subexpression, env.clone());
+            visitor.visit_block(&**block, env.clone())
         }
-        ExprForLoop(pattern, subexpression, block, _) => {
-            visitor.visit_pat(pattern, env.clone());
-            visitor.visit_expr(subexpression, env.clone());
-            visitor.visit_block(block, env.clone())
+        ExprForLoop(ref pattern, ref subexpression, ref block, _) => {
+            visitor.visit_pat(&**pattern, env.clone());
+            visitor.visit_expr(&**subexpression, env.clone());
+            visitor.visit_block(&**block, env.clone())
         }
-        ExprLoop(block, _) => visitor.visit_block(block, env.clone()),
-        ExprMatch(subexpression, ref arms) => {
-            visitor.visit_expr(subexpression, env.clone());
+        ExprLoop(ref block, _) => visitor.visit_block(&**block, env.clone()),
+        ExprMatch(ref subexpression, ref arms) => {
+            visitor.visit_expr(&**subexpression, env.clone());
             for arm in arms.iter() {
                 visitor.visit_arm(arm, env.clone())
             }
         }
-        ExprFnBlock(function_declaration, body) => {
+        ExprFnBlock(ref function_declaration, ref body) => {
             visitor.visit_fn(&FkFnBlock,
-                             function_declaration,
-                             body,
+                             &**function_declaration,
+                             &**body,
                              expression.span,
                              expression.id,
                              env.clone())
         }
-        ExprProc(function_declaration, body) => {
+        ExprProc(ref function_declaration, ref body) => {
             visitor.visit_fn(&FkFnBlock,
-                             function_declaration,
-                             body,
+                             &**function_declaration,
+                             &**body,
                              expression.span,
                              expression.id,
                              env.clone())
         }
-        ExprBlock(block) => visitor.visit_block(block, env.clone()),
-        ExprAssign(left_hand_expression, right_hand_expression) => {
-            visitor.visit_expr(right_hand_expression, env.clone());
-            visitor.visit_expr(left_hand_expression, env.clone())
+        ExprBlock(ref block) => visitor.visit_block(&**block, env.clone()),
+        ExprAssign(ref left_hand_expression, ref right_hand_expression) => {
+            visitor.visit_expr(&**right_hand_expression, env.clone());
+            visitor.visit_expr(&**left_hand_expression, env.clone())
         }
-        ExprAssignOp(_, left_expression, right_expression) => {
-            visitor.visit_expr(right_expression, env.clone());
-            visitor.visit_expr(left_expression, env.clone())
+        ExprAssignOp(_, ref left_expression, ref right_expression) => {
+            visitor.visit_expr(&**right_expression, env.clone());
+            visitor.visit_expr(&**left_expression, env.clone())
         }
-        ExprField(subexpression, _, ref types) => {
-            visitor.visit_expr(subexpression, env.clone());
-            for &typ in types.iter() {
-                visitor.visit_ty(typ, env.clone())
+        ExprField(ref subexpression, _, ref types) => {
+            visitor.visit_expr(&**subexpression, env.clone());
+            for typ in types.iter() {
+                visitor.visit_ty(&**typ, env.clone())
             }
         }
-        ExprIndex(main_expression, index_expression) => {
-            visitor.visit_expr(main_expression, env.clone());
-            visitor.visit_expr(index_expression, env.clone())
+        ExprIndex(ref main_expression, ref index_expression) => {
+            visitor.visit_expr(&**main_expression, env.clone());
+            visitor.visit_expr(&**index_expression, env.clone())
         }
         ExprPath(ref path) => {
             visitor.visit_path(path, expression.id, env.clone())
@@ -803,15 +805,15 @@ pub fn walk_expr<E: Clone, V: Visitor<E>>(visitor: &mut V, expression: &Expr, en
             walk_expr_opt(visitor, optional_expression, env.clone())
         }
         ExprMac(ref macro) => visitor.visit_mac(macro, env.clone()),
-        ExprParen(subexpression) => {
-            visitor.visit_expr(subexpression, env.clone())
+        ExprParen(ref subexpression) => {
+            visitor.visit_expr(&**subexpression, env.clone())
         }
         ExprInlineAsm(ref assembler) => {
-            for &(_, input) in assembler.inputs.iter() {
-                visitor.visit_expr(input, env.clone())
+            for &(_, ref input) in assembler.inputs.iter() {
+                visitor.visit_expr(&**input, env.clone())
             }
-            for &(_, output) in assembler.outputs.iter() {
-                visitor.visit_expr(output, env.clone())
+            for &(_, ref output) in assembler.outputs.iter() {
+                visitor.visit_expr(&**output, env.clone())
             }
         }
     }
@@ -821,7 +823,7 @@ pub fn walk_expr<E: Clone, V: Visitor<E>>(visitor: &mut V, expression: &Expr, en
 
 pub fn walk_arm<E: Clone, V: Visitor<E>>(visitor: &mut V, arm: &Arm, env: E) {
     for pattern in arm.pats.iter() {
-        visitor.visit_pat(*pattern, env.clone())
+        visitor.visit_pat(&**pattern, env.clone())
     }
     walk_expr_opt(visitor, arm.guard, env.clone());
     visitor.visit_expr(arm.body, env.clone());