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).)
This commit is contained in:
bors 2013-09-29 20:06:13 -07:00
commit 80b6056f5d
21 changed files with 178 additions and 227 deletions

View File

@ -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(),

View File

@ -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)
}

View File

@ -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> {

View File

@ -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)
}

View File

@ -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

View File

@ -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(),

View File

@ -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`,

View File

@ -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));
// 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));
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,

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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()
}

View File

@ -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

View File

@ -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)
}

View File

@ -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,

View File

@ -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)))

View File

@ -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);

View File

@ -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,

View File

@ -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(),

BIN
src/libsyntax/syntax Executable file

Binary file not shown.

View File

@ -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)
}