about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-09-29 20:06:13 -0700
committerbors <bors@rust-lang.org>2013-09-29 20:06:13 -0700
commit80b6056f5d4ae6b527b36c502cc074c2518a3f7d (patch)
treeb67d74eca80fc1a56a42aab154f3fff431f66c97 /src
parent0fd8cb07c1fb1547ae50b5d3732e643286aff419 (diff)
parent7b18976f085a741322c735f0a4279816547d7eaf (diff)
auto merge of #9612 : alexcrichton/rust/rc-crate2, r=huonw
This patch exposes actual ownership of an `ast::Crate` structure so it's not implicitly copied and reference counted via `@`.

The main purpose for this patch was to get rid of the massive spike in memory during the start of the compiler (this can be seen on isrustfastyet). The reason that this spike exists is that during `phase_2` we're creating many copies of the crate by folding. Because these are reference counted, all instances of the old crates aren't dropped until the end of the function, which is why so much memory is accumulated.

This patch exposes true ownership of the crate, meaning that it will be destroyed ASAP when requested. There are no code changes except for dealing with actual ownership of the crate. The large spike is then avoided: http://i.imgur.com/IO3NENy.png

This shouldn't help our overall memory usage (that still is the highest at the end), but if we ever manage to bring that down it should help us not have a 1GB spike at the beginning of compilation.

(This was to un-stuck bors (hopefully).)
Diffstat (limited to 'src')
-rw-r--r--src/librustc/driver/driver.rs84
-rw-r--r--src/librustc/front/assign_node_ids.rs4
-rw-r--r--src/librustc/front/config.rs11
-rw-r--r--src/librustc/front/std_inject.rs15
-rw-r--r--src/librustc/front/test.rs31
-rw-r--r--src/librustc/middle/lint.rs4
-rw-r--r--src/librustc/middle/reachable.rs4
-rw-r--r--src/librustc/middle/resolve.rs137
-rw-r--r--src/librustc/middle/trans/base.rs11
-rw-r--r--src/librustc/middle/typeck/mod.rs6
-rw-r--r--src/librustc/util/common.rs6
-rw-r--r--src/librustdoc/core.rs6
-rw-r--r--src/librusti/rusti.rs14
-rw-r--r--src/librustpkg/rustpkg.rs17
-rw-r--r--src/librustpkg/util.rs17
-rw-r--r--src/libsyntax/ext/expand.rs24
-rw-r--r--src/libsyntax/fold.rs4
-rw-r--r--src/libsyntax/parse/mod.rs4
-rw-r--r--src/libsyntax/parse/parser.rs4
-rwxr-xr-xsrc/libsyntax/syntaxbin0 -> 8435744 bytes
-rw-r--r--src/libsyntax/util/parser_testing.rs4
21 files changed, 179 insertions, 228 deletions
diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs
index df3a40c2289..5fe1a5f7233 100644
--- a/src/librustc/driver/driver.rs
+++ b/src/librustc/driver/driver.rs
@@ -130,8 +130,8 @@ pub enum input {
 }
 
 pub fn phase_1_parse_input(sess: Session, cfg: ast::CrateConfig, input: &input)
-    -> @ast::Crate {
-    time(sess.time_passes(), ~"parsing", || {
+    -> ast::Crate {
+    time(sess.time_passes(), ~"parsing", (), |_| {
         match *input {
             file_input(ref file) => {
                 parse::parse_crate_from_file(&(*file), cfg.clone(), sess.parse_sess)
@@ -153,11 +153,11 @@ pub fn phase_1_parse_input(sess: Session, cfg: ast::CrateConfig, input: &input)
 /// standard library and prelude.
 pub fn phase_2_configure_and_expand(sess: Session,
                                     cfg: ast::CrateConfig,
-                                    mut crate: @ast::Crate) -> @ast::Crate {
+                                    mut crate: ast::Crate) -> ast::Crate {
     let time_passes = sess.time_passes();
 
     *sess.building_library = session::building_library(sess.opts.crate_type,
-                                                       crate, sess.opts.test);
+                                                       &crate, sess.opts.test);
 
 
     // strip before expansion to allow macros to depend on
@@ -167,29 +167,29 @@ pub fn phase_2_configure_and_expand(sess: Session,
     //   mod bar { macro_rules! baz!(() => {{}}) }
     //
     // baz! should not use this definition unless foo is enabled.
-    crate = time(time_passes, ~"std macros injection", ||
+    crate = time(time_passes, ~"std macros injection", crate, |crate|
                  syntax::ext::expand::inject_std_macros(sess.parse_sess,
                                                         cfg.clone(),
                                                         crate));
 
-    crate = time(time_passes, ~"configuration 1", ||
+    crate = time(time_passes, ~"configuration 1", crate, |crate|
                  front::config::strip_unconfigured_items(crate));
 
-    crate = time(time_passes, ~"expansion", ||
+    crate = time(time_passes, ~"expansion", crate, |crate|
                  syntax::ext::expand::expand_crate(sess.parse_sess, cfg.clone(),
                                                    crate));
 
     // strip again, in case expansion added anything with a #[cfg].
-    crate = time(time_passes, ~"configuration 2", ||
+    crate = time(time_passes, ~"configuration 2", crate, |crate|
                  front::config::strip_unconfigured_items(crate));
 
-    crate = time(time_passes, ~"maybe building test harness", ||
+    crate = time(time_passes, ~"maybe building test harness", crate, |crate|
                  front::test::modify_for_testing(sess, crate));
 
-    crate = time(time_passes, ~"std injection", ||
+    crate = time(time_passes, ~"std injection", crate, |crate|
                  front::std_inject::maybe_inject_libstd_ref(sess, crate));
 
-    crate = time(time_passes, ~"assigning node ids", ||
+    crate = time(time_passes, ~"assigning node ids", crate, |crate|
                  front::assign_node_ids::assign_node_ids(sess, crate));
 
     return crate;
@@ -207,21 +207,21 @@ pub struct CrateAnalysis {
 /// miscellaneous analysis passes on the crate. Return various
 /// structures carrying the results of the analysis.
 pub fn phase_3_run_analysis_passes(sess: Session,
-                                   crate: @ast::Crate) -> CrateAnalysis {
+                                   crate: &ast::Crate) -> CrateAnalysis {
 
     let time_passes = sess.time_passes();
 
-    let ast_map = time(time_passes, ~"ast indexing", ||
+    let ast_map = time(time_passes, ~"ast indexing", (), |_|
                        syntax::ast_map::map_crate(sess.diagnostic(), crate));
 
-    time(time_passes, ~"external crate/lib resolution", ||
+    time(time_passes, ~"external crate/lib resolution", (), |_|
          creader::read_crates(sess.diagnostic(), crate, sess.cstore,
                               sess.filesearch,
                               session::sess_os_to_meta_os(sess.targ_cfg.os),
                               sess.opts.is_static,
                               token::get_ident_interner()));
 
-    let lang_items = time(time_passes, ~"language item collection", ||
+    let lang_items = time(time_passes, ~"language item collection", (), |_|
                           middle::lang_items::collect_language_items(crate, sess));
 
     let middle::resolve::CrateMap {
@@ -229,19 +229,19 @@ pub fn phase_3_run_analysis_passes(sess: Session,
         exp_map2: exp_map2,
         trait_map: trait_map
     } =
-        time(time_passes, ~"resolution", ||
+        time(time_passes, ~"resolution", (), |_|
              middle::resolve::resolve_crate(sess, lang_items, crate));
 
-    time(time_passes, ~"looking for entry point",
-         || middle::entry::find_entry_point(sess, crate, ast_map));
+    time(time_passes, ~"looking for entry point", (),
+         |_| middle::entry::find_entry_point(sess, crate, ast_map));
 
-    let freevars = time(time_passes, ~"freevar finding", ||
+    let freevars = time(time_passes, ~"freevar finding", (), |_|
                         freevars::annotate_freevars(def_map, crate));
 
-    let region_map = time(time_passes, ~"region resolution", ||
+    let region_map = time(time_passes, ~"region resolution", (), |_|
                           middle::region::resolve_crate(sess, def_map, crate));
 
-    let rp_set = time(time_passes, ~"region parameterization inference", ||
+    let rp_set = time(time_passes, ~"region parameterization inference", (), |_|
                       middle::region::determine_rp_in_crate(sess, ast_map, def_map, crate));
 
     let ty_cx = ty::mk_ctxt(sess, def_map, ast_map, freevars,
@@ -252,53 +252,53 @@ pub fn phase_3_run_analysis_passes(sess: Session,
         ty_cx, trait_map, crate);
 
     // These next two const passes can probably be merged
-    time(time_passes, ~"const marking", ||
+    time(time_passes, ~"const marking", (), |_|
          middle::const_eval::process_crate(crate, ty_cx));
 
-    time(time_passes, ~"const checking", ||
+    time(time_passes, ~"const checking", (), |_|
          middle::check_const::check_crate(sess, crate, ast_map, def_map,
                                           method_map, ty_cx));
 
     let exported_items =
-        time(time_passes, ~"privacy checking", ||
+        time(time_passes, ~"privacy checking", (), |_|
              middle::privacy::check_crate(ty_cx, &method_map, &exp_map2, crate));
 
-    time(time_passes, ~"effect checking", ||
+    time(time_passes, ~"effect checking", (), |_|
          middle::effect::check_crate(ty_cx, method_map, crate));
 
-    time(time_passes, ~"loop checking", ||
+    time(time_passes, ~"loop checking", (), |_|
          middle::check_loop::check_crate(ty_cx, crate));
 
-    time(time_passes, ~"stack checking", ||
+    time(time_passes, ~"stack checking", (), |_|
          middle::stack_check::stack_check_crate(ty_cx, crate));
 
     let middle::moves::MoveMaps {moves_map, moved_variables_set,
                                  capture_map} =
-        time(time_passes, ~"compute moves", ||
+        time(time_passes, ~"compute moves", (), |_|
              middle::moves::compute_moves(ty_cx, method_map, crate));
 
-    time(time_passes, ~"match checking", ||
+    time(time_passes, ~"match checking", (), |_|
          middle::check_match::check_crate(ty_cx, method_map,
                                           moves_map, crate));
 
-    time(time_passes, ~"liveness checking", ||
+    time(time_passes, ~"liveness checking", (), |_|
          middle::liveness::check_crate(ty_cx, method_map,
                                        capture_map, crate));
 
     let (root_map, write_guard_map) =
-        time(time_passes, ~"borrow checking", ||
+        time(time_passes, ~"borrow checking", (), |_|
              middle::borrowck::check_crate(ty_cx, method_map,
                                            moves_map, moved_variables_set,
                                            capture_map, crate));
 
-    time(time_passes, ~"kind checking", ||
+    time(time_passes, ~"kind checking", (), |_|
          kind::check_crate(ty_cx, method_map, crate));
 
     let reachable_map =
-        time(time_passes, ~"reachability checking", ||
+        time(time_passes, ~"reachability checking", (), |_|
              reachable::find_reachable(ty_cx, method_map, crate));
 
-    time(time_passes, ~"lint checking", ||
+    time(time_passes, ~"lint checking", (), |_|
          lint::check_crate(ty_cx, crate));
 
     CrateAnalysis {
@@ -325,10 +325,10 @@ pub struct CrateTranslation {
 /// Run the translation phase to LLVM, after which the AST and analysis can
 /// be discarded.
 pub fn phase_4_translate_to_llvm(sess: Session,
-                                 crate: @ast::Crate,
+                                 crate: ast::Crate,
                                  analysis: &CrateAnalysis,
                                  outputs: &OutputFilenames) -> CrateTranslation {
-    time(sess.time_passes(), ~"translation", ||
+    time(sess.time_passes(), ~"translation", crate, |crate|
          trans::base::trans_crate(sess, crate, analysis,
                                   &outputs.obj_filename))
 }
@@ -349,7 +349,7 @@ pub fn phase_5_run_llvm_passes(sess: Session,
         let output_type = link::output_type_assembly;
         let asm_filename = outputs.obj_filename.with_filetype("s");
 
-        time(sess.time_passes(), ~"LLVM passes", ||
+        time(sess.time_passes(), ~"LLVM passes", (), |_|
             link::write::run_passes(sess,
                                     trans.context,
                                     trans.module,
@@ -363,7 +363,7 @@ pub fn phase_5_run_llvm_passes(sess: Session,
             os::remove_file(&asm_filename);
         }
     } else {
-        time(sess.time_passes(), ~"LLVM passes", ||
+        time(sess.time_passes(), ~"LLVM passes", (), |_|
             link::write::run_passes(sess,
                                     trans.context,
                                     trans.module,
@@ -377,7 +377,7 @@ pub fn phase_5_run_llvm_passes(sess: Session,
 pub fn phase_6_link_output(sess: Session,
                            trans: &CrateTranslation,
                            outputs: &OutputFilenames) {
-    time(sess.time_passes(), ~"linking", ||
+    time(sess.time_passes(), ~"linking", (), |_|
          link::link_binary(sess,
                            &outputs.obj_filename,
                            &outputs.out_filename,
@@ -430,7 +430,7 @@ pub fn compile_input(sess: Session, cfg: ast::CrateConfig, input: &input,
             if stop_after_phase_1(sess) { return; }
             phase_2_configure_and_expand(sess, cfg, crate)
         };
-        let analysis = phase_3_run_analysis_passes(sess, expanded_crate);
+        let analysis = phase_3_run_analysis_passes(sess, &expanded_crate);
         if stop_after_phase_3(sess) { return; }
         let outputs = build_output_filenames(input, outdir, output, [], sess);
         let trans = phase_4_translate_to_llvm(sess, expanded_crate,
@@ -535,7 +535,7 @@ pub fn pretty_print_input(sess: Session,
             } as @pprust::pp_ann
         }
         PpmTyped => {
-            let analysis = phase_3_run_analysis_passes(sess, crate);
+            let analysis = phase_3_run_analysis_passes(sess, &crate);
             @TypedAnnotation {
                 analysis: analysis
             } as @pprust::pp_ann
@@ -548,7 +548,7 @@ pub fn pretty_print_input(sess: Session,
         pprust::print_crate(sess.codemap,
                             token::get_ident_interner(),
                             sess.span_diagnostic,
-                            crate,
+                            &crate,
                             source_name(input),
                             rdr,
                             io::stdout(),
diff --git a/src/librustc/front/assign_node_ids.rs b/src/librustc/front/assign_node_ids.rs
index fc1b034de97..3d0b32fcee0 100644
--- a/src/librustc/front/assign_node_ids.rs
+++ b/src/librustc/front/assign_node_ids.rs
@@ -24,9 +24,9 @@ impl ast_fold for NodeIdAssigner {
     }
 }
 
-pub fn assign_node_ids(sess: Session, crate: @ast::Crate) -> @ast::Crate {
+pub fn assign_node_ids(sess: Session, crate: ast::Crate) -> ast::Crate {
     let fold = NodeIdAssigner {
         sess: sess,
     };
-    @fold.fold_crate(crate)
+    fold.fold_crate(crate)
 }
diff --git a/src/librustc/front/config.rs b/src/librustc/front/config.rs
index efaebcca011..b99e154853e 100644
--- a/src/librustc/front/config.rs
+++ b/src/librustc/front/config.rs
@@ -18,9 +18,10 @@ struct Context<'self> {
 
 // Support conditional compilation by transforming the AST, stripping out
 // any items that do not belong in the current configuration
-pub fn strip_unconfigured_items(crate: @ast::Crate) -> @ast::Crate {
+pub fn strip_unconfigured_items(crate: ast::Crate) -> ast::Crate {
+    let config = crate.config.clone();
     do strip_items(crate) |attrs| {
-        in_cfg(crate.config, attrs)
+        in_cfg(config, attrs)
     }
 }
 
@@ -40,13 +41,13 @@ impl<'self> fold::ast_fold for Context<'self> {
     }
 }
 
-pub fn strip_items(crate: &ast::Crate,
+pub fn strip_items(crate: ast::Crate,
                    in_cfg: &fn(attrs: &[ast::Attribute]) -> bool)
-                   -> @ast::Crate {
+                   -> ast::Crate {
     let ctxt = Context {
         in_cfg: in_cfg,
     };
-    @ctxt.fold_crate(crate)
+    ctxt.fold_crate(crate)
 }
 
 fn filter_item(cx: &Context, item: @ast::item) -> Option<@ast::item> {
diff --git a/src/librustc/front/std_inject.rs b/src/librustc/front/std_inject.rs
index ad5575f14a7..2253f151ddf 100644
--- a/src/librustc/front/std_inject.rs
+++ b/src/librustc/front/std_inject.rs
@@ -22,9 +22,9 @@ use syntax::opt_vec;
 
 static STD_VERSION: &'static str = "0.9-pre";
 
-pub fn maybe_inject_libstd_ref(sess: Session, crate: @ast::Crate)
-                               -> @ast::Crate {
-    if use_std(crate) {
+pub fn maybe_inject_libstd_ref(sess: Session, crate: ast::Crate)
+                               -> ast::Crate {
+    if use_std(&crate) {
         inject_libstd_ref(sess, crate)
     } else {
         crate
@@ -51,7 +51,7 @@ struct StandardLibraryInjector {
 }
 
 impl fold::ast_fold for StandardLibraryInjector {
-    fn fold_crate(&self, crate: &ast::Crate) -> ast::Crate {
+    fn fold_crate(&self, crate: ast::Crate) -> ast::Crate {
         let version = STD_VERSION.to_managed();
         let vi1 = ast::view_item {
             node: ast::view_item_extern_mod(self.sess.ident_of("std"),
@@ -77,10 +77,9 @@ impl fold::ast_fold for StandardLibraryInjector {
             new_module = self.fold_mod(&new_module);
         }
 
-        // FIXME #2543: Bad copy.
         ast::Crate {
             module: new_module,
-            ..(*crate).clone()
+            ..crate
         }
     }
 
@@ -133,9 +132,9 @@ impl fold::ast_fold for StandardLibraryInjector {
     }
 }
 
-fn inject_libstd_ref(sess: Session, crate: &ast::Crate) -> @ast::Crate {
+fn inject_libstd_ref(sess: Session, crate: ast::Crate) -> ast::Crate {
     let fold = StandardLibraryInjector {
         sess: sess,
     };
-    @fold.fold_crate(crate)
+    fold.fold_crate(crate)
 }
diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs
index 4ac398d351f..254116bd507 100644
--- a/src/librustc/front/test.rs
+++ b/src/librustc/front/test.rs
@@ -37,17 +37,17 @@ struct Test {
 
 struct TestCtxt {
     sess: session::Session,
-    crate: @ast::Crate,
     path: ~[ast::Ident],
     ext_cx: @ExtCtxt,
-    testfns: ~[Test]
+    testfns: ~[Test],
+    is_extra: bool,
+    config: ast::CrateConfig,
 }
 
 // Traverse the crate, collecting all the test functions, eliding any
 // existing main functions, and synthesizing a main test harness
 pub fn modify_for_testing(sess: session::Session,
-                          crate: @ast::Crate)
-                       -> @ast::Crate {
+                          crate: ast::Crate) -> ast::Crate {
     // We generate the test harness when building in the 'test'
     // configuration, either with the '--test' or '--cfg test'
     // command line options.
@@ -65,7 +65,7 @@ struct TestHarnessGenerator {
 }
 
 impl fold::ast_fold for TestHarnessGenerator {
-    fn fold_crate(&self, c: &ast::Crate) -> ast::Crate {
+    fn fold_crate(&self, c: ast::Crate) -> ast::Crate {
         let folded = fold::noop_fold_crate(c, self);
 
         // Add a special __test module to the crate that will contain code
@@ -141,14 +141,15 @@ impl fold::ast_fold for TestHarnessGenerator {
     }
 }
 
-fn generate_test_harness(sess: session::Session, crate: @ast::Crate)
-                         -> @ast::Crate {
+fn generate_test_harness(sess: session::Session, crate: ast::Crate)
+                         -> ast::Crate {
     let cx: @mut TestCtxt = @mut TestCtxt {
         sess: sess,
-        crate: crate,
         ext_cx: ExtCtxt::new(sess.parse_sess, sess.opts.cfg.clone()),
         path: ~[],
-        testfns: ~[]
+        testfns: ~[],
+        is_extra: is_extra(&crate),
+        config: crate.config.clone(),
     };
 
     let ext_cx = cx.ext_cx;
@@ -163,12 +164,12 @@ fn generate_test_harness(sess: session::Session, crate: @ast::Crate)
     let fold = TestHarnessGenerator {
         cx: cx
     };
-    let res = @fold.fold_crate(&*crate);
+    let res = fold.fold_crate(crate);
     ext_cx.bt_pop();
     return res;
 }
 
-fn strip_test_functions(crate: &ast::Crate) -> @ast::Crate {
+fn strip_test_functions(crate: ast::Crate) -> ast::Crate {
     // When not compiling with --test we should not compile the
     // #[test] functions
     do config::strip_items(crate) |attrs| {
@@ -234,7 +235,7 @@ fn is_ignored(cx: @mut TestCtxt, i: @ast::item) -> bool {
     do i.attrs.iter().any |attr| {
         // check ignore(cfg(foo, bar))
         "ignore" == attr.name() && match attr.meta_item_list() {
-            Some(ref cfgs) => attr::test_cfg(cx.crate.config, cfgs.iter().map(|x| *x)),
+            Some(ref cfgs) => attr::test_cfg(cx.config, cfgs.iter().map(|x| *x)),
             None => true
         }
     }
@@ -273,7 +274,7 @@ mod __test {
 
 fn mk_std(cx: &TestCtxt) -> ast::view_item {
     let id_extra = cx.sess.ident_of("extra");
-    let vi = if is_extra(cx) {
+    let vi = if cx.is_extra {
         ast::view_item_use(
             ~[@nospan(ast::view_path_simple(id_extra,
                                             path_node(~[id_extra]),
@@ -371,8 +372,8 @@ fn mk_tests(cx: &TestCtxt) -> @ast::item {
     )).unwrap()
 }
 
-fn is_extra(cx: &TestCtxt) -> bool {
-    let items = attr::find_linkage_metas(cx.crate.attrs);
+fn is_extra(crate: &ast::Crate) -> bool {
+    let items = attr::find_linkage_metas(crate.attrs);
     match attr::last_meta_item_value_str_by_name(items, "name") {
         Some(s) if "extra" == s => true,
         _ => false
diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs
index 331bd25e359..3c6ebc9311d 100644
--- a/src/librustc/middle/lint.rs
+++ b/src/librustc/middle/lint.rs
@@ -135,7 +135,7 @@ pub type LintDict = HashMap<&'static str, LintSpec>;
 enum AttributedNode<'self> {
     Item(@ast::item),
     Method(&'self ast::method),
-    Crate(@ast::Crate),
+    Crate(&'self ast::Crate),
 }
 
 #[deriving(Eq)]
@@ -1565,7 +1565,7 @@ impl Visitor<@mut Context> for LintCheckVisitor {
     }
 }
 
-pub fn check_crate(tcx: ty::ctxt, crate: @ast::Crate) {
+pub fn check_crate(tcx: ty::ctxt, crate: &ast::Crate) {
     let cx = @mut Context {
         dict: @get_lint_dict(),
         curr: SmallIntMap::new(),
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index 07ec4bc27fb..718f8005b74 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -268,7 +268,7 @@ impl ReachableContext {
 
     // Step 1: Mark all public symbols, and add all public symbols that might
     // be inlined to a worklist.
-    fn mark_public_symbols(&self, crate: @Crate) {
+    fn mark_public_symbols(&self, crate: &Crate) {
         let reachable_symbols = self.reachable_symbols;
         let worklist = self.worklist;
 
@@ -429,7 +429,7 @@ impl ReachableContext {
 
 pub fn find_reachable(tcx: ty::ctxt,
                       method_map: typeck::method_map,
-                      crate: @Crate)
+                      crate: &Crate)
                       -> @mut HashSet<NodeId> {
     // XXX(pcwalton): We only need to mark symbols that are exported. But this
     // is more complicated than just looking at whether the symbol is `pub`,
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index a01f4f04246..1bc4f18cce9 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -37,7 +37,6 @@ use syntax::opt_vec::OptVec;
 use syntax::visit;
 use syntax::visit::Visitor;
 
-use std::str;
 use std::uint;
 use std::hashmap::{HashMap, HashSet};
 use std::util;
@@ -803,8 +802,7 @@ pub fn namespace_error_to_str(ns: NamespaceError) -> &'static str {
 
 pub fn Resolver(session: Session,
                 lang_items: LanguageItems,
-                crate: @Crate)
-             -> Resolver {
+                crate_span: Span) -> Resolver {
     let graph_root = @mut NameBindings();
 
     graph_root.define_module(Public,
@@ -812,14 +810,13 @@ pub fn Resolver(session: Session,
                              Some(DefId { crate: 0, node: 0 }),
                              NormalModuleKind,
                              false,
-                             crate.span);
+                             crate_span);
 
     let current_module = graph_root.get_module();
 
     let this = Resolver {
         session: @session,
         lang_items: lang_items,
-        crate: crate,
 
         // The outermost module has def ID 0; this is not reflected in the
         // AST.
@@ -862,7 +859,6 @@ pub fn Resolver(session: Session,
 pub struct Resolver {
     session: @Session,
     lang_items: LanguageItems,
-    crate: @Crate,
 
     intr: @ident_interner,
 
@@ -959,8 +955,8 @@ impl<'self> Visitor<()> for UnusedImportCheckVisitor<'self> {
 
 impl Resolver {
     /// The main name resolution procedure.
-    pub fn resolve(&mut self) {
-        self.build_reduced_graph();
+    pub fn resolve(&mut self, crate: &ast::Crate) {
+        self.build_reduced_graph(crate);
         self.session.abort_if_errors();
 
         self.resolve_imports();
@@ -969,10 +965,10 @@ impl Resolver {
         self.record_exports();
         self.session.abort_if_errors();
 
-        self.resolve_crate();
+        self.resolve_crate(crate);
         self.session.abort_if_errors();
 
-        self.check_for_unused_imports();
+        self.check_for_unused_imports(crate);
     }
 
     //
@@ -983,12 +979,12 @@ impl Resolver {
     //
 
     /// Constructs the reduced graph for the entire crate.
-    pub fn build_reduced_graph(&mut self) {
+    pub fn build_reduced_graph(&mut self, crate: &ast::Crate) {
         let initial_parent =
             ModuleReducedGraphParent(self.graph_root.get_module());
 
         let mut visitor = BuildReducedGraphVisitor { resolver: self, };
-        visit::walk_crate(&mut visitor, self.crate, initial_parent);
+        visit::walk_crate(&mut visitor, crate, initial_parent);
     }
 
     /// Returns the current module tracked by the reduced graph parent.
@@ -3554,10 +3550,10 @@ impl Resolver {
         return None;
     }
 
-    pub fn resolve_crate(&mut self) {
+    pub fn resolve_crate(&mut self, crate: &ast::Crate) {
         debug!("(resolving crate) starting");
 
-        visit::walk_crate(self, self.crate, ());
+        visit::walk_crate(self, crate, ());
     }
 
     pub fn resolve_item(&mut self, item: @item) {
@@ -4986,40 +4982,6 @@ impl Resolver {
         }
     }
 
-    pub fn name_exists_in_scope_struct(&mut self, name: &str) -> bool {
-        let this = &mut *self;
-
-        let mut i = this.type_ribs.len();
-        while i != 0 {
-          i -= 1;
-          match this.type_ribs[i].kind {
-            MethodRibKind(node_id, _) =>
-              for item in this.crate.module.items.iter() {
-                if item.id == node_id {
-                  match item.node {
-                    item_struct(class_def, _) => {
-                      for field in class_def.fields.iter() {
-                        match field.node.kind {
-                          unnamed_field => {},
-                          named_field(ident, _) => {
-                              if str::eq_slice(this.session.str_of(ident),
-                                               name) {
-                                return true
-                              }
-                            }
-                        }
-                      }
-                    }
-                    _ => {}
-                  }
-                }
-            },
-          _ => {}
-        }
-      }
-      return false;
-    }
-
     pub fn resolve_expr(&mut self, expr: @Expr) {
         // First, record candidate traits for this expression if it could
         // result in the invocation of a method call.
@@ -5060,47 +5022,38 @@ impl Resolver {
                     }
                     None => {
                         let wrong_name = self.path_idents_to_str(path);
-                        if self.name_exists_in_scope_struct(wrong_name) {
-                            self.resolve_error(expr.span,
-                                        fmt!("unresolved name `%s`. \
-                                            Did you mean `self.%s`?",
-                                        wrong_name,
-                                        wrong_name));
-                        }
-                        else {
-                            // Be helpful if the name refers to a struct
-                            // (The pattern matching def_tys where the id is in self.structs
-                            // matches on regular structs while excluding tuple- and enum-like
-                            // structs, which wouldn't result in this error.)
-                            match self.with_no_errors(|this|
-                                this.resolve_path(expr.id, path, TypeNS, false)) {
-                                Some(DefTy(struct_id))
-                                  if self.structs.contains(&struct_id) => {
-                                    self.resolve_error(expr.span,
-                                            fmt!("`%s` is a structure name, but this expression \
-                                                uses it like a function name", wrong_name));
-
-                                    self.session.span_note(expr.span, fmt!("Did you mean to write: \
-                                                `%s { /* fields */ }`?", wrong_name));
+                        // Be helpful if the name refers to a struct
+                        // (The pattern matching def_tys where the id is in self.structs
+                        // matches on regular structs while excluding tuple- and enum-like
+                        // structs, which wouldn't result in this error.)
+                        match self.with_no_errors(|this|
+                            this.resolve_path(expr.id, path, TypeNS, false)) {
+                            Some(DefTy(struct_id))
+                              if self.structs.contains(&struct_id) => {
+                                self.resolve_error(expr.span,
+                                        fmt!("`%s` is a structure name, but this expression \
+                                            uses it like a function name", wrong_name));
+
+                                self.session.span_note(expr.span, fmt!("Did you mean to write: \
+                                            `%s { /* fields */ }`?", wrong_name));
 
-                                }
-                                _ =>
-                                   // limit search to 5 to reduce the number
-                                   // of stupid suggestions
-                                   match self.find_best_match_for_name(wrong_name, 5) {
-                                       Some(m) => {
-                                           self.resolve_error(expr.span,
-                                               fmt!("unresolved name `%s`. \
-                                                   Did you mean `%s`?",
-                                                   wrong_name, m));
-                                       }
-                                       None => {
-                                           self.resolve_error(expr.span,
-                                                fmt!("unresolved name `%s`.",
-                                                    wrong_name));
-                                       }
-                                   }
                             }
+                            _ =>
+                               // limit search to 5 to reduce the number
+                               // of stupid suggestions
+                               match self.find_best_match_for_name(wrong_name, 5) {
+                                   Some(m) => {
+                                       self.resolve_error(expr.span,
+                                           fmt!("unresolved name `%s`. \
+                                               Did you mean `%s`?",
+                                               wrong_name, m));
+                                   }
+                                   None => {
+                                       self.resolve_error(expr.span,
+                                            fmt!("unresolved name `%s`.",
+                                                wrong_name));
+                                   }
+                               }
                         }
                     }
                 }
@@ -5431,9 +5384,9 @@ impl Resolver {
     // resolve data structures.
     //
 
-    pub fn check_for_unused_imports(&self) {
+    pub fn check_for_unused_imports(&self, crate: &ast::Crate) {
         let mut visitor = UnusedImportCheckVisitor{ resolver: self };
-        visit::walk_crate(&mut visitor, self.crate, ());
+        visit::walk_crate(&mut visitor, crate, ());
     }
 
     pub fn check_for_item_unused_imports(&self, vi: &view_item) {
@@ -5549,10 +5502,10 @@ pub struct CrateMap {
 /// Entry point to crate resolution.
 pub fn resolve_crate(session: Session,
                      lang_items: LanguageItems,
-                     crate: @Crate)
+                     crate: &Crate)
                   -> CrateMap {
-    let mut resolver = Resolver(session, lang_items, crate);
-    resolver.resolve();
+    let mut resolver = Resolver(session, lang_items, crate.span);
+    resolver.resolve(crate);
     CrateMap {
         def_map: resolver.def_map,
         exp_map2: resolver.export_map2,
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 3f021881b27..983708183d8 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -3075,16 +3075,17 @@ pub fn write_abi_version(ccx: &mut CrateContext) {
 }
 
 pub fn trans_crate(sess: session::Session,
-                   crate: &ast::Crate,
+                   crate: ast::Crate,
                    analysis: &CrateAnalysis,
                    output: &Path) -> CrateTranslation {
     // Before we touch LLVM, make sure that multithreading is enabled.
     if unsafe { !llvm::LLVMRustStartMultithreading() } {
-        //sess.bug("couldn't enable multi-threaded LLVM");
+        sess.bug("couldn't enable multi-threaded LLVM");
     }
 
     let mut symbol_hasher = hash::default_state();
-    let link_meta = link::build_link_meta(sess, crate, output, &mut symbol_hasher);
+    let link_meta = link::build_link_meta(sess, &crate, output,
+                                          &mut symbol_hasher);
 
     // Append ".rc" to crate name as LLVM module identifier.
     //
@@ -3107,7 +3108,7 @@ pub fn trans_crate(sess: session::Session,
                                      analysis.reachable);
 
     if ccx.sess.opts.debuginfo {
-        debuginfo::initialize(ccx, crate);
+        debuginfo::initialize(ccx, &crate);
     }
 
     {
@@ -3144,7 +3145,7 @@ pub fn trans_crate(sess: session::Session,
     }
 
     // Translate the metadata.
-    write_metadata(ccx, crate);
+    write_metadata(ccx, &crate);
     if ccx.sess.trans_stats() {
         io::println("--- trans stats ---");
         println!("n_static_tydescs: {}", ccx.stats.n_static_tydescs);
diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs
index 45a65f954a3..fbd3088902f 100644
--- a/src/librustc/middle/typeck/mod.rs
+++ b/src/librustc/middle/typeck/mod.rs
@@ -447,17 +447,17 @@ pub fn check_crate(tcx: ty::ctxt,
         tcx: tcx
     };
 
-    time(time_passes, ~"type collecting", ||
+    time(time_passes, ~"type collecting", (), |_|
         collect::collect_item_types(ccx, crate));
 
     // this ensures that later parts of type checking can assume that items
     // have valid types and not error
     tcx.sess.abort_if_errors();
 
-    time(time_passes, ~"coherence checking", ||
+    time(time_passes, ~"coherence checking", (), |_|
         coherence::check_coherence(ccx, crate));
 
-    time(time_passes, ~"type checking", ||
+    time(time_passes, ~"type checking", (), |_|
         check::check_item_types(ccx, crate));
 
     check_for_entry_fn(ccx);
diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs
index bd7ca3a5529..3ffbbdd8358 100644
--- a/src/librustc/util/common.rs
+++ b/src/librustc/util/common.rs
@@ -17,10 +17,10 @@ use syntax::visit::Visitor;
 use std::hashmap::HashSet;
 use extra;
 
-pub fn time<T>(do_it: bool, what: ~str, thunk: &fn() -> T) -> T {
-    if !do_it { return thunk(); }
+pub fn time<T, U>(do_it: bool, what: ~str, u: U, f: &fn(U) -> T) -> T {
+    if !do_it { return f(u); }
     let start = extra::time::precise_time_s();
-    let rv = thunk();
+    let rv = f(u);
     let end = extra::time::precise_time_s();
     println!("time: {:3.3f} s\t{}", end - start, what);
     rv
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 8a7bb1f9346..ff60241056c 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -24,7 +24,7 @@ use clean;
 use clean::Clean;
 
 pub struct DocContext {
-    crate: @ast::Crate,
+    crate: ast::Crate,
     tycx: middle::ty::ctxt,
     sess: driver::session::Session
 }
@@ -60,7 +60,7 @@ fn get_ast_and_resolve(cpath: &Path, libs: ~[Path]) -> DocContext {
 
     let mut crate = phase_1_parse_input(sess, cfg.clone(), &input);
     crate = phase_2_configure_and_expand(sess, cfg, crate);
-    let analysis = phase_3_run_analysis_passes(sess, crate);
+    let analysis = phase_3_run_analysis_passes(sess, &crate);
 
     debug!("crate: %?", crate);
     DocContext { crate: crate, tycx: analysis.ty_cx, sess: sess }
@@ -75,7 +75,7 @@ pub fn run_core (libs: ~[Path], path: &Path) -> clean::Crate {
     local_data::set(super::ctxtkey, ctxt);
 
     let v = @mut RustdocVisitor::new();
-    v.visit(ctxt.crate);
+    v.visit(&ctxt.crate);
 
     v.clean()
 }
diff --git a/src/librusti/rusti.rs b/src/librusti/rusti.rs
index ae6c36b8861..ebf939c8bea 100644
--- a/src/librusti/rusti.rs
+++ b/src/librusti/rusti.rs
@@ -161,7 +161,7 @@ fn run(mut program: ~Program, binary: ~str, lib_search_paths: ~[~str],
     let mut to_run = ~[];       // statements to run (emitted back into code)
     let new_locals = @mut ~[];  // new locals being defined
     let mut result = None;      // resultant expression (to print via pp)
-    do find_main(crate, sess) |blk| {
+    do find_main(&crate, sess) |blk| {
         // Fish out all the view items, be sure to record 'extern mod' items
         // differently beause they must appear before all 'use' statements
         for vi in blk.view_items.iter() {
@@ -241,11 +241,11 @@ fn run(mut program: ~Program, binary: ~str, lib_search_paths: ~[~str],
 
     let crate = driver::phase_1_parse_input(sess, cfg.clone(), &dinput);
     let expanded_crate = driver::phase_2_configure_and_expand(sess, cfg, crate);
-    let analysis = driver::phase_3_run_analysis_passes(sess, expanded_crate);
+    let analysis = driver::phase_3_run_analysis_passes(sess, &expanded_crate);
 
     // Once we're typechecked, record the types of all local variables defined
     // in this input
-    do find_main(crate, sess) |blk| {
+    do find_main(&expanded_crate, sess) |blk| {
         program.register_new_vars(blk, analysis.ty_cx);
     }
 
@@ -264,7 +264,7 @@ fn run(mut program: ~Program, binary: ~str, lib_search_paths: ~[~str],
 
     let crate = driver::phase_1_parse_input(sess, cfg.clone(), &input);
     let expanded_crate = driver::phase_2_configure_and_expand(sess, cfg, crate);
-    let analysis = driver::phase_3_run_analysis_passes(sess, expanded_crate);
+    let analysis = driver::phase_3_run_analysis_passes(sess, &expanded_crate);
     let trans = driver::phase_4_translate_to_llvm(sess, expanded_crate, &analysis, outputs);
     driver::phase_5_run_llvm_passes(sess, &trans, outputs);
 
@@ -283,14 +283,14 @@ fn run(mut program: ~Program, binary: ~str, lib_search_paths: ~[~str],
     //
     return (program, jit::consume_engine());
 
-    fn parse_input(sess: session::Session, input: &str) -> @ast::Crate {
+    fn parse_input(sess: session::Session, input: &str) -> ast::Crate {
         let code = fmt!("fn main() {\n %s \n}", input);
         let input = driver::str_input(code.to_managed());
         let cfg = driver::build_configuration(sess);
         driver::phase_1_parse_input(sess, cfg.clone(), &input)
     }
 
-    fn find_main(crate: @ast::Crate, sess: session::Session,
+    fn find_main(crate: &ast::Crate, sess: session::Session,
                  f: &fn(&ast::Block)) {
         for item in crate.module.items.iter() {
             match item.node {
@@ -358,7 +358,7 @@ fn compile_crate(src_filename: ~str, binary: ~str) -> Option<bool> {
             println(fmt!("compiling %s...", src_filename));
             let crate = driver::phase_1_parse_input(sess, cfg.clone(), &input);
             let expanded_crate = driver::phase_2_configure_and_expand(sess, cfg, crate);
-            let analysis = driver::phase_3_run_analysis_passes(sess, expanded_crate);
+            let analysis = driver::phase_3_run_analysis_passes(sess, &expanded_crate);
             let trans = driver::phase_4_translate_to_llvm(sess, expanded_crate, &analysis, outputs);
             driver::phase_5_run_llvm_passes(sess, &trans, outputs);
             true
diff --git a/src/librustpkg/rustpkg.rs b/src/librustpkg/rustpkg.rs
index e4f88081239..2945b75128e 100644
--- a/src/librustpkg/rustpkg.rs
+++ b/src/librustpkg/rustpkg.rs
@@ -85,7 +85,7 @@ struct PkgScript<'self> {
     /// The config for compiling the custom build script
     cfg: ast::CrateConfig,
     /// The crate for the custom build script
-    crate: @ast::Crate,
+    crate: Option<ast::Crate>,
     /// Directory in which to store build output
     build_dir: Path
 }
@@ -125,7 +125,7 @@ impl<'self> PkgScript<'self> {
             input: script,
             sess: sess,
             cfg: cfg,
-            crate: crate,
+            crate: Some(crate),
             build_dir: work_dir
         }
     }
@@ -134,12 +134,13 @@ impl<'self> PkgScript<'self> {
     /// is the command to pass to it (e.g., "build", "clean", "install")
     /// Returns a pair of an exit code and list of configs (obtained by
     /// calling the package script's configs() function if it exists
-    fn run_custom(&self, exec: &mut workcache::Exec, sysroot: &Path) -> (~[~str], ExitCode) {
+    fn run_custom(&mut self, exec: &mut workcache::Exec,
+                  sysroot: &Path) -> (~[~str], ExitCode) {
         let sess = self.sess;
 
         debug!("Working directory = %s", self.build_dir.to_str());
         // Collect together any user-defined commands in the package script
-        let crate = util::ready_crate(sess, self.crate);
+        let crate = util::ready_crate(sess, self.crate.take_unwrap());
         debug!("Building output filenames with script name %s",
                driver::source_name(&driver::file_input(self.input.clone())));
         let exe = self.build_dir.push(~"pkg" + util::exe_suffix());
@@ -419,10 +420,10 @@ impl CtxMethods for BuildContext {
                     let sub_id = pkgid.clone();
                     declare_package_script_dependency(prep, &*pkg_src);
                     do prep.exec |exec| {
-                        let pscript = PkgScript::parse(@sub_sysroot.clone(),
-                                                       package_script_path_clone.clone(),
-                                                       &sub_ws,
-                                                       &sub_id);
+                        let mut pscript = PkgScript::parse(@sub_sysroot.clone(),
+                                                          package_script_path_clone.clone(),
+                                                          &sub_ws,
+                                                          &sub_id);
 
                         pscript.run_custom(exec, &sub_sysroot)
                     }
diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs
index b30ad6f2c92..af80abdac38 100644
--- a/src/librustpkg/util.rs
+++ b/src/librustpkg/util.rs
@@ -68,7 +68,6 @@ struct ListenerFn {
 
 struct ReadyCtx {
     sess: session::Session,
-    crate: @ast::Crate,
     ext_cx: @ExtCtxt,
     path: ~[ast::Ident],
     fns: ~[ListenerFn]
@@ -151,10 +150,9 @@ impl fold::ast_fold for CrateSetup {
 
 /// Generate/filter main function, add the list of commands, etc.
 pub fn ready_crate(sess: session::Session,
-                   crate: @ast::Crate) -> @ast::Crate {
+                   crate: ast::Crate) -> ast::Crate {
     let ctx = @mut ReadyCtx {
         sess: sess,
-        crate: crate,
         ext_cx: ExtCtxt::new(sess.parse_sess, sess.opts.cfg.clone()),
         path: ~[],
         fns: ~[]
@@ -162,7 +160,7 @@ pub fn ready_crate(sess: session::Session,
     let fold = CrateSetup {
         ctx: ctx,
     };
-    @fold.fold_crate(crate)
+    fold.fold_crate(crate)
 }
 
 pub fn compile_input(context: &BuildContext,
@@ -262,7 +260,7 @@ pub fn compile_input(context: &BuildContext,
     let mut crate = driver::phase_1_parse_input(sess, cfg.clone(), &input);
     crate = driver::phase_2_configure_and_expand(sess, cfg.clone(), crate);
 
-    find_and_install_dependencies(context, pkg_id, sess, exec, crate,
+    find_and_install_dependencies(context, pkg_id, sess, exec, &crate,
                                   |p| {
                                       debug!("a dependency: %s", p.to_str());
                                       // Pass the directory containing a dependency
@@ -289,10 +287,7 @@ pub fn compile_input(context: &BuildContext,
                                            pkg_id.path.to_str().to_managed())];
 
         debug!("link options: %?", link_options);
-        crate = @ast::Crate {
-            attrs: ~[attr::mk_attr(attr::mk_list_item(@"link", link_options))],
-            .. (*crate).clone()
-        }
+        crate.attrs = ~[attr::mk_attr(attr::mk_list_item(@"link", link_options))];
     }
 
     debug!("calling compile_crate_from_input, workspace = %s,
@@ -334,7 +329,7 @@ pub fn compile_crate_from_input(input: &Path,
                                 sess: session::Session,
 // Returns None if one of the flags that suppresses compilation output was
 // given
-                                crate: @ast::Crate) -> Option<Path> {
+                                crate: ast::Crate) -> Option<Path> {
     debug!("Calling build_output_filenames with %s, building library? %?",
            out_dir.to_str(), sess.building_library);
 
@@ -352,7 +347,7 @@ pub fn compile_crate_from_input(input: &Path,
     for lib in sess.opts.addl_lib_search_paths.iter() {
         debug!("an additional library: %s", lib.to_str());
     }
-    let analysis = driver::phase_3_run_analysis_passes(sess, crate);
+    let analysis = driver::phase_3_run_analysis_passes(sess, &crate);
     if driver::stop_after_phase_3(sess) { return None; }
     let translation = driver::phase_4_translate_to_llvm(sess, crate,
                                                         &analysis,
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index c62ebb9254e..0ca4f4fa1cd 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -1143,8 +1143,8 @@ impl ast_fold for Injector {
 // program (ick). This should run before cfg stripping.
 pub fn inject_std_macros(parse_sess: @mut parse::ParseSess,
                          cfg: ast::CrateConfig,
-                         c: @Crate)
-                         -> @Crate {
+                         c: Crate)
+                         -> Crate {
     let sm = match parse_item_from_source_str(@"<std-macros>",
                                               std_macros(),
                                               cfg.clone(),
@@ -1157,7 +1157,7 @@ pub fn inject_std_macros(parse_sess: @mut parse::ParseSess,
     let injector = @Injector {
         sm: sm,
     } as @ast_fold;
-    @injector.fold_crate(c)
+    injector.fold_crate(c)
 }
 
 struct NoOpFolder {
@@ -1214,7 +1214,7 @@ impl ast_fold for MacroExpander {
 
 pub fn expand_crate(parse_sess: @mut parse::ParseSess,
                     cfg: ast::CrateConfig,
-                    c: &Crate) -> @Crate {
+                    c: Crate) -> Crate {
     // adding *another* layer of indirection here so that the block
     // visitor can swap out one exts table for another for the duration
     // of the block.  The cleaner alternative would be to thread the
@@ -1227,7 +1227,7 @@ pub fn expand_crate(parse_sess: @mut parse::ParseSess,
         cx: cx,
     } as @ast_fold;
 
-    let ret = @expander.fold_crate(c);
+    let ret = expander.fold_crate(c);
     parse_sess.span_diagnostic.handler().abort_if_errors();
     return ret;
 }
@@ -1534,7 +1534,7 @@ mod test {
         let a2_name = gensym("a2");
         let renamer = new_rename_folder(ast::Ident{name:a_name,ctxt:EMPTY_CTXT},
                                         a2_name);
-        let renamed_ast = renamer.fold_crate(item_ast);
+        let renamed_ast = renamer.fold_crate(item_ast.clone());
         let varrefs = @mut ~[];
         visit::walk_crate(&mut new_path_finder(varrefs), &renamed_ast, ());
         match varrefs {
@@ -1557,12 +1557,12 @@ mod test {
         }
     }
 
-    fn fake_print_crate(crate: @ast::Crate) {
+    fn fake_print_crate(crate: &ast::Crate) {
         let s = pprust::rust_printer(std::io::stderr(),get_ident_interner());
         pprust::print_crate_(s, crate);
     }
 
-    fn expand_crate_str(crate_str: @str) -> @ast::Crate {
+    fn expand_crate_str(crate_str: @str) -> ast::Crate {
         let (crate_ast,ps) = string_to_crate_and_sess(crate_str);
         // the cfg argument actually does matter, here...
         expand_crate(ps,~[],crate_ast)
@@ -1658,10 +1658,10 @@ mod test {
         let cr = expand_crate_str(teststr.to_managed());
         // find the bindings:
         let bindings = @mut ~[];
-        visit::walk_crate(&mut new_name_finder(bindings),cr,());
+        visit::walk_crate(&mut new_name_finder(bindings),&cr,());
         // find the varrefs:
         let varrefs = @mut ~[];
-        visit::walk_crate(&mut new_path_finder(varrefs),cr,());
+        visit::walk_crate(&mut new_path_finder(varrefs),&cr,());
         // must be one check clause for each binding:
         assert_eq!(bindings.len(),bound_connections.len());
         for (binding_idx,shouldmatch) in bound_connections.iter().enumerate() {
@@ -1721,7 +1721,7 @@ foo_module!()
         let cr = expand_crate_str(crate_str);
         // find the xx binding
         let bindings = @mut ~[];
-        visit::walk_crate(&mut new_name_finder(bindings), cr, ());
+        visit::walk_crate(&mut new_name_finder(bindings), &cr, ());
         let cxbinds : ~[&ast::Ident] =
             bindings.iter().filter(|b|{@"xx" == (ident_to_str(*b))}).collect();
         let cxbind = match cxbinds {
@@ -1731,7 +1731,7 @@ foo_module!()
         let resolved_binding = mtwt_resolve(*cxbind);
         // find all the xx varrefs:
         let varrefs = @mut ~[];
-        visit::walk_crate(&mut new_path_finder(varrefs), cr, ());
+        visit::walk_crate(&mut new_path_finder(varrefs), &cr, ());
         // the xx binding should bind all of the xx varrefs:
         for (idx,v) in varrefs.iter().filter(|p|{ p.segments.len() == 1
                                           && (@"xx" == (ident_to_str(&p.segments[0].identifier)))
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index a25f267c458..b823ff726ac 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -16,7 +16,7 @@ use opt_vec::OptVec;
 
 // We may eventually want to be able to fold over type parameters, too.
 pub trait ast_fold {
-    fn fold_crate(&self, c: &Crate) -> Crate {
+    fn fold_crate(&self, c: Crate) -> Crate {
         noop_fold_crate(c, self)
     }
 
@@ -691,7 +691,7 @@ pub fn noop_fold_mod<T:ast_fold>(m: &_mod, folder: &T) -> _mod {
     }
 }
 
-pub fn noop_fold_crate<T:ast_fold>(c: &Crate, folder: &T) -> Crate {
+pub fn noop_fold_crate<T:ast_fold>(c: Crate, folder: &T) -> Crate {
     let fold_meta_item = |x| fold_meta_item_(x, folder);
     let fold_attribute = |x| fold_attribute_(x, folder);
 
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 37f2f8345cd..a492a2283e3 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -73,7 +73,7 @@ pub fn parse_crate_from_file(
     input: &Path,
     cfg: ast::CrateConfig,
     sess: @mut ParseSess
-) -> @ast::Crate {
+) -> ast::Crate {
     new_parser_from_file(sess, /*bad*/ cfg.clone(), input).parse_crate_mod()
     // why is there no p.abort_if_errors here?
 }
@@ -83,7 +83,7 @@ pub fn parse_crate_from_source_str(
     source: @str,
     cfg: ast::CrateConfig,
     sess: @mut ParseSess
-) -> @ast::Crate {
+) -> ast::Crate {
     let p = new_parser_from_source_str(sess,
                                        /*bad*/ cfg.clone(),
                                        name,
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 6c905c252c1..5a68e32a533 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -5140,7 +5140,7 @@ impl Parser {
 
     // Parses a source module as a crate. This is the main
     // entry point for the parser.
-    pub fn parse_crate_mod(&self) -> @Crate {
+    pub fn parse_crate_mod(&self) -> Crate {
         let lo = self.span.lo;
         // parse the crate's inner attrs, maybe (oops) one
         // of the attrs of an item:
@@ -5149,7 +5149,7 @@ impl Parser {
         // parse the items inside the crate:
         let m = self.parse_mod_items(token::EOF, first_item_outer_attrs);
 
-        @ast::Crate {
+        ast::Crate {
             module: m,
             attrs: inner,
             config: self.cfg.clone(),
diff --git a/src/libsyntax/syntax b/src/libsyntax/syntax
new file mode 100755
index 00000000000..942ee88bd0e
--- /dev/null
+++ b/src/libsyntax/syntax
Binary files differdiff --git a/src/libsyntax/util/parser_testing.rs b/src/libsyntax/util/parser_testing.rs
index 23396c06a9a..59a6f0adeb4 100644
--- a/src/libsyntax/util/parser_testing.rs
+++ b/src/libsyntax/util/parser_testing.rs
@@ -47,14 +47,14 @@ fn with_error_checking_parse<T>(s: @str, f: &fn(&mut Parser) -> T) -> T {
 }
 
 // parse a string, return a crate.
-pub fn string_to_crate (source_str : @str) -> @ast::Crate {
+pub fn string_to_crate (source_str : @str) -> ast::Crate {
     do with_error_checking_parse(source_str) |p| {
         p.parse_crate_mod()
     }
 }
 
 // parse a string, return a crate and the ParseSess
-pub fn string_to_crate_and_sess (source_str : @str) -> (@ast::Crate,@mut ParseSess) {
+pub fn string_to_crate_and_sess (source_str : @str) -> (ast::Crate,@mut ParseSess) {
     let (p,ps) = string_to_parser_and_sess(source_str);
     (p.parse_crate_mod(),ps)
 }