From 28d4a8903d47307c12a9a71892595fa7e8a2cf49 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 26 Feb 2015 19:35:35 +0200 Subject: [PATCH 01/11] rustc_driver: hold references to contexts, instead of owning them, in pretty-printing annotators. --- src/librustc_driver/pretty.rs | 93 ++++++++++++++--------------------- 1 file changed, 38 insertions(+), 55 deletions(-) diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 22473099baf60..bf5377f071d77 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -131,17 +131,14 @@ impl PpSourceMode { { match *self { PpmNormal | PpmEveryBodyLoops | PpmExpanded => { - let annotation = NoAnn { sess: sess, ast_map: ast_map }; - f(&annotation, payload) + f(&NoAnn { sess: &sess, ast_map: ast_map.as_ref() }, payload) } PpmIdentified | PpmExpandedIdentified => { - let annotation = IdentifiedAnnotation { sess: sess, ast_map: ast_map }; - f(&annotation, payload) + f(&IdentifiedAnnotation { sess: &sess, ast_map: ast_map.as_ref() }, payload) } PpmExpandedHygiene => { - let annotation = HygieneAnnotation { sess: sess, ast_map: ast_map }; - f(&annotation, payload) + f(&HygieneAnnotation { sess: &sess, ast_map: ast_map.as_ref() }, payload) } PpmTyped => { let ast_map = ast_map.expect("--pretty=typed missing ast_map"); @@ -150,8 +147,7 @@ impl PpSourceMode { arenas, id, resolve::MakeGlobMap::No); - let annotation = TypedAnnotation { analysis: analysis }; - f(&annotation, payload) + f(&TypedAnnotation { tcx: &analysis.ty_cx }, payload) } } } @@ -173,39 +169,31 @@ trait PrinterSupport<'ast>: pprust::PpAnn { fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn; } -struct NoAnn<'ast> { - sess: Session, - ast_map: Option> +struct NoAnn<'a, 'ast: 'a> { + sess: &'a Session, + ast_map: Option<&'a ast_map::Map<'ast>> } -impl<'ast> PrinterSupport<'ast> for NoAnn<'ast> { - fn sess<'a>(&'a self) -> &'a Session { &self.sess } - - fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map<'ast>> { - self.ast_map.as_ref() - } - - fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self } +impl<'a, 'ast: 'a> PrinterSupport<'ast> for NoAnn<'a, 'ast> { + fn sess<'b>(&'b self) -> &'b Session { self.sess } + fn ast_map<'b>(&'b self) -> Option<&'b ast_map::Map<'ast>> { self.ast_map } + fn pp_ann<'b>(&'b self) -> &'b pprust::PpAnn { self } } -impl<'ast> pprust::PpAnn for NoAnn<'ast> {} +impl<'a, 'ast> pprust::PpAnn for NoAnn<'a, 'ast> {} -struct IdentifiedAnnotation<'ast> { - sess: Session, - ast_map: Option>, +struct IdentifiedAnnotation<'a, 'ast: 'a> { + sess: &'a Session, + ast_map: Option<&'a ast_map::Map<'ast>> } -impl<'ast> PrinterSupport<'ast> for IdentifiedAnnotation<'ast> { - fn sess<'a>(&'a self) -> &'a Session { &self.sess } - - fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map<'ast>> { - self.ast_map.as_ref() - } - - fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self } +impl<'a, 'ast: 'a> PrinterSupport<'ast> for IdentifiedAnnotation<'a, 'ast> { + fn sess<'b>(&'b self) -> &'b Session { self.sess } + fn ast_map<'b>(&'b self) -> Option<&'b ast_map::Map<'ast>> { self.ast_map } + fn pp_ann<'b>(&'b self) -> &'b pprust::PpAnn { self } } -impl<'ast> pprust::PpAnn for IdentifiedAnnotation<'ast> { +impl<'a, 'ast> pprust::PpAnn for IdentifiedAnnotation<'a, 'ast> { fn pre(&self, s: &mut pprust::State, node: pprust::AnnNode) -> old_io::IoResult<()> { @@ -241,22 +229,18 @@ impl<'ast> pprust::PpAnn for IdentifiedAnnotation<'ast> { } } -struct HygieneAnnotation<'ast> { - sess: Session, - ast_map: Option>, +struct HygieneAnnotation<'a, 'ast: 'a> { + sess: &'a Session, + ast_map: Option<&'a ast_map::Map<'ast>> } -impl<'ast> PrinterSupport<'ast> for HygieneAnnotation<'ast> { - fn sess<'a>(&'a self) -> &'a Session { &self.sess } - - fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map<'ast>> { - self.ast_map.as_ref() - } - - fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self } +impl<'a, 'ast: 'a> PrinterSupport<'ast> for HygieneAnnotation<'a, 'ast> { + fn sess<'b>(&'b self) -> &'b Session { self.sess } + fn ast_map<'b>(&'b self) -> Option<&'b ast_map::Map<'ast>> { self.ast_map } + fn pp_ann<'b>(&'b self) -> &'b pprust::PpAnn { self } } -impl<'ast> pprust::PpAnn for HygieneAnnotation<'ast> { +impl<'a, 'ast> pprust::PpAnn for HygieneAnnotation<'a, 'ast> { fn post(&self, s: &mut pprust::State, node: pprust::AnnNode) -> old_io::IoResult<()> { @@ -277,21 +261,21 @@ impl<'ast> pprust::PpAnn for HygieneAnnotation<'ast> { } -struct TypedAnnotation<'tcx> { - analysis: ty::CrateAnalysis<'tcx>, +struct TypedAnnotation<'a, 'tcx: 'a> { + tcx: &'a ty::ctxt<'tcx>, } -impl<'tcx> PrinterSupport<'tcx> for TypedAnnotation<'tcx> { - fn sess<'a>(&'a self) -> &'a Session { &self.analysis.ty_cx.sess } +impl<'a, 'tcx: 'a> PrinterSupport<'tcx> for TypedAnnotation<'a, 'tcx> { + fn sess<'b>(&'b self) -> &'b Session { &self.tcx.sess } - fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map<'tcx>> { - Some(&self.analysis.ty_cx.map) + fn ast_map<'b>(&'b self) -> Option<&'b ast_map::Map<'tcx>> { + Some(&self.tcx.map) } - fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self } + fn pp_ann<'b>(&'b self) -> &'b pprust::PpAnn { self } } -impl<'tcx> pprust::PpAnn for TypedAnnotation<'tcx> { +impl<'a, 'tcx> pprust::PpAnn for TypedAnnotation<'a, 'tcx> { fn pre(&self, s: &mut pprust::State, node: pprust::AnnNode) -> old_io::IoResult<()> { @@ -303,7 +287,6 @@ impl<'tcx> pprust::PpAnn for TypedAnnotation<'tcx> { fn post(&self, s: &mut pprust::State, node: pprust::AnnNode) -> old_io::IoResult<()> { - let tcx = &self.analysis.ty_cx; match node { pprust::NodeExpr(expr) => { try!(pp::space(&mut s.s)); @@ -311,8 +294,8 @@ impl<'tcx> pprust::PpAnn for TypedAnnotation<'tcx> { try!(pp::space(&mut s.s)); try!(pp::word(&mut s.s, &ppaux::ty_to_string( - tcx, - ty::expr_ty(tcx, expr)))); + self.tcx, + ty::expr_ty(self.tcx, expr)))); s.pclose() } _ => Ok(()) From 16f63306921a571efdaa590c31dc850efa5f34f9 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 26 Feb 2015 19:56:51 +0200 Subject: [PATCH 02/11] rustc: clean up a couple of workarounds that predate `FnOnce`. --- src/librustc/util/common.rs | 17 ++-- src/librustc_driver/driver.rs | 159 +++++++++++++++---------------- src/librustc_driver/lib.rs | 11 +-- src/librustc_driver/pretty.rs | 30 +++--- src/librustc_trans/back/link.rs | 4 +- src/librustc_trans/back/lto.rs | 16 ++-- src/librustc_trans/back/write.rs | 8 +- src/librustc_typeck/lib.rs | 8 +- 8 files changed, 118 insertions(+), 135 deletions(-) diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index ca740f5378219..c26545a42ecc6 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -30,11 +30,11 @@ pub const FN_OUTPUT_NAME: &'static str = "Output"; #[derive(Clone, Copy, Debug)] pub struct ErrorReported; -pub fn time(do_it: bool, what: &str, u: U, f: F) -> T where - F: FnOnce(U) -> T, +pub fn time(do_it: bool, what: &str, f: F) -> T where + F: FnOnce() -> T, { thread_local!(static DEPTH: Cell = Cell::new(0)); - if !do_it { return f(u); } + if !do_it { return f(); } let old = DEPTH.with(|slot| { let r = slot.get(); @@ -42,15 +42,10 @@ pub fn time(do_it: bool, what: &str, u: U, f: F) -> T where r }); - let mut u = Some(u); let mut rv = None; - let dur = { - let ref mut rvp = rv; - - Duration::span(move || { - *rvp = Some(f(u.take().unwrap())) - }) - }; + let dur = Duration::span(|| { + rv = Some(f()); + }); let rv = rv.unwrap(); println!("{}time: {}.{:03} \t{}", repeat(" ").take(old).collect::(), diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 425ec7ec452ee..4b9b81f583530 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -336,7 +336,7 @@ pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input) syntax::ext::mtwt::reset_tables(); token::reset_ident_interner(); - let krate = time(sess.time_passes(), "parsing", (), |_| { + let krate = time(sess.time_passes(), "parsing", || { match *input { Input::File(ref file) => { parse::parse_crate_from_file(&(*file), cfg.clone(), &sess.parse_sess) @@ -383,7 +383,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, *sess.crate_metadata.borrow_mut() = collect_crate_metadata(sess, &krate.attrs); - time(time_passes, "recursion limit", (), |_| { + time(time_passes, "recursion limit", || { middle::recursion_limit::update_recursion_limit(sess, &krate); }); @@ -395,7 +395,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, // // baz! should not use this definition unless foo is enabled. - time(time_passes, "gated macro checking", (), |_| { + time(time_passes, "gated macro checking", || { let features = syntax::feature_gate::check_crate_macros(sess.codemap(), &sess.parse_sess.span_diagnostic, @@ -406,23 +406,23 @@ pub fn phase_2_configure_and_expand(sess: &Session, sess.abort_if_errors(); }); - krate = time(time_passes, "configuration 1", krate, |krate| + krate = time(time_passes, "configuration 1", || syntax::config::strip_unconfigured_items(sess.diagnostic(), krate)); - krate = time(time_passes, "crate injection", krate, |krate| + krate = time(time_passes, "crate injection", || syntax::std_inject::maybe_inject_crates_ref(krate, sess.opts.alt_std_name.clone())); - let macros = time(time_passes, "macro loading", (), |_| + let macros = time(time_passes, "macro loading", || metadata::macro_import::read_macro_defs(sess, &krate)); let mut addl_plugins = Some(addl_plugins); - let registrars = time(time_passes, "plugin loading", (), |_| + let registrars = time(time_passes, "plugin loading", || plugin::load::load_plugins(sess, &krate, addl_plugins.take().unwrap())); let mut registry = Registry::new(sess, &krate); - time(time_passes, "plugin registration", registrars, |registrars| { + time(time_passes, "plugin registration", || { if sess.features.borrow().rustc_diagnostic_macros { registry.register_macro("__diagnostic_used", diagnostics::plugin::expand_diagnostic_used); @@ -461,40 +461,38 @@ pub fn phase_2_configure_and_expand(sess: &Session, // Abort if there are errors from lint processing or a plugin registrar. sess.abort_if_errors(); - krate = time(time_passes, "expansion", (krate, macros, syntax_exts), - |(krate, macros, syntax_exts)| { - // Windows dlls do not have rpaths, so they don't know how to find their - // dependencies. It's up to us to tell the system where to find all the - // dependent dlls. Note that this uses cfg!(windows) as opposed to - // targ_cfg because syntax extensions are always loaded for the host - // compiler, not for the target. - let mut _old_path = OsString::from_str(""); - if cfg!(windows) { - _old_path = env::var_os("PATH").unwrap_or(_old_path); - let mut new_path = sess.host_filesearch(PathKind::All).get_dylib_search_paths(); - new_path.extend(os::split_paths(_old_path.to_str().unwrap()).into_iter()); - env::set_var("PATH", &env::join_paths(new_path.iter()).unwrap()); - } - let features = sess.features.borrow(); - let cfg = syntax::ext::expand::ExpansionConfig { - crate_name: crate_name.to_string(), - features: Some(&features), - recursion_limit: sess.recursion_limit.get(), - }; - let ret = syntax::ext::expand::expand_crate(&sess.parse_sess, - cfg, - macros, - syntax_exts, - krate); - if cfg!(windows) { - env::set_var("PATH", &_old_path); - } - ret + krate = time(time_passes, "expansion", || { + // Windows dlls do not have rpaths, so they don't know how to find their + // dependencies. It's up to us to tell the system where to find all the + // dependent dlls. Note that this uses cfg!(windows) as opposed to + // targ_cfg because syntax extensions are always loaded for the host + // compiler, not for the target. + let mut _old_path = OsString::from_str(""); + if cfg!(windows) { + _old_path = env::var_os("PATH").unwrap_or(_old_path); + let mut new_path = sess.host_filesearch(PathKind::All).get_dylib_search_paths(); + new_path.extend(os::split_paths(_old_path.to_str().unwrap()).into_iter()); + env::set_var("PATH", &env::join_paths(new_path.iter()).unwrap()); } - ); + let features = sess.features.borrow(); + let cfg = syntax::ext::expand::ExpansionConfig { + crate_name: crate_name.to_string(), + features: Some(&features), + recursion_limit: sess.recursion_limit.get(), + }; + let ret = syntax::ext::expand::expand_crate(&sess.parse_sess, + cfg, + macros, + syntax_exts, + krate); + if cfg!(windows) { + env::set_var("PATH", &_old_path); + } + ret + }); // Needs to go *after* expansion to be able to check the results of macro expansion. - time(time_passes, "complete gated feature checking", (), |_| { + time(time_passes, "complete gated feature checking", || { let features = syntax::feature_gate::check_crate(sess.codemap(), &sess.parse_sess.span_diagnostic, @@ -506,20 +504,20 @@ pub fn phase_2_configure_and_expand(sess: &Session, // JBC: make CFG processing part of expansion to avoid this problem: // strip again, in case expansion added anything with a #[cfg]. - krate = time(time_passes, "configuration 2", krate, |krate| + krate = time(time_passes, "configuration 2", || syntax::config::strip_unconfigured_items(sess.diagnostic(), krate)); - krate = time(time_passes, "maybe building test harness", krate, |krate| + krate = time(time_passes, "maybe building test harness", || syntax::test::modify_for_testing(&sess.parse_sess, &sess.opts.cfg, krate, sess.diagnostic())); - krate = time(time_passes, "prelude injection", krate, |krate| + krate = time(time_passes, "prelude injection", || syntax::std_inject::maybe_inject_prelude(krate)); - time(time_passes, "checking that all macro invocations are gone", &krate, |krate| - syntax::ext::expand::check_for_macros(&sess.parse_sess, krate)); + time(time_passes, "checking that all macro invocations are gone", || + syntax::ext::expand::check_for_macros(&sess.parse_sess, &krate)); Some(krate) } @@ -538,7 +536,7 @@ pub fn assign_node_ids_and_map<'ast>(sess: &Session, } } - let map = time(sess.time_passes(), "assigning node ids and indexing ast", forest, |forest| + let map = time(sess.time_passes(), "assigning node ids and indexing ast", move || ast_map::map_crate(forest, NodeIdAssigner { sess: sess })); if sess.opts.debugging_opts.ast_json { @@ -560,10 +558,10 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session, let time_passes = sess.time_passes(); let krate = ast_map.krate(); - time(time_passes, "external crate/lib resolution", (), |_| + time(time_passes, "external crate/lib resolution", || CrateReader::new(&sess).read_crates(krate)); - let lang_items = time(time_passes, "language item collection", (), |_| + let lang_items = time(time_passes, "language item collection", || middle::lang_items::collect_language_items(krate, &sess)); let resolve::CrateMap { @@ -573,35 +571,34 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session, trait_map, external_exports, glob_map, - } = - time(time_passes, "resolution", (), - |_| resolve::resolve_crate(&sess, - &ast_map, - &lang_items, - krate, - make_glob_map)); + } = time(time_passes, "resolution", || + resolve::resolve_crate(&sess, + &ast_map, + &lang_items, + krate, + make_glob_map)); // Discard MTWT tables that aren't required past resolution. syntax::ext::mtwt::clear_tables(); - let named_region_map = time(time_passes, "lifetime resolution", (), - |_| middle::resolve_lifetime::krate(&sess, krate, &def_map)); + let named_region_map = time(time_passes, "lifetime resolution", || + middle::resolve_lifetime::krate(&sess, krate, &def_map)); - time(time_passes, "looking for entry point", (), - |_| middle::entry::find_entry_point(&sess, &ast_map)); + time(time_passes, "looking for entry point", || + middle::entry::find_entry_point(&sess, &ast_map)); sess.plugin_registrar_fn.set( - time(time_passes, "looking for plugin registrar", (), |_| + time(time_passes, "looking for plugin registrar", || plugin::build::find_plugin_registrar( sess.diagnostic(), krate))); - let region_map = time(time_passes, "region resolution", (), |_| + let region_map = time(time_passes, "region resolution", || middle::region::resolve_crate(&sess, krate)); - time(time_passes, "loop checking", (), |_| + time(time_passes, "loop checking", || middle::check_loop::check_crate(&sess, krate)); - time(time_passes, "static item recursion checking", (), |_| + time(time_passes, "static item recursion checking", || middle::check_static_recursion::check_crate(&sess, krate, &def_map, &ast_map)); let ty_cx = ty::mk_ctxt(sess, @@ -617,33 +614,33 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session, // passes are timed inside typeck typeck::check_crate(&ty_cx, trait_map); - time(time_passes, "const checking", (), |_| + time(time_passes, "const checking", || middle::check_const::check_crate(&ty_cx)); let (exported_items, public_items) = - time(time_passes, "privacy checking", (), |_| + time(time_passes, "privacy checking", || rustc_privacy::check_crate(&ty_cx, &export_map, external_exports)); // Do not move this check past lint - time(time_passes, "stability index", (), |_| + time(time_passes, "stability index", || ty_cx.stability.borrow_mut().build(&ty_cx.sess, krate, &public_items)); - time(time_passes, "intrinsic checking", (), |_| + time(time_passes, "intrinsic checking", || middle::intrinsicck::check_crate(&ty_cx)); - time(time_passes, "effect checking", (), |_| + time(time_passes, "effect checking", || middle::effect::check_crate(&ty_cx)); - time(time_passes, "match checking", (), |_| + time(time_passes, "match checking", || middle::check_match::check_crate(&ty_cx)); - time(time_passes, "liveness checking", (), |_| + time(time_passes, "liveness checking", || middle::liveness::check_crate(&ty_cx)); - time(time_passes, "borrow checking", (), |_| + time(time_passes, "borrow checking", || borrowck::check_crate(&ty_cx)); - time(time_passes, "rvalue checking", (), |_| + time(time_passes, "rvalue checking", || middle::check_rvalues::check_crate(&ty_cx, krate)); // Avoid overwhelming user with errors if type checking failed. @@ -654,24 +651,24 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session, ty_cx.sess.abort_if_errors(); let reachable_map = - time(time_passes, "reachability checking", (), |_| + time(time_passes, "reachability checking", || reachable::find_reachable(&ty_cx, &exported_items)); - time(time_passes, "death checking", (), |_| { + time(time_passes, "death checking", || { middle::dead::check_crate(&ty_cx, &exported_items, &reachable_map) }); let ref lib_features_used = - time(time_passes, "stability checking", (), |_| + time(time_passes, "stability checking", || stability::check_unstable_api_usage(&ty_cx)); - time(time_passes, "unused lib feature checking", (), |_| + time(time_passes, "unused lib feature checking", || stability::check_unused_or_stable_features( &ty_cx.sess, lib_features_used)); - time(time_passes, "lint checking", (), |_| + time(time_passes, "lint checking", || lint::check_crate(&ty_cx, &exported_items)); // The above three passes generate errors w/o aborting @@ -694,11 +691,11 @@ pub fn phase_4_translate_to_llvm<'tcx>(analysis: ty::CrateAnalysis<'tcx>) -> (ty::ctxt<'tcx>, trans::CrateTranslation) { let time_passes = analysis.ty_cx.sess.time_passes(); - time(time_passes, "resolving dependency formats", (), |_| + time(time_passes, "resolving dependency formats", || dependency_format::calculate(&analysis.ty_cx)); // Option dance to work around the lack of stack once closures. - time(time_passes, "translation", analysis, |analysis| + time(time_passes, "translation", || trans::trans_crate(analysis)) } @@ -710,7 +707,7 @@ pub fn phase_5_run_llvm_passes(sess: &Session, if sess.opts.cg.no_integrated_as { let output_type = config::OutputTypeAssembly; - time(sess.time_passes(), "LLVM passes", (), |_| + time(sess.time_passes(), "LLVM passes", || write::run_passes(sess, trans, &[output_type], outputs)); write::run_assembler(sess, outputs); @@ -720,7 +717,7 @@ pub fn phase_5_run_llvm_passes(sess: &Session, fs::unlink(&outputs.temp_path(config::OutputTypeAssembly)).unwrap(); } } else { - time(sess.time_passes(), "LLVM passes", (), |_| + time(sess.time_passes(), "LLVM passes", || write::run_passes(sess, trans, &sess.opts.output_types, @@ -740,7 +737,7 @@ pub fn phase_6_link_output(sess: &Session, new_path.extend(os::split_paths(old_path.to_str().unwrap()).into_iter()); env::set_var("PATH", &env::join_paths(new_path.iter()).unwrap()); - time(sess.time_passes(), "linking", (), |_| + time(sess.time_passes(), "linking", || link::link_binary(sess, trans, outputs, diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 15fae351ddbf2..bdd7085d83bef 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -377,12 +377,11 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { if sess.opts.debugging_opts.save_analysis { control.after_analysis.callback = box |state| { time(state.session.time_passes(), - "save analysis", - state.expanded_crate.unwrap(), - |krate| save::process_crate(state.session, - krate, - state.analysis.unwrap(), - state.out_dir)); + "save analysis", || + save::process_crate(state.session, + state.expanded_crate.unwrap(), + state.analysis.unwrap(), + state.out_dir)); }; control.make_glob_map = resolve::MakeGlobMap::Yes; } diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index bf5377f071d77..fac2b86874e70 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -114,31 +114,27 @@ pub fn parse_pretty(sess: &Session, // Note that since the `&PrinterSupport` is freshly constructed on each // call, it would not make sense to try to attach the lifetime of `self` // to the lifetime of the `&PrinterObject`. -// -// (The `use_once_payload` is working around the current lack of once -// functions in the compiler.) impl PpSourceMode { /// Constructs a `PrinterSupport` object and passes it to `f`. - fn call_with_pp_support<'tcx, A, B, F>(&self, - sess: Session, - ast_map: Option>, - arenas: &'tcx ty::CtxtArenas<'tcx>, - id: String, - payload: B, - f: F) -> A where - F: FnOnce(&PrinterSupport, B) -> A, + fn call_with_pp_support<'tcx, A, F>(&self, + sess: Session, + ast_map: Option>, + arenas: &'tcx ty::CtxtArenas<'tcx>, + id: String, + f: F) -> A where + F: FnOnce(&PrinterSupport) -> A, { match *self { PpmNormal | PpmEveryBodyLoops | PpmExpanded => { - f(&NoAnn { sess: &sess, ast_map: ast_map.as_ref() }, payload) + f(&NoAnn { sess: &sess, ast_map: ast_map.as_ref() }) } PpmIdentified | PpmExpandedIdentified => { - f(&IdentifiedAnnotation { sess: &sess, ast_map: ast_map.as_ref() }, payload) + f(&IdentifiedAnnotation { sess: &sess, ast_map: ast_map.as_ref() }) } PpmExpandedHygiene => { - f(&HygieneAnnotation { sess: &sess, ast_map: ast_map.as_ref() }, payload) + f(&HygieneAnnotation { sess: &sess, ast_map: ast_map.as_ref() }) } PpmTyped => { let ast_map = ast_map.expect("--pretty=typed missing ast_map"); @@ -147,7 +143,7 @@ impl PpSourceMode { arenas, id, resolve::MakeGlobMap::No); - f(&TypedAnnotation { tcx: &analysis.ty_cx }, payload) + f(&TypedAnnotation { tcx: &analysis.ty_cx }) } } } @@ -543,7 +539,7 @@ pub fn pretty_print_input(sess: Session, match (ppm, opt_uii) { (PpmSource(s), None) => s.call_with_pp_support( - sess, ast_map, &arenas, id, out, |annotation, out| { + sess, ast_map, &arenas, id, |annotation| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); pprust::print_crate(sess.codemap(), @@ -558,7 +554,7 @@ pub fn pretty_print_input(sess: Session, (PpmSource(s), Some(uii)) => s.call_with_pp_support( - sess, ast_map, &arenas, id, (out,uii), |annotation, (out,uii)| { + sess, ast_map, &arenas, id, |annotation| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); let ast_map = annotation.ast_map() diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 7b377ac3611b6..d54c9e0a53039 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -788,7 +788,7 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool, // Invoke the system linker debug!("{:?}", &cmd); - let prog = time(sess.time_passes(), "running linker", (), |()| cmd.output()); + let prog = time(sess.time_passes(), "running linker", || cmd.output()); match prog { Ok(prog) => { if !prog.status.success() { @@ -1190,7 +1190,7 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session, let name = &name[3..name.len() - 5]; // chop off lib/.rlib time(sess.time_passes(), &format!("altering {}.rlib", name), - (), |()| { + || { let dst = tmpdir.join(cratepath.filename().unwrap()); match fs::copy(&cratepath, &dst) { Ok(..) => {} diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs index d8a296bf0410c..f51b8ad2ac288 100644 --- a/src/librustc_trans/back/lto.rs +++ b/src/librustc_trans/back/lto.rs @@ -65,11 +65,8 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, for i in iter::count(0, 1) { let bc_encoded = time(sess.time_passes(), &format!("check for {}.{}.bytecode.deflate", name, i), - (), - |_| { - archive.read(&format!("{}.{}.bytecode.deflate", - file, i)) - }); + || archive.read(&format!("{}.{}.bytecode.deflate", + file, i))); let bc_encoded = match bc_encoded { Some(data) => data, None => { @@ -84,7 +81,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, }; let bc_decoded = if is_versioned_bytecode_format(bc_encoded) { - time(sess.time_passes(), &format!("decode {}.{}.bc", file, i), (), |_| { + time(sess.time_passes(), &format!("decode {}.{}.bc", file, i), || { // Read the version let version = extract_bytecode_format_version(bc_encoded); @@ -108,7 +105,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, } }) } else { - time(sess.time_passes(), &format!("decode {}.{}.bc", file, i), (), |_| { + time(sess.time_passes(), &format!("decode {}.{}.bc", file, i), || { // the object must be in the old, pre-versioning format, so simply // inflate everything and let LLVM decide if it can make sense of it match flate::inflate_bytes(bc_encoded) { @@ -125,8 +122,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, debug!("linking {}, part {}", name, i); time(sess.time_passes(), &format!("ll link {}.{}", name, i), - (), - |()| unsafe { + || unsafe { if !llvm::LLVMRustLinkInExternalBitcode(llmod, ptr as *const libc::c_char, bc_decoded.len() as libc::size_t) { @@ -183,7 +179,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, llvm::LLVMRustAddPass(pm, "verify\0".as_ptr() as *const _); - time(sess.time_passes(), "LTO passes", (), |()| + time(sess.time_passes(), "LTO passes", || llvm::LLVMRunPassManager(pm, llmod)); llvm::LLVMDisposePassManager(pm); diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index cd14fe529b1a7..c712a2f261384 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -460,9 +460,9 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, } // Finally, run the actual optimization passes - time(config.time_passes, "llvm function passes", (), |()| + time(config.time_passes, "llvm function passes", || llvm::LLVMRustRunFunctionPassManager(fpm, llmod)); - time(config.time_passes, "llvm module passes", (), |()| + time(config.time_passes, "llvm module passes", || llvm::LLVMRunPassManager(mpm, llmod)); // Deallocate managers that we're now done with @@ -471,7 +471,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, match cgcx.lto_ctxt { Some((sess, reachable)) if sess.lto() => { - time(sess.time_passes(), "all lto passes", (), |()| + time(sess.time_passes(), "all lto passes", || lto::run(sess, llmod, tm, reachable)); if config.emit_lto_bc { @@ -515,7 +515,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr()); } - time(config.time_passes, "codegen passes", (), |()| { + time(config.time_passes, "codegen passes", || { if config.emit_ir { let ext = format!("{}.ll", name_extra); let out = output_names.with_extension(&ext); diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 78dd66c8e7dbb..4d8b1d1c0e8d2 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -326,20 +326,20 @@ pub fn check_crate(tcx: &ty::ctxt, trait_map: ty::TraitMap) { tcx: tcx }; - time(time_passes, "type collecting", (), |_| + time(time_passes, "type collecting", || collect::collect_item_types(tcx)); // 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, "variance inference", (), |_| + time(time_passes, "variance inference", || variance::infer_variance(tcx)); - time(time_passes, "coherence checking", (), |_| + time(time_passes, "coherence checking", || coherence::check_coherence(&ccx)); - time(time_passes, "type checking", (), |_| + time(time_passes, "type checking", || check::check_item_types(&ccx)); check_for_entry_fn(&ccx); From e70c9a05b5b218875a9a5c4c87865f7f1d3c1f27 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 26 Feb 2015 21:38:26 +0200 Subject: [PATCH 03/11] rustc_driver: refactor PrinterSupport away by localizing ownership to pretty_print_input. --- src/librustc_driver/lib.rs | 10 +- src/librustc_driver/pretty.rs | 307 +++++++++++++--------------------- 2 files changed, 122 insertions(+), 195 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index bdd7085d83bef..31bf34713e101 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -144,13 +144,9 @@ pub fn run_compiler<'a>(args: &[String], // It is somewhat unfortunate that this is hardwired in - this is forced by // the fact that pretty_print_input requires the session by value. - let pretty = callbacks.parse_pretty(&sess, &matches); - match pretty { - Some((ppm, opt_uii)) => { - pretty::pretty_print_input(sess, cfg, &input, ppm, opt_uii, ofile); - return; - } - None => {/* continue */ } + if let Some((ppm, opt_uii)) = callbacks.parse_pretty(&sess, &matches) { + pretty::pretty_print_input(sess, cfg, &input, ppm, opt_uii, ofile).unwrap(); + return; } let plugins = sess.opts.debugging_opts.extra_plugins.clone(); diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index fac2b86874e70..1f17439a86afc 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -38,7 +38,7 @@ use syntax::ptr::P; use graphviz as dot; -use std::old_io::{self, MemReader}; +use std::old_io::{self, BufReader}; use std::option; use std::str::FromStr; @@ -103,93 +103,13 @@ pub fn parse_pretty(sess: &Session, (first, opt_second) } +struct NoAnn; +const NO_ANNOTATION: &'static pprust::PpAnn = &NoAnn; +impl pprust::PpAnn for NoAnn {} - -// This slightly awkward construction is to allow for each PpMode to -// choose whether it needs to do analyses (which can consume the -// Session) and then pass through the session (now attached to the -// analysis results) on to the chosen pretty-printer, along with the -// `&PpAnn` object. -// -// Note that since the `&PrinterSupport` is freshly constructed on each -// call, it would not make sense to try to attach the lifetime of `self` -// to the lifetime of the `&PrinterObject`. - -impl PpSourceMode { - /// Constructs a `PrinterSupport` object and passes it to `f`. - fn call_with_pp_support<'tcx, A, F>(&self, - sess: Session, - ast_map: Option>, - arenas: &'tcx ty::CtxtArenas<'tcx>, - id: String, - f: F) -> A where - F: FnOnce(&PrinterSupport) -> A, - { - match *self { - PpmNormal | PpmEveryBodyLoops | PpmExpanded => { - f(&NoAnn { sess: &sess, ast_map: ast_map.as_ref() }) - } - - PpmIdentified | PpmExpandedIdentified => { - f(&IdentifiedAnnotation { sess: &sess, ast_map: ast_map.as_ref() }) - } - PpmExpandedHygiene => { - f(&HygieneAnnotation { sess: &sess, ast_map: ast_map.as_ref() }) - } - PpmTyped => { - let ast_map = ast_map.expect("--pretty=typed missing ast_map"); - let analysis = driver::phase_3_run_analysis_passes(sess, - ast_map, - arenas, - id, - resolve::MakeGlobMap::No); - f(&TypedAnnotation { tcx: &analysis.ty_cx }) - } - } - } -} - -trait PrinterSupport<'ast>: pprust::PpAnn { - /// Provides a uniform interface for re-extracting a reference to a - /// `Session` from a value that now owns it. - fn sess<'a>(&'a self) -> &'a Session; - - /// Provides a uniform interface for re-extracting a reference to an - /// `ast_map::Map` from a value that now owns it. - fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map<'ast>>; - - /// Produces the pretty-print annotation object. - /// - /// (Rust does not yet support upcasting from a trait object to - /// an object for one of its super-traits.) - fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn; -} - -struct NoAnn<'a, 'ast: 'a> { - sess: &'a Session, - ast_map: Option<&'a ast_map::Map<'ast>> -} - -impl<'a, 'ast: 'a> PrinterSupport<'ast> for NoAnn<'a, 'ast> { - fn sess<'b>(&'b self) -> &'b Session { self.sess } - fn ast_map<'b>(&'b self) -> Option<&'b ast_map::Map<'ast>> { self.ast_map } - fn pp_ann<'b>(&'b self) -> &'b pprust::PpAnn { self } -} - -impl<'a, 'ast> pprust::PpAnn for NoAnn<'a, 'ast> {} - -struct IdentifiedAnnotation<'a, 'ast: 'a> { - sess: &'a Session, - ast_map: Option<&'a ast_map::Map<'ast>> -} - -impl<'a, 'ast: 'a> PrinterSupport<'ast> for IdentifiedAnnotation<'a, 'ast> { - fn sess<'b>(&'b self) -> &'b Session { self.sess } - fn ast_map<'b>(&'b self) -> Option<&'b ast_map::Map<'ast>> { self.ast_map } - fn pp_ann<'b>(&'b self) -> &'b pprust::PpAnn { self } -} - -impl<'a, 'ast> pprust::PpAnn for IdentifiedAnnotation<'a, 'ast> { +struct IdentifiedAnnotation; +const IDENTIFIED_ANNOTATION: &'static pprust::PpAnn = &IdentifiedAnnotation; +impl pprust::PpAnn for IdentifiedAnnotation { fn pre(&self, s: &mut pprust::State, node: pprust::AnnNode) -> old_io::IoResult<()> { @@ -225,18 +145,9 @@ impl<'a, 'ast> pprust::PpAnn for IdentifiedAnnotation<'a, 'ast> { } } -struct HygieneAnnotation<'a, 'ast: 'a> { - sess: &'a Session, - ast_map: Option<&'a ast_map::Map<'ast>> -} - -impl<'a, 'ast: 'a> PrinterSupport<'ast> for HygieneAnnotation<'a, 'ast> { - fn sess<'b>(&'b self) -> &'b Session { self.sess } - fn ast_map<'b>(&'b self) -> Option<&'b ast_map::Map<'ast>> { self.ast_map } - fn pp_ann<'b>(&'b self) -> &'b pprust::PpAnn { self } -} - -impl<'a, 'ast> pprust::PpAnn for HygieneAnnotation<'a, 'ast> { +struct HygieneAnnotation; +const HYGIENE_ANNOTATION: &'static pprust::PpAnn = &HygieneAnnotation; +impl pprust::PpAnn for HygieneAnnotation { fn post(&self, s: &mut pprust::State, node: pprust::AnnNode) -> old_io::IoResult<()> { @@ -256,21 +167,10 @@ impl<'a, 'ast> pprust::PpAnn for HygieneAnnotation<'a, 'ast> { } } - struct TypedAnnotation<'a, 'tcx: 'a> { tcx: &'a ty::ctxt<'tcx>, } -impl<'a, 'tcx: 'a> PrinterSupport<'tcx> for TypedAnnotation<'a, 'tcx> { - fn sess<'b>(&'b self) -> &'b Session { &self.tcx.sess } - - fn ast_map<'b>(&'b self) -> Option<&'b ast_map::Map<'tcx>> { - Some(&self.tcx.map) - } - - fn pp_ann<'b>(&'b self) -> &'b pprust::PpAnn { self } -} - impl<'a, 'tcx> pprust::PpAnn for TypedAnnotation<'a, 'tcx> { fn pre(&self, s: &mut pprust::State, @@ -395,8 +295,8 @@ impl UserIdentifiedItem { } } -fn needs_ast_map(ppm: &PpMode, opt_uii: &Option) -> bool { - match *ppm { +fn needs_ast_map(ppm: PpMode, opt_uii: &Option) -> bool { + match ppm { PpmSource(PpmNormal) | PpmSource(PpmEveryBodyLoops) | PpmSource(PpmIdentified) => opt_uii.is_some(), @@ -409,8 +309,8 @@ fn needs_ast_map(ppm: &PpMode, opt_uii: &Option) -> bool { } } -fn needs_expansion(ppm: &PpMode) -> bool { - match *ppm { +fn needs_expansion(ppm: PpMode) -> bool { + match ppm { PpmSource(PpmNormal) | PpmSource(PpmEveryBodyLoops) | PpmSource(PpmIdentified) => false, @@ -423,6 +323,20 @@ fn needs_expansion(ppm: &PpMode) -> bool { } } +fn needs_types(ppm: PpMode) -> bool { + match ppm { + PpmSource(PpmNormal) | + PpmSource(PpmEveryBodyLoops) | + PpmSource(PpmIdentified) | + PpmSource(PpmExpanded) | + PpmSource(PpmExpandedIdentified) | + PpmSource(PpmExpandedHygiene) => false, + + PpmSource(PpmTyped) | + PpmFlowGraph(_) => true + } +} + struct ReplaceBodyWithLoop { within_static_or_const: bool, } @@ -486,7 +400,8 @@ pub fn pretty_print_input(sess: Session, input: &Input, ppm: PpMode, opt_uii: Option, - ofile: Option) { + ofile: Option) + -> old_io::IoResult<()> { let krate = driver::phase_1_parse_input(&sess, cfg, input); let krate = if let PpmSource(PpmEveryBodyLoops) = ppm { @@ -498,11 +413,11 @@ pub fn pretty_print_input(sess: Session, let id = link::find_crate_name(Some(&sess), &krate.attrs, input); - let is_expanded = needs_expansion(&ppm); - let compute_ast_map = needs_ast_map(&ppm, &opt_uii); + let compute_ast_map = needs_ast_map(ppm, &opt_uii); + let compute_types = needs_types(ppm); let krate = if compute_ast_map { match driver::phase_2_configure_and_expand(&sess, krate, &id[..], None) { - None => return, + None => return Ok(()), Some(k) => k } } else { @@ -519,75 +434,97 @@ pub fn pretty_print_input(sess: Session, (forest.krate(), None) }; - let src_name = driver::source_name(input); - let src = sess.codemap().get_filemap(&src_name[..]) - .src.as_bytes().to_vec(); - let mut rdr = MemReader::new(src); + let analysis; + let (ast_map, tcx, sess) = if compute_types { + let ast_map = ast_map.expect("--pretty missing ast_map for type context"); + analysis = driver::phase_3_run_analysis_passes(sess, + ast_map, + &arenas, + id, + resolve::MakeGlobMap::No); + (Some(&analysis.ty_cx.map), Some(&analysis.ty_cx), &analysis.ty_cx.sess) + } else { + (ast_map.as_ref(), None, &sess) + }; let out = match ofile { None => box old_io::stdout() as Box, Some(p) => { - let r = old_io::File::create(&p); - match r { + match old_io::File::create(&p) { Ok(w) => box w as Box, Err(e) => panic!("print-print failed to open {} due to {}", - p.display(), e), + p.display(), e), } } }; - match (ppm, opt_uii) { - (PpmSource(s), None) => - s.call_with_pp_support( - sess, ast_map, &arenas, id, |annotation| { - debug!("pretty printing source code {:?}", s); - let sess = annotation.sess(); - pprust::print_crate(sess.codemap(), - sess.diagnostic(), - krate, - src_name.to_string(), - &mut rdr, - out, - annotation.pp_ann(), - is_expanded) - }), + match ppm { + PpmSource(mode) => { + debug!("pretty printing source code {:?}", mode); - (PpmSource(s), Some(uii)) => - s.call_with_pp_support( - sess, ast_map, &arenas, id, |annotation| { - debug!("pretty printing source code {:?}", s); - let sess = annotation.sess(); - let ast_map = annotation.ast_map() - .expect("--pretty missing ast_map"); - let mut pp_state = - pprust::State::new_from_input(sess.codemap(), - sess.diagnostic(), - src_name.to_string(), - &mut rdr, - out, - annotation.pp_ann(), - is_expanded); - for node_id in uii.all_matching_node_ids(ast_map) { - let node = ast_map.get(node_id); - try!(pp_state.print_node(&node)); - try!(pp::space(&mut pp_state.s)); - try!(pp_state.synth_comment(ast_map.path_to_string(node_id))); - try!(pp::hardbreak(&mut pp_state.s)); - } - pp::eof(&mut pp_state.s) - }), + let typed_annotation = tcx.map(|tcx| TypedAnnotation { tcx: tcx }); + let annotation: &pprust::PpAnn = match mode { + PpmNormal | PpmEveryBodyLoops | PpmExpanded => { + NO_ANNOTATION + } + PpmIdentified | PpmExpandedIdentified => { + IDENTIFIED_ANNOTATION + } + PpmExpandedHygiene => { + HYGIENE_ANNOTATION + } + PpmTyped => { + typed_annotation.as_ref().expect("--pretty=typed missing type context") + } + }; - (PpmFlowGraph(mode), opt_uii) => { + let is_expanded = needs_expansion(ppm); + + let src_name = driver::source_name(input); + let filemap = sess.codemap().get_filemap(&src_name); + let mut rdr = BufReader::new(filemap.src.as_bytes()); + + if let Some(ref uii) = opt_uii { + let ast_map = ast_map.expect("--pretty missing ast_map"); + let mut pp_state = + pprust::State::new_from_input(sess.codemap(), + sess.diagnostic(), + src_name, + &mut rdr, + out, + annotation, + is_expanded); + for node_id in uii.all_matching_node_ids(ast_map) { + let node = ast_map.get(node_id); + try!(pp_state.print_node(&node)); + try!(pp::space(&mut pp_state.s)); + try!(pp_state.synth_comment(ast_map.path_to_string(node_id))); + try!(pp::hardbreak(&mut pp_state.s)); + } + pp::eof(&mut pp_state.s) + } else { + pprust::print_crate(sess.codemap(), + sess.diagnostic(), + krate, + src_name, + &mut rdr, + out, + annotation, + is_expanded) + } + } + + PpmFlowGraph(mode) => { debug!("pretty printing flow graph for {:?}", opt_uii); let uii = opt_uii.unwrap_or_else(|| { sess.fatal(&format!("`pretty flowgraph=..` needs NodeId (int) or unique path suffix (b::c::d)")) }); - let ast_map = ast_map.expect("--pretty flowgraph missing ast_map"); - let nodeid = uii.to_one_node_id("--pretty", &sess, &ast_map); + let tcx = tcx.expect("--pretty flowgraph missing type context"); + let nodeid = uii.to_one_node_id("--pretty", sess, &tcx.map); - let node = ast_map.find(nodeid).unwrap_or_else(|| { + let node = tcx.map.find(nodeid).unwrap_or_else(|| { sess.fatal(&format!("--pretty flowgraph couldn't find id: {}", nodeid)) }); @@ -595,13 +532,8 @@ pub fn pretty_print_input(sess: Session, let code = blocks::Code::from_node(node); match code { Some(code) => { - let variants = gather_flowgraph_variants(&sess); - let analysis = driver::phase_3_run_analysis_passes(sess, - ast_map, - &arenas, - id, - resolve::MakeGlobMap::No); - print_flowgraph(variants, analysis, code, mode, out) + let variants = gather_flowgraph_variants(sess); + print_flowgraph(variants, tcx, code, mode, out) } None => { let message = format!("--pretty=flowgraph needs \ @@ -610,29 +542,28 @@ pub fn pretty_print_input(sess: Session, // point to what was found, if there's an // accessible span. - match ast_map.opt_span(nodeid) { + match tcx.map.opt_span(nodeid) { Some(sp) => sess.span_fatal(sp, &message[..]), None => sess.fatal(&message[..]) } } } } - }.unwrap() + } } fn print_flowgraph(variants: Vec, - analysis: ty::CrateAnalysis, - code: blocks::Code, - mode: PpFlowGraphMode, - mut out: W) -> old_io::IoResult<()> { - let ty_cx = &analysis.ty_cx; + tcx: &ty::ctxt, + code: blocks::Code, + mode: PpFlowGraphMode, + mut out: W) -> old_io::IoResult<()> { let cfg = match code { - blocks::BlockCode(block) => cfg::CFG::new(ty_cx, &*block), - blocks::FnLikeCode(fn_like) => cfg::CFG::new(ty_cx, &*fn_like.body()), + blocks::BlockCode(block) => cfg::CFG::new(tcx, &*block), + blocks::FnLikeCode(fn_like) => cfg::CFG::new(tcx, &*fn_like.body()), }; let labelled_edges = mode != PpFlowGraphMode::UnlabelledEdges; let lcfg = LabelledCFG { - ast_map: &ty_cx.map, + ast_map: &tcx.map, cfg: &cfg, name: format!("node_{}", code.id()), labelled_edges: labelled_edges, @@ -644,14 +575,14 @@ fn print_flowgraph(variants: Vec, return expand_err_details(r); } blocks::BlockCode(_) => { - ty_cx.sess.err("--pretty flowgraph with -Z flowgraph-print \ - annotations requires fn-like node id."); + tcx.sess.err("--pretty flowgraph with -Z flowgraph-print \ + annotations requires fn-like node id."); return Ok(()) } blocks::FnLikeCode(fn_like) => { let fn_parts = borrowck::FnPartsWithCFG::from_fn_like(&fn_like, &cfg); let (bccx, analysis_data) = - borrowck::build_borrowck_dataflow_data_for_fn(ty_cx, fn_parts); + borrowck::build_borrowck_dataflow_data_for_fn(tcx, fn_parts); let lcfg = borrowck_dot::DataflowLabeller { inner: lcfg, From d4945b4755da0b5c3f257c26bf16a0649ac98b35 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Fri, 27 Feb 2015 09:43:20 +0200 Subject: [PATCH 04/11] rustc_driver: move pretty-printing to the new driver controller API. --- src/librustc_driver/driver.rs | 54 ++++++++---- src/librustc_driver/lib.rs | 88 ++++++++------------ src/librustc_driver/pretty.rs | 151 +++++++++++----------------------- 3 files changed, 121 insertions(+), 172 deletions(-) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 4b9b81f583530..4c8ea60d5363e 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -69,10 +69,18 @@ pub fn compile_input(sess: Session, let (outputs, expanded_crate, id) = { let krate = phase_1_parse_input(&sess, cfg, input); + let krate = if control.every_body_loops { + use syntax::fold::Folder; + ::pretty::ReplaceBodyWithLoop::new().fold_crate(krate) + } else { + krate + }; + controller_entry_point!(after_parse, CompileState::state_after_parse(input, &sess, outdir, + output, &krate)); let outputs = build_output_filenames(input, @@ -99,6 +107,7 @@ pub fn compile_input(sess: Session, CompileState::state_after_expand(input, &sess, outdir, + output, &expanded_crate, &id[..])); @@ -112,6 +121,7 @@ pub fn compile_input(sess: Session, CompileState::state_after_write_deps(input, &sess, outdir, + output, &ast_map, &ast_map.krate(), &id[..])); @@ -126,6 +136,7 @@ pub fn compile_input(sess: Session, CompileState::state_after_analysis(input, &analysis.ty_cx.sess, outdir, + output, analysis.ty_cx.map.krate(), &analysis, &analysis.ty_cx)); @@ -152,6 +163,7 @@ pub fn compile_input(sess: Session, CompileState::state_after_llvm(input, &sess, outdir, + output, &trans)); phase_6_link_output(&sess, &trans, &outputs); @@ -193,6 +205,7 @@ pub struct CompileController<'a> { pub after_llvm: PhaseController<'a>, pub make_glob_map: resolve::MakeGlobMap, + pub every_body_loops: bool, } impl<'a> CompileController<'a> { @@ -204,6 +217,7 @@ impl<'a> CompileController<'a> { after_analysis: PhaseController::basic(), after_llvm: PhaseController::basic(), make_glob_map: resolve::MakeGlobMap::No, + every_body_loops: false, } } } @@ -225,7 +239,7 @@ impl<'a> PhaseController<'a> { /// State that is passed to a callback. What state is available depends on when /// during compilation the callback is made. See the various constructor methods /// (`state_*`) in the impl to see which data is provided for any given entry point. -pub struct CompileState<'a, 'ast: 'a, 'tcx: 'a> { +pub struct CompileState<'a, 'tcx: 'a> { pub input: &'a Input, pub session: &'a Session, pub cfg: Option<&'a ast::CrateConfig>, @@ -233,22 +247,25 @@ pub struct CompileState<'a, 'ast: 'a, 'tcx: 'a> { pub crate_name: Option<&'a str>, pub output_filenames: Option<&'a OutputFilenames>, pub out_dir: Option<&'a Path>, + pub output: Option<&'a Path>, pub expanded_crate: Option<&'a ast::Crate>, - pub ast_map: Option<&'a ast_map::Map<'ast>>, + pub ast_map: Option<&'a ast_map::Map<'tcx>>, pub analysis: Option<&'a ty::CrateAnalysis<'tcx>>, pub tcx: Option<&'a ty::ctxt<'tcx>>, pub trans: Option<&'a trans::CrateTranslation>, } -impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> { +impl<'a, 'tcx> CompileState<'a, 'tcx> { fn empty(input: &'a Input, session: &'a Session, - out_dir: &'a Option) - -> CompileState<'a, 'ast, 'tcx> { + out_dir: &'a Option, + output: &'a Option) + -> CompileState<'a, 'tcx> { CompileState { input: input, session: session, out_dir: out_dir.as_ref(), + output: output.as_ref(), cfg: None, krate: None, crate_name: None, @@ -264,54 +281,58 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> { fn state_after_parse(input: &'a Input, session: &'a Session, out_dir: &'a Option, + output: &'a Option, krate: &'a ast::Crate) - -> CompileState<'a, 'ast, 'tcx> { + -> CompileState<'a, 'tcx> { CompileState { krate: Some(krate), - .. CompileState::empty(input, session, out_dir) + .. CompileState::empty(input, session, out_dir, output) } } fn state_after_expand(input: &'a Input, session: &'a Session, out_dir: &'a Option, + output: &'a Option, expanded_crate: &'a ast::Crate, crate_name: &'a str) - -> CompileState<'a, 'ast, 'tcx> { + -> CompileState<'a, 'tcx> { CompileState { crate_name: Some(crate_name), expanded_crate: Some(expanded_crate), - .. CompileState::empty(input, session, out_dir) + .. CompileState::empty(input, session, out_dir, output) } } fn state_after_write_deps(input: &'a Input, session: &'a Session, out_dir: &'a Option, - ast_map: &'a ast_map::Map<'ast>, + output: &'a Option, + ast_map: &'a ast_map::Map<'tcx>, expanded_crate: &'a ast::Crate, crate_name: &'a str) - -> CompileState<'a, 'ast, 'tcx> { + -> CompileState<'a, 'tcx> { CompileState { crate_name: Some(crate_name), ast_map: Some(ast_map), expanded_crate: Some(expanded_crate), - .. CompileState::empty(input, session, out_dir) + .. CompileState::empty(input, session, out_dir, output) } } fn state_after_analysis(input: &'a Input, session: &'a Session, out_dir: &'a Option, + output: &'a Option, expanded_crate: &'a ast::Crate, analysis: &'a ty::CrateAnalysis<'tcx>, tcx: &'a ty::ctxt<'tcx>) - -> CompileState<'a, 'ast, 'tcx> { + -> CompileState<'a, 'tcx> { CompileState { analysis: Some(analysis), tcx: Some(tcx), expanded_crate: Some(expanded_crate), - .. CompileState::empty(input, session, out_dir) + .. CompileState::empty(input, session, out_dir, output) } } @@ -319,11 +340,12 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> { fn state_after_llvm(input: &'a Input, session: &'a Session, out_dir: &'a Option, + output: &'a Option, trans: &'a trans::CrateTranslation) - -> CompileState<'a, 'ast, 'tcx> { + -> CompileState<'a, 'tcx> { CompileState { trans: Some(trans), - .. CompileState::empty(input, session, out_dir) + .. CompileState::empty(input, session, out_dir, output) } } } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 31bf34713e101..1556018a0edf0 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -98,7 +98,7 @@ const BUG_REPORT_URL: &'static str = pub fn run(args: Vec) -> int { - monitor(move || run_compiler(&args, &mut RustcDefaultCalls)); + monitor(move || run_compiler(&args, &mut RustcDefaultCalls::new())); 0 } @@ -142,13 +142,6 @@ pub fn run_compiler<'a>(args: &[String], do_or_return!(callbacks.late_callback(&matches, &sess, &input, &odir, &ofile)); - // It is somewhat unfortunate that this is hardwired in - this is forced by - // the fact that pretty_print_input requires the session by value. - if let Some((ppm, opt_uii)) = callbacks.parse_pretty(&sess, &matches) { - pretty::pretty_print_input(sess, cfg, &input, ppm, opt_uii, ofile).unwrap(); - return; - } - let plugins = sess.opts.debugging_opts.extra_plugins.clone(); let control = callbacks.build_controller(&sess); driver::compile_input(sess, cfg, &input, &odir, &ofile, Some(plugins), control); @@ -235,33 +228,15 @@ pub trait CompilerCalls<'a> { &diagnostics::registry::Registry) -> Option<(Input, Option)>; - // Parse pretty printing information from the arguments. The implementer can - // choose to ignore this (the default will return None) which will skip pretty - // printing. If you do want to pretty print, it is recommended to use the - // implementation of this method from RustcDefaultCalls. - // FIXME, this is a terrible bit of API. Parsing of pretty printing stuff - // should be done as part of the framework and the implementor should customise - // handling of it. However, that is not possible atm because pretty printing - // essentially goes off and takes another path through the compiler which - // means the session is either moved or not depending on what parse_pretty - // returns (we could fix this by cloning, but it's another hack). The proper - // solution is to handle pretty printing as if it were a compiler extension, - // extending CompileController to make this work (see for example the treatment - // of save-analysis in RustcDefaultCalls::build_controller). - fn parse_pretty(&mut self, - _sess: &Session, - _matches: &getopts::Matches) - -> Option<(PpMode, Option)> { - None - } - // Create a CompilController struct for controlling the behaviour of compilation. fn build_controller(&mut self, &Session) -> CompileController<'a>; } // CompilerCalls instance for a regular rustc build. -#[derive(Copy)] -pub struct RustcDefaultCalls; +pub struct RustcDefaultCalls { + save_analysis: bool, + pretty_print: Option<(PpMode, Option)> +} impl<'a> CompilerCalls<'a> for RustcDefaultCalls { fn early_callback(&mut self, @@ -316,28 +291,6 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { None } - fn parse_pretty(&mut self, - sess: &Session, - matches: &getopts::Matches) - -> Option<(PpMode, Option)> { - let pretty = if sess.opts.debugging_opts.unstable_options { - matches.opt_default("pretty", "normal").map(|a| { - // stable pretty-print variants only - pretty::parse_pretty(sess, &a, false) - }) - } else { - None - }; - if pretty.is_none() && sess.unstable_options() { - matches.opt_str("xpretty").map(|a| { - // extended with unstable pretty-print variants - pretty::parse_pretty(sess, &a, true) - }) - } else { - pretty - } - } - fn late_callback(&mut self, matches: &getopts::Matches, sess: &Session, @@ -345,6 +298,18 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { odir: &Option, ofile: &Option) -> Compilation { + self.save_analysis = sess.opts.debugging_opts.save_analysis; + + if sess.unstable_options() { + self.pretty_print = matches.opt_default("pretty", "normal").map(|a| { + // stable pretty-print variants only + pretty::parse_pretty(sess, &a, false) + }).or_else(|| matches.opt_str("xpretty").map(|a| { + // extended with unstable pretty-print variants + pretty::parse_pretty(sess, &a, true) + })); + } + RustcDefaultCalls::print_crate_info(sess, Some(input), odir, ofile).and_then( || RustcDefaultCalls::list_metadata(sess, matches, input)) } @@ -370,7 +335,17 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { control.after_llvm.stop = Compilation::Stop; } - if sess.opts.debugging_opts.save_analysis { + if let Some((ppm, opt_uii)) = self.pretty_print.take() { + let phase = pretty::printing_phase(&mut control, ppm, opt_uii.as_ref()); + + phase.callback = box move |state| { + let output = state.output; + pretty::print_from_phase(state, ppm, opt_uii.as_ref(), output).unwrap(); + }; + phase.stop = Compilation::Stop; + } + + if self.save_analysis { control.after_analysis.callback = box |state| { time(state.session.time_passes(), "save analysis", || @@ -387,6 +362,13 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { } impl RustcDefaultCalls { + pub fn new() -> RustcDefaultCalls { + RustcDefaultCalls { + save_analysis: false, + pretty_print: None + } + } + pub fn list_metadata(sess: &Session, matches: &getopts::Matches, input: &Input) diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 1f17439a86afc..4bd02757e0a11 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -15,19 +15,15 @@ pub use self::PpSourceMode::*; pub use self::PpMode::*; use self::NodesMatchingUII::*; -use rustc_trans::back::link; - use driver; use rustc::middle::ty; use rustc::middle::cfg; use rustc::middle::cfg::graphviz::LabelledCFG; use rustc::session::Session; -use rustc::session::config::Input; use rustc::util::ppaux; use rustc_borrowck as borrowck; use rustc_borrowck::graphviz as borrowck_dot; -use rustc_resolve as resolve; use syntax::ast; use syntax::ast_map::{self, blocks, NodePrinter}; @@ -266,7 +262,8 @@ impl UserIdentifiedItem { } } - fn to_one_node_id(self, user_option: &str, sess: &Session, map: &ast_map::Map) -> ast::NodeId { + fn to_one_node_id(&self, user_option: &str, sess: &Session, map: &ast_map::Map) + -> ast::NodeId { let fail_because = |is_wrong_because| -> ast::NodeId { let message = format!("{} needs NodeId (int) or unique \ @@ -295,54 +292,12 @@ impl UserIdentifiedItem { } } -fn needs_ast_map(ppm: PpMode, opt_uii: &Option) -> bool { - match ppm { - PpmSource(PpmNormal) | - PpmSource(PpmEveryBodyLoops) | - PpmSource(PpmIdentified) => opt_uii.is_some(), - - PpmSource(PpmExpanded) | - PpmSource(PpmExpandedIdentified) | - PpmSource(PpmExpandedHygiene) | - PpmSource(PpmTyped) | - PpmFlowGraph(_) => true - } -} - -fn needs_expansion(ppm: PpMode) -> bool { - match ppm { - PpmSource(PpmNormal) | - PpmSource(PpmEveryBodyLoops) | - PpmSource(PpmIdentified) => false, - - PpmSource(PpmExpanded) | - PpmSource(PpmExpandedIdentified) | - PpmSource(PpmExpandedHygiene) | - PpmSource(PpmTyped) | - PpmFlowGraph(_) => true - } -} - -fn needs_types(ppm: PpMode) -> bool { - match ppm { - PpmSource(PpmNormal) | - PpmSource(PpmEveryBodyLoops) | - PpmSource(PpmIdentified) | - PpmSource(PpmExpanded) | - PpmSource(PpmExpandedIdentified) | - PpmSource(PpmExpandedHygiene) => false, - - PpmSource(PpmTyped) | - PpmFlowGraph(_) => true - } -} - -struct ReplaceBodyWithLoop { +pub struct ReplaceBodyWithLoop { within_static_or_const: bool, } impl ReplaceBodyWithLoop { - fn new() -> ReplaceBodyWithLoop { + pub fn new() -> ReplaceBodyWithLoop { ReplaceBodyWithLoop { within_static_or_const: false } } } @@ -395,62 +350,52 @@ impl fold::Folder for ReplaceBodyWithLoop { } } -pub fn pretty_print_input(sess: Session, - cfg: ast::CrateConfig, - input: &Input, - ppm: PpMode, - opt_uii: Option, - ofile: Option) - -> old_io::IoResult<()> { - let krate = driver::phase_1_parse_input(&sess, cfg, input); - - let krate = if let PpmSource(PpmEveryBodyLoops) = ppm { - let mut fold = ReplaceBodyWithLoop::new(); - fold.fold_crate(krate) - } else { - krate - }; - - let id = link::find_crate_name(Some(&sess), &krate.attrs, input); +pub fn printing_phase<'a, 'b>(control: &'a mut driver::CompileController<'b>, + ppm: PpMode, + opt_uii: Option<&UserIdentifiedItem>) + -> &'a mut driver::PhaseController<'b> { + if ppm == PpmSource(PpmEveryBodyLoops) { + control.every_body_loops = true; + } - let compute_ast_map = needs_ast_map(ppm, &opt_uii); - let compute_types = needs_types(ppm); - let krate = if compute_ast_map { - match driver::phase_2_configure_and_expand(&sess, krate, &id[..], None) { - None => return Ok(()), - Some(k) => k + match ppm { + PpmSource(PpmNormal) | + PpmSource(PpmEveryBodyLoops) | + PpmSource(PpmIdentified) => { + if opt_uii.is_some() { + &mut control.after_write_deps + } else { + &mut control.after_parse + } } - } else { - krate - }; - - let mut forest = ast_map::Forest::new(krate); - let arenas = ty::CtxtArenas::new(); - let (krate, ast_map) = if compute_ast_map { - let map = driver::assign_node_ids_and_map(&sess, &mut forest); - (map.krate(), Some(map)) - } else { - (forest.krate(), None) - }; + PpmSource(PpmExpanded) | + PpmSource(PpmExpandedIdentified) | + PpmSource(PpmExpandedHygiene) => { + &mut control.after_write_deps + } - let analysis; - let (ast_map, tcx, sess) = if compute_types { - let ast_map = ast_map.expect("--pretty missing ast_map for type context"); - analysis = driver::phase_3_run_analysis_passes(sess, - ast_map, - &arenas, - id, - resolve::MakeGlobMap::No); - (Some(&analysis.ty_cx.map), Some(&analysis.ty_cx), &analysis.ty_cx.sess) - } else { - (ast_map.as_ref(), None, &sess) - }; + PpmSource(PpmTyped) | + PpmFlowGraph(_) => { + &mut control.after_analysis + } + } +} - let out = match ofile { +pub fn print_from_phase(state: driver::CompileState, + ppm: PpMode, + opt_uii: Option<&UserIdentifiedItem>, + output: Option<&Path>) + -> old_io::IoResult<()> { + let sess = state.session; + let krate = state.krate.or(state.expanded_crate) + .expect("--pretty=typed missing crate"); + let ast_map = state.ast_map.or_else(|| state.tcx.map(|tcx| &tcx.map)); + + let out = match output { None => box old_io::stdout() as Box, Some(p) => { - match old_io::File::create(&p) { + match old_io::File::create(p) { Ok(w) => box w as Box, Err(e) => panic!("print-print failed to open {} due to {}", p.display(), e), @@ -462,7 +407,7 @@ pub fn pretty_print_input(sess: Session, PpmSource(mode) => { debug!("pretty printing source code {:?}", mode); - let typed_annotation = tcx.map(|tcx| TypedAnnotation { tcx: tcx }); + let typed_annotation = state.tcx.map(|tcx| TypedAnnotation { tcx: tcx }); let annotation: &pprust::PpAnn = match mode { PpmNormal | PpmEveryBodyLoops | PpmExpanded => { NO_ANNOTATION @@ -478,13 +423,13 @@ pub fn pretty_print_input(sess: Session, } }; - let is_expanded = needs_expansion(ppm); + let is_expanded = ast_map.is_some(); - let src_name = driver::source_name(input); + let src_name = driver::source_name(state.input); let filemap = sess.codemap().get_filemap(&src_name); let mut rdr = BufReader::new(filemap.src.as_bytes()); - if let Some(ref uii) = opt_uii { + if let Some(uii) = opt_uii { let ast_map = ast_map.expect("--pretty missing ast_map"); let mut pp_state = pprust::State::new_from_input(sess.codemap(), @@ -521,7 +466,7 @@ pub fn pretty_print_input(sess: Session, unique path suffix (b::c::d)")) }); - let tcx = tcx.expect("--pretty flowgraph missing type context"); + let tcx = state.tcx.expect("--pretty flowgraph missing type context"); let nodeid = uii.to_one_node_id("--pretty", sess, &tcx.map); let node = tcx.map.find(nodeid).unwrap_or_else(|| { From d12d31600043563ae6dfe5c54e019f4d1f64bf88 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Fri, 27 Feb 2015 10:39:35 +0200 Subject: [PATCH 05/11] rustc_driver: add -Z pretty-keep-going to continue compilation after pretty-printing. --- src/librustc/session/config.rs | 2 ++ src/librustc_driver/lib.rs | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 536caece21f84..e03b9a43b373b 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -580,6 +580,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "Include assignment analysis data in --pretty flowgraph output"), flowgraph_print_all: bool = (false, parse_bool, "Include all dataflow analysis data in --pretty flowgraph output"), + pretty_keep_going: bool = (false, parse_bool, + "Do not stop after pretty-printing (use with --pretty)"), print_region_graph: bool = (false, parse_bool, "Prints region inference graph. \ Use with RUST_REGION_GRAPH=help for more info"), diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 1556018a0edf0..4400a1796b0ca 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -342,7 +342,10 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { let output = state.output; pretty::print_from_phase(state, ppm, opt_uii.as_ref(), output).unwrap(); }; - phase.stop = Compilation::Stop; + + if !sess.opts.debugging_opts.pretty_keep_going { + phase.stop = Compilation::Stop; + } } if self.save_analysis { From 13d51f4935df1240b058c0a1f5c6ad35cabe472c Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Fri, 27 Feb 2015 10:50:19 +0200 Subject: [PATCH 06/11] rustc_driver: add -Z pretty-dump-dir to specify a directory for bulk --pretty dumps. --- src/librustc/session/config.rs | 2 ++ src/librustc_driver/driver.rs | 27 ++++++++++++++++++------- src/librustc_driver/lib.rs | 37 +++++++++++++++++++++++++++++++--- 3 files changed, 56 insertions(+), 10 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index e03b9a43b373b..e6779dfae409b 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -582,6 +582,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "Include all dataflow analysis data in --pretty flowgraph output"), pretty_keep_going: bool = (false, parse_bool, "Do not stop after pretty-printing (use with --pretty)"), + pretty_dump_dir: Option = (None, parse_opt_string, + "The directory where --pretty output will be saved"), print_region_graph: bool = (false, parse_bool, "Prints region inference graph. \ Use with RUST_REGION_GRAPH=help for more info"), diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 4c8ea60d5363e..569edc19a7915 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -108,6 +108,7 @@ pub fn compile_input(sess: Session, &sess, outdir, output, + &outputs, &expanded_crate, &id[..])); @@ -122,6 +123,7 @@ pub fn compile_input(sess: Session, &sess, outdir, output, + &outputs, &ast_map, &ast_map.krate(), &id[..])); @@ -137,6 +139,7 @@ pub fn compile_input(sess: Session, &analysis.ty_cx.sess, outdir, output, + &outputs, analysis.ty_cx.map.krate(), &analysis, &analysis.ty_cx)); @@ -164,6 +167,7 @@ pub fn compile_input(sess: Session, &sess, outdir, output, + &outputs, &trans)); phase_6_link_output(&sess, &trans, &outputs); @@ -259,17 +263,18 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { fn empty(input: &'a Input, session: &'a Session, out_dir: &'a Option, - output: &'a Option) + output: &'a Option, + output_filenames: Option<&'a OutputFilenames>) -> CompileState<'a, 'tcx> { CompileState { input: input, session: session, out_dir: out_dir.as_ref(), output: output.as_ref(), + output_filenames: output_filenames, cfg: None, krate: None, crate_name: None, - output_filenames: None, expanded_crate: None, ast_map: None, analysis: None, @@ -286,7 +291,7 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { -> CompileState<'a, 'tcx> { CompileState { krate: Some(krate), - .. CompileState::empty(input, session, out_dir, output) + .. CompileState::empty(input, session, out_dir, output, None) } } @@ -294,13 +299,15 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { session: &'a Session, out_dir: &'a Option, output: &'a Option, + output_filenames: &'a OutputFilenames, expanded_crate: &'a ast::Crate, crate_name: &'a str) -> CompileState<'a, 'tcx> { CompileState { crate_name: Some(crate_name), expanded_crate: Some(expanded_crate), - .. CompileState::empty(input, session, out_dir, output) + .. CompileState::empty(input, session, out_dir, output, + Some(output_filenames)) } } @@ -308,6 +315,7 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { session: &'a Session, out_dir: &'a Option, output: &'a Option, + output_filenames: &'a OutputFilenames, ast_map: &'a ast_map::Map<'tcx>, expanded_crate: &'a ast::Crate, crate_name: &'a str) @@ -316,7 +324,8 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { crate_name: Some(crate_name), ast_map: Some(ast_map), expanded_crate: Some(expanded_crate), - .. CompileState::empty(input, session, out_dir, output) + .. CompileState::empty(input, session, out_dir, output, + Some(output_filenames)) } } @@ -324,6 +333,7 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { session: &'a Session, out_dir: &'a Option, output: &'a Option, + output_filenames: &'a OutputFilenames, expanded_crate: &'a ast::Crate, analysis: &'a ty::CrateAnalysis<'tcx>, tcx: &'a ty::ctxt<'tcx>) @@ -332,7 +342,8 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { analysis: Some(analysis), tcx: Some(tcx), expanded_crate: Some(expanded_crate), - .. CompileState::empty(input, session, out_dir, output) + .. CompileState::empty(input, session, out_dir, output, + Some(output_filenames)) } } @@ -341,11 +352,13 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { session: &'a Session, out_dir: &'a Option, output: &'a Option, + output_filenames: &'a OutputFilenames, trans: &'a trans::CrateTranslation) -> CompileState<'a, 'tcx> { CompileState { trans: Some(trans), - .. CompileState::empty(input, session, out_dir, output) + .. CompileState::empty(input, session, out_dir, output, + Some(output_filenames)) } } } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 4400a1796b0ca..69c77be89af18 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -76,6 +76,7 @@ use std::cmp::Ordering::Equal; use std::old_io::{self, stdio}; use std::iter::repeat; use std::env; +use std::os; use std::sync::mpsc::channel; use std::thread; @@ -235,7 +236,8 @@ pub trait CompilerCalls<'a> { // CompilerCalls instance for a regular rustc build. pub struct RustcDefaultCalls { save_analysis: bool, - pretty_print: Option<(PpMode, Option)> + pretty_print: Option<(PpMode, Option)>, + pretty_dump_dir: Option } impl<'a> CompilerCalls<'a> for RustcDefaultCalls { @@ -310,6 +312,12 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { })); } + if let Some(ref dir) = sess.opts.debugging_opts.pretty_dump_dir { + let pretty_dump_dir = os::getcwd().unwrap().join(dir); + assert!(pretty_dump_dir.is_absolute()); + self.pretty_dump_dir = Some(pretty_dump_dir); + } + RustcDefaultCalls::print_crate_info(sess, Some(input), odir, ofile).and_then( || RustcDefaultCalls::list_metadata(sess, matches, input)) } @@ -338,8 +346,30 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { if let Some((ppm, opt_uii)) = self.pretty_print.take() { let phase = pretty::printing_phase(&mut control, ppm, opt_uii.as_ref()); + let dump_dir = self.pretty_dump_dir.take(); phase.callback = box move |state| { - let output = state.output; + let pretty_output_path; + let output = if let Some(ref dir) = dump_dir { + let file_path = if let Some(outputs) = state.output_filenames { + outputs.with_extension("rs") + } else { + state.session.fatal( + "-Z pretty-dump-dir cannot be used with --pretty \ + options that print before expansion"); + }; + let file_path = os::getcwd().unwrap().join(&file_path); + assert!(file_path.is_absolute()); + + // Cheap isomorphism: /foo/bar--bar/baz <-> foo--bar----bar--baz. + let components: Vec<_> = file_path.components().map(|bytes| { + String::from_utf8_lossy(bytes).replace("--", "----") + }).collect(); + + pretty_output_path = dir.join(components.connect("--")); + Some(&pretty_output_path) + } else { + state.output + }; pretty::print_from_phase(state, ppm, opt_uii.as_ref(), output).unwrap(); }; @@ -368,7 +398,8 @@ impl RustcDefaultCalls { pub fn new() -> RustcDefaultCalls { RustcDefaultCalls { save_analysis: false, - pretty_print: None + pretty_print: None, + pretty_dump_dir: None } } From fec2c12c4090a742732e31c6a20d50649406cd24 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Fri, 27 Feb 2015 10:51:37 +0200 Subject: [PATCH 07/11] rustc_driver: use `(expr: T)` in --pretty=typed, instead of `(expr as T)`, as the latter might compile some day. --- src/librustc_driver/pretty.rs | 4 +- src/test/pretty/issue-4264.pp | 70 +++++++++++++++-------------------- 2 files changed, 30 insertions(+), 44 deletions(-) diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 4bd02757e0a11..a115f9c417135 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -181,9 +181,7 @@ impl<'a, 'tcx> pprust::PpAnn for TypedAnnotation<'a, 'tcx> { node: pprust::AnnNode) -> old_io::IoResult<()> { match node { pprust::NodeExpr(expr) => { - try!(pp::space(&mut s.s)); - try!(pp::word(&mut s.s, "as")); - try!(pp::space(&mut s.s)); + try!(s.word_space(":")); try!(pp::word(&mut s.s, &ppaux::ty_to_string( self.tcx, diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index 83ee2bd08f4ad..b993ccd6d1a9e 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -20,18 +20,18 @@ // #4264 fixed-length vector types -pub fn foo(_: [i32; (3 as usize)]) { } +pub fn foo(_: [i32; (3: usize)]) { } pub fn bar() { - const FOO: usize = ((5 as usize) - (4 as usize) as usize); - let _: [(); (FOO as usize)] = ([(() as ())] as [(); 1]); + const FOO: usize = ((5: usize) - (4: usize): usize); + let _: [(); (FOO: usize)] = ([((): ())]: [(); 1]); - let _: [(); (1usize as usize)] = ([(() as ())] as [(); 1]); + let _: [(); (1usize: usize)] = ([((): ())]: [(); 1]); let _ = - (((&((([(1 as i32), (2 as i32), (3 as i32)] as [i32; 3])) as [i32; 3]) - as &[i32; 3]) as *const _ as *const [i32; 3]) as - *const [i32; (3usize as usize)] as *const [i32; 3]); + (((&((([(1: i32), (2: i32), (3: i32)]: [i32; 3])): [i32; 3]): + &[i32; 3]) as *const _: *const [i32; 3]) as + *const [i32; (3usize: usize)]: *const [i32; 3]); @@ -41,56 +41,44 @@ - ((::std::fmt::format as - fn(core::fmt::Arguments<'_>) -> collections::string::String {collections::fmt::format})(((::std::fmt::Arguments::new_v1 - as + ((::std::fmt::format: + fn(core::fmt::Arguments<'_>) -> collections::string::String {collections::fmt::format})(((::std::fmt::Arguments::new_v1: fn(&[&str], &[core::fmt::ArgumentV1<'_>]) -> core::fmt::Arguments<'_> {core::fmt::Arguments<'a>::new_v1})(({ static __STATIC_FMTSTR: &'static [&'static str] = - (&([("test" - as - &'static str)] - as - [&'static str; 1]) - as + (&([("test": + &'static str)]: + [&'static str; 1]): &'static [&'static str; 1]); - (__STATIC_FMTSTR - as + (__STATIC_FMTSTR: &'static [&'static str]) - } - as + }: &[&str]), - (&(match (() - as + (&(match ((): ()) { () => - ([] - as + ([]: [core::fmt::ArgumentV1<'_>; 0]), - } - as - [core::fmt::ArgumentV1<'_>; 0]) - as - &[core::fmt::ArgumentV1<'_>; 0])) - as - core::fmt::Arguments<'_>)) - as collections::string::String); + }: + [core::fmt::ArgumentV1<'_>; 0]): + &[core::fmt::ArgumentV1<'_>; 0])): + core::fmt::Arguments<'_>)): + collections::string::String); } -pub type Foo = [i32; (3 as usize)]; +pub type Foo = [i32; (3: usize)]; pub struct Bar { - pub x: [i32; (3 as usize)], + pub x: [i32; (3: usize)], } -pub struct TupleBar([i32; (4 as usize)]); -pub enum Baz { BazVariant([i32; (5 as usize)]), } -pub fn id(x: T) -> T { (x as T) } +pub struct TupleBar([i32; (4: usize)]); +pub enum Baz { BazVariant([i32; (5: usize)]), } +pub fn id(x: T) -> T { (x: T) } pub fn use_id() { let _ = - ((id::<[i32; (3 as usize)]> as - fn([i32; 3]) -> [i32; 3] {id})(([(1 as i32), (2 as i32), - (3 as i32)] as [i32; 3])) as - [i32; 3]); + ((id::<[i32; (3: usize)]>: + fn([i32; 3]) -> [i32; 3] {id})(([(1: i32), (2: i32), (3: i32)]: + [i32; 3])): [i32; 3]); } fn main() { } From 95593a63153aa61c3a72c2a5700c8b0f282093fd Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Fri, 27 Feb 2015 18:00:43 +0200 Subject: [PATCH 08/11] syntax: support customization of literals in pretty-printing annotators. --- src/libsyntax/ext/quote.rs | 10 +-- src/libsyntax/print/pprust.rs | 161 +++++++++++++++++----------------- 2 files changed, 86 insertions(+), 85 deletions(-) diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index 544fb15dcde7b..3c137351e3814 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -199,7 +199,7 @@ pub mod rt { fn to_source(&self) -> String { let lit = dummy_spanned(ast::LitStr( token::intern_and_get_ident(self), ast::CookedStr)); - pprust::lit_to_string(&lit) + pprust::lit_to_string(&lit).into_owned() } } impl ToSourceWithHygiene for str { @@ -222,7 +222,7 @@ pub mod rt { impl ToSource for bool { fn to_source(&self) -> String { let lit = dummy_spanned(ast::LitBool(*self)); - pprust::lit_to_string(&lit) + pprust::lit_to_string(&lit).into_owned() } } impl ToSourceWithHygiene for bool { @@ -234,7 +234,7 @@ pub mod rt { impl ToSource for char { fn to_source(&self) -> String { let lit = dummy_spanned(ast::LitChar(*self)); - pprust::lit_to_string(&lit) + pprust::lit_to_string(&lit).into_owned() } } impl ToSourceWithHygiene for char { @@ -249,7 +249,7 @@ pub mod rt { fn to_source(&self) -> String { let lit = ast::LitInt(*self as u64, ast::SignedIntLit($tag, ast::Sign::new(*self))); - pprust::lit_to_string(&dummy_spanned(lit)) + pprust::lit_to_string(&dummy_spanned(lit)).into_owned() } } impl ToSourceWithHygiene for $t { @@ -262,7 +262,7 @@ pub mod rt { impl ToSource for $t { fn to_source(&self) -> String { let lit = ast::LitInt(*self as u64, ast::UnsignedIntLit($tag)); - pprust::lit_to_string(&dummy_spanned(lit)) + pprust::lit_to_string(&dummy_spanned(lit)).into_owned() } } impl ToSourceWithHygiene for $t { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index af16e19c9f034..e5e67f66529f4 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -30,6 +30,7 @@ use ptr::P; use std_inject; use std::{ascii, mem}; +use std::borrow::{Cow, IntoCow}; use std::old_io::{self, IoResult}; use std::iter; @@ -45,6 +46,9 @@ pub enum AnnNode<'a> { pub trait PpAnn { fn pre(&self, _state: &mut State, _node: AnnNode) -> IoResult<()> { Ok(()) } fn post(&self, _state: &mut State, _node: AnnNode) -> IoResult<()> { Ok(()) } + fn literal_to_string<'a>(&self, state: &mut State, lit: &'a ast::Lit) -> Cow<'a, str> { + state.literal_to_string(lit) + } } #[derive(Copy)] @@ -309,6 +313,73 @@ pub fn token_to_string(tok: &Token) -> String { } } +fn string_lit_to_string(st: &str, style: ast::StrStyle) -> String { + match style { + ast::CookedStr => { + format!("\"{}\"", st.escape_default()) + } + ast::RawStr(n) => { + format!("r{delim}\"{string}\"{delim}", + delim=repeat("#", n), + string=st) + } + } +} + +pub fn lit_to_string<'a>(lit: &'a ast::Lit) -> Cow<'a, str> { + match lit.node { + ast::LitStr(ref st, style) => { + string_lit_to_string(&st, style).into_cow() + } + ast::LitByte(byte) => { + let mut res = String::from_str("b'"); + res.extend(ascii::escape_default(byte).map(|c| c as char)); + res.push('\''); + res.into_cow() + } + ast::LitChar(ch) => { + let mut res = String::from_str("'"); + res.extend(ch.escape_default()); + res.push('\''); + res.into_cow() + } + ast::LitInt(i, t) => { + match t { + ast::SignedIntLit(st, ast::Plus) => { + ast_util::int_ty_to_string(st, Some(i as i64)) + } + ast::SignedIntLit(st, ast::Minus) => { + let istr = ast_util::int_ty_to_string(st, Some(-(i as i64))); + format!("-{}", istr) + } + ast::UnsignedIntLit(ut) => { + ast_util::uint_ty_to_string(ut, Some(i)) + } + ast::UnsuffixedIntLit(ast::Plus) => { + format!("{}", i) + } + ast::UnsuffixedIntLit(ast::Minus) => { + format!("-{}", i) + } + }.into_cow() + } + ast::LitFloat(ref f, t) => { + format!("{}{}", f, &ast_util::float_ty_to_string(t)).into_cow() + } + ast::LitFloatUnsuffixed(ref f) => f.into_cow(), + ast::LitBool(val) => { + if val { "true" } else { "false" }.into_cow() + } + ast::LitBinary(ref v) => { + let mut escaped: String = String::new(); + for &ch in &**v { + escaped.extend(ascii::escape_default(ch as u8).map(|c| c as char)); + } + format!("b\"{}\"", escaped).into_cow() + } + } +} + // FIXME (Issue #16472): the thing_to_string_impls macro should go away // after we revise the syntax::ext::quote::ToToken impls to go directly // to token-trees instead of thing -> string -> token-trees. @@ -409,10 +480,6 @@ pub fn attribute_to_string(attr: &ast::Attribute) -> String { $to_string(|s| s.print_attribute(attr)) } -pub fn lit_to_string(l: &ast::Lit) -> String { - $to_string(|s| s.print_literal(l)) -} - pub fn explicit_self_to_string(explicit_self: &ast::ExplicitSelf_) -> String { $to_string(|s| s.print_explicit_self(explicit_self, ast::MutImmutable).map(|_| {})) } @@ -1710,7 +1777,8 @@ impl<'a> State<'a> { try!(self.print_expr_addr_of(m, &**expr)); } ast::ExprLit(ref lit) => { - try!(self.print_literal(&**lit)); + let s = self.ann.literal_to_string(self, lit); + try!(word(&mut self.s, &s)); } ast::ExprCast(ref expr, ref ty) => { try!(self.print_expr(&**expr)); @@ -2582,7 +2650,8 @@ impl<'a> State<'a> { ast::MetaNameValue(ref name, ref value) => { try!(self.word_space(&name[..])); try!(self.word_space("=")); - try!(self.print_literal(value)); + let s = self.literal_to_string(value); + try!(word(&mut self.s, &s)); } ast::MetaList(ref name, ref items) => { try!(word(&mut self.s, &name)); @@ -2767,69 +2836,11 @@ impl<'a> State<'a> { Ok(()) } - pub fn print_literal(&mut self, lit: &ast::Lit) -> IoResult<()> { - try!(self.maybe_print_comment(lit.span.lo)); - match self.next_lit(lit.span.lo) { - Some(ref ltrl) => { - return word(&mut self.s, &(*ltrl).lit); - } - _ => () - } - match lit.node { - ast::LitStr(ref st, style) => self.print_string(&st, style), - ast::LitByte(byte) => { - let mut res = String::from_str("b'"); - res.extend(ascii::escape_default(byte).map(|c| c as char)); - res.push('\''); - word(&mut self.s, &res[..]) - } - ast::LitChar(ch) => { - let mut res = String::from_str("'"); - res.extend(ch.escape_default()); - res.push('\''); - word(&mut self.s, &res[..]) - } - ast::LitInt(i, t) => { - match t { - ast::SignedIntLit(st, ast::Plus) => { - word(&mut self.s, - &ast_util::int_ty_to_string(st, Some(i as i64))) - } - ast::SignedIntLit(st, ast::Minus) => { - let istr = ast_util::int_ty_to_string(st, Some(-(i as i64))); - word(&mut self.s, - &format!("-{}", istr)) - } - ast::UnsignedIntLit(ut) => { - word(&mut self.s, &ast_util::uint_ty_to_string(ut, Some(i))) - } - ast::UnsuffixedIntLit(ast::Plus) => { - word(&mut self.s, &format!("{}", i)) - } - ast::UnsuffixedIntLit(ast::Minus) => { - word(&mut self.s, &format!("-{}", i)) - } - } - } - ast::LitFloat(ref f, t) => { - word(&mut self.s, - &format!( - "{}{}", - &f, - &ast_util::float_ty_to_string(t))) - } - ast::LitFloatUnsuffixed(ref f) => word(&mut self.s, &f[..]), - ast::LitBool(val) => { - if val { word(&mut self.s, "true") } else { word(&mut self.s, "false") } - } - ast::LitBinary(ref v) => { - let mut escaped: String = String::new(); - for &ch in &**v { - escaped.extend(ascii::escape_default(ch as u8) - .map(|c| c as char)); - } - word(&mut self.s, &format!("b\"{}\"", escaped)) - } + pub fn literal_to_string<'b>(&mut self, lit: &'b ast::Lit) -> Cow<'b, str> { + if let Some(ltrl) = self.next_lit(lit.span.lo) { + ltrl.lit.into_cow() + } else { + lit_to_string(lit) } } @@ -2916,17 +2927,7 @@ impl<'a> State<'a> { pub fn print_string(&mut self, st: &str, style: ast::StrStyle) -> IoResult<()> { - let st = match style { - ast::CookedStr => { - (format!("\"{}\"", st.escape_default())) - } - ast::RawStr(n) => { - (format!("r{delim}\"{string}\"{delim}", - delim=repeat("#", n), - string=st)) - } - }; - word(&mut self.s, &st[..]) + word(&mut self.s, &string_lit_to_string(st, style)) } pub fn next_comment(&mut self) -> Option { From fbffa94a25e82a00f5dc9a1abdd11df7a09d553e Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Sun, 1 Mar 2015 01:24:44 +0200 Subject: [PATCH 09/11] rustc_driver: add --xpretty typed,unsuffixed_literals (integers and floats). --- src/librustc_driver/pretty.rs | 57 +++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 3 deletions(-) diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index a115f9c417135..ec4fb85e03a50 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -34,6 +34,7 @@ use syntax::ptr::P; use graphviz as dot; +use std::borrow::{Cow, IntoCow}; use std::old_io::{self, BufReader}; use std::option; use std::str::FromStr; @@ -44,6 +45,7 @@ pub enum PpSourceMode { PpmEveryBodyLoops, PpmExpanded, PpmTyped, + PpmTypedUnsuffixedLiterals, PpmIdentified, PpmExpandedIdentified, PpmExpandedHygiene, @@ -76,6 +78,7 @@ pub fn parse_pretty(sess: &Session, ("everybody_loops", true) => PpmSource(PpmEveryBodyLoops), ("expanded", _) => PpmSource(PpmExpanded), ("typed", _) => PpmSource(PpmTyped), + ("typed,unsuffixed_literals", true) => PpmSource(PpmTypedUnsuffixedLiterals), ("expanded,identified", _) => PpmSource(PpmExpandedIdentified), ("expanded,hygiene", _) => PpmSource(PpmExpandedHygiene), ("identified", _) => PpmSource(PpmIdentified), @@ -85,7 +88,8 @@ pub fn parse_pretty(sess: &Session, if extended { sess.fatal(&format!( "argument to `xpretty` must be one of `normal`, \ - `expanded`, `flowgraph[,unlabelled]=`, `typed`, `identified`, \ + `expanded`, `flowgraph[,unlabelled]=`, `typed`, \ + `typed,unsuffixed_literals`, `identified`, \ `expanded,identified`, or `everybody_loops`; got {}", name)); } else { sess.fatal(&format!( @@ -163,6 +167,7 @@ impl pprust::PpAnn for HygieneAnnotation { } } +#[derive(Copy)] struct TypedAnnotation<'a, 'tcx: 'a> { tcx: &'a ty::ctxt<'tcx>, } @@ -193,6 +198,44 @@ impl<'a, 'tcx> pprust::PpAnn for TypedAnnotation<'a, 'tcx> { } } +struct UnsuffixedLitAnnotation { + ann: A +} + +impl pprust::PpAnn for UnsuffixedLitAnnotation { + fn pre(&self, + s: &mut pprust::State, + node: pprust::AnnNode) -> old_io::IoResult<()> { + self.ann.pre(s, node) + } + fn post(&self, + s: &mut pprust::State, + node: pprust::AnnNode) -> old_io::IoResult<()> { + self.ann.post(s, node) + } + fn literal_to_string<'a>(&self, + s: &mut pprust::State, + lit: &'a ast::Lit) -> Cow<'a, str> { + match lit.node { + ast::LitInt(i, t) => { + match t { + ast::UnsignedIntLit(_) | + ast::SignedIntLit(_, ast::Plus) | + ast::UnsuffixedIntLit(ast::Plus) => { + format!("{}", i) + } + ast::SignedIntLit(_, ast::Minus) | + ast::UnsuffixedIntLit(ast::Minus) => { + format!("-{}", i) + } + }.into_cow() + } + ast::LitFloat(ref f, _) => f.into_cow(), + _ => self.ann.literal_to_string(s, lit) + } + } +} + fn gather_flowgraph_variants(sess: &Session) -> Vec { let print_loans = sess.opts.debugging_opts.flowgraph_print_loans; let print_moves = sess.opts.debugging_opts.flowgraph_print_moves; @@ -374,6 +417,7 @@ pub fn printing_phase<'a, 'b>(control: &'a mut driver::CompileController<'b>, } PpmSource(PpmTyped) | + PpmSource(PpmTypedUnsuffixedLiterals) | PpmFlowGraph(_) => { &mut control.after_analysis } @@ -405,7 +449,10 @@ pub fn print_from_phase(state: driver::CompileState, PpmSource(mode) => { debug!("pretty printing source code {:?}", mode); - let typed_annotation = state.tcx.map(|tcx| TypedAnnotation { tcx: tcx }); + let typed_ann = state.tcx.map(|tcx| TypedAnnotation { tcx: tcx }); + let typed_unsuffixed_lit_ann = typed_ann.map(|ann| { + UnsuffixedLitAnnotation { ann: ann } + }); let annotation: &pprust::PpAnn = match mode { PpmNormal | PpmEveryBodyLoops | PpmExpanded => { NO_ANNOTATION @@ -417,7 +464,11 @@ pub fn print_from_phase(state: driver::CompileState, HYGIENE_ANNOTATION } PpmTyped => { - typed_annotation.as_ref().expect("--pretty=typed missing type context") + typed_ann.as_ref().expect("--pretty=typed missing type context") + } + PpmTypedUnsuffixedLiterals => { + typed_unsuffixed_lit_ann.as_ref().expect( + "--xpretty=typed,unsuffixed_literals missing type context") } }; From c082ee21b91c5e9e9f49b5a986d28b3ee11dffdc Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Sun, 1 Mar 2015 01:26:45 +0200 Subject: [PATCH 10/11] rustdoc::test: use build_controller, rather than setting up CompileController manually. --- src/librustdoc/test.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 43e8f44244e78..656e267dcc9a3 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -24,7 +24,7 @@ use rustc_lint; use rustc::session::{self, config}; use rustc::session::config::get_unstable_features_setting; use rustc::session::search_paths::{SearchPaths, PathKind}; -use rustc_driver::{driver, Compilation}; +use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls}; use syntax::codemap::CodeMap; use syntax::diagnostic; @@ -117,8 +117,8 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths, let sessopts = config::Options { maybe_sysroot: Some(os::self_exe_name().unwrap().dir_path().dir_path()), search_paths: libs, - crate_types: vec!(config::CrateTypeExecutable), - output_types: vec!(config::OutputTypeExe), + crate_types: vec![config::CrateTypeExecutable], + output_types: vec![config::OutputTypeExe], externs: externs, cg: config::CodegenOptions { prefer_dynamic: true, @@ -126,6 +126,7 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths, }, test: as_test_harness, unstable_features: get_unstable_features_setting(), + no_trans: no_run, ..config::basic_options().clone() }; @@ -173,10 +174,7 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths, let out = Some(outdir.path().clone()); let cfg = config::build_configuration(&sess); let libdir = sess.target_filesearch(PathKind::All).get_lib_path(); - let mut control = driver::CompileController::basic(); - if no_run { - control.after_analysis.stop = Compilation::Stop; - } + let control = RustcDefaultCalls::new().build_controller(&sess); driver::compile_input(sess, cfg, &input, &out, &None, None, control); if no_run { return } From 496c8ba1adabab5e06f87ba3c72984db4d4a7b5c Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Sun, 1 Mar 2015 02:21:47 +0200 Subject: [PATCH 11/11] rustc_driver: add env var RUSTC_PRETTY_DUMP=mode:dir which acts like --xpretty=mode -Z pretty-keep-going -Z pretty-dump-dir=dir. --- src/librustc_driver/lib.rs | 56 +++---------------- src/librustc_driver/pretty.rs | 102 +++++++++++++++++++++++++++------- 2 files changed, 91 insertions(+), 67 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 69c77be89af18..cbf5f5eccf83f 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -76,7 +76,6 @@ use std::cmp::Ordering::Equal; use std::old_io::{self, stdio}; use std::iter::repeat; use std::env; -use std::os; use std::sync::mpsc::channel; use std::thread; @@ -236,8 +235,7 @@ pub trait CompilerCalls<'a> { // CompilerCalls instance for a regular rustc build. pub struct RustcDefaultCalls { save_analysis: bool, - pretty_print: Option<(PpMode, Option)>, - pretty_dump_dir: Option + pretty_print: Option<(PpMode, Option)> } impl<'a> CompilerCalls<'a> for RustcDefaultCalls { @@ -305,19 +303,13 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { if sess.unstable_options() { self.pretty_print = matches.opt_default("pretty", "normal").map(|a| { // stable pretty-print variants only - pretty::parse_pretty(sess, &a, false) + pretty::parse_pretty(&a, false).unwrap_or_else(|e| sess.fatal(&e)) }).or_else(|| matches.opt_str("xpretty").map(|a| { // extended with unstable pretty-print variants - pretty::parse_pretty(sess, &a, true) + pretty::parse_pretty(&a, true).unwrap_or_else(|e| sess.fatal(&e)) })); } - if let Some(ref dir) = sess.opts.debugging_opts.pretty_dump_dir { - let pretty_dump_dir = os::getcwd().unwrap().join(dir); - assert!(pretty_dump_dir.is_absolute()); - self.pretty_dump_dir = Some(pretty_dump_dir); - } - RustcDefaultCalls::print_crate_info(sess, Some(input), odir, ofile).and_then( || RustcDefaultCalls::list_metadata(sess, matches, input)) } @@ -343,40 +335,11 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { control.after_llvm.stop = Compilation::Stop; } - if let Some((ppm, opt_uii)) = self.pretty_print.take() { - let phase = pretty::printing_phase(&mut control, ppm, opt_uii.as_ref()); - - let dump_dir = self.pretty_dump_dir.take(); - phase.callback = box move |state| { - let pretty_output_path; - let output = if let Some(ref dir) = dump_dir { - let file_path = if let Some(outputs) = state.output_filenames { - outputs.with_extension("rs") - } else { - state.session.fatal( - "-Z pretty-dump-dir cannot be used with --pretty \ - options that print before expansion"); - }; - let file_path = os::getcwd().unwrap().join(&file_path); - assert!(file_path.is_absolute()); - - // Cheap isomorphism: /foo/bar--bar/baz <-> foo--bar----bar--baz. - let components: Vec<_> = file_path.components().map(|bytes| { - String::from_utf8_lossy(bytes).replace("--", "----") - }).collect(); - - pretty_output_path = dir.join(components.connect("--")); - Some(&pretty_output_path) - } else { - state.output - }; - pretty::print_from_phase(state, ppm, opt_uii.as_ref(), output).unwrap(); - }; - - if !sess.opts.debugging_opts.pretty_keep_going { - phase.stop = Compilation::Stop; - } - } + pretty::setup_controller(&mut control, + self.pretty_print.take(), + sess.opts.debugging_opts.pretty_dump_dir + .as_ref().map(|s| &s[..]), + sess.opts.debugging_opts.pretty_keep_going); if self.save_analysis { control.after_analysis.callback = box |state| { @@ -398,8 +361,7 @@ impl RustcDefaultCalls { pub fn new() -> RustcDefaultCalls { RustcDefaultCalls { save_analysis: false, - pretty_print: None, - pretty_dump_dir: None + pretty_print: None } } diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index ec4fb85e03a50..9bdb99d27f8c9 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -35,8 +35,10 @@ use syntax::ptr::P; use graphviz as dot; use std::borrow::{Cow, IntoCow}; +use std::env; use std::old_io::{self, BufReader}; use std::option; +use std::os; use std::str::FromStr; #[derive(Copy, PartialEq, Debug)] @@ -67,9 +69,8 @@ pub enum PpMode { PpmFlowGraph(PpFlowGraphMode), } -pub fn parse_pretty(sess: &Session, - name: &str, - extended: bool) -> (PpMode, Option) { +pub fn parse_pretty(name: &str, extended: bool) + -> Result<(PpMode, Option), String> { let mut split = name.splitn(1, '='); let first = split.next().unwrap(); let opt_second = split.next(); @@ -84,23 +85,23 @@ pub fn parse_pretty(sess: &Session, ("identified", _) => PpmSource(PpmIdentified), ("flowgraph", true) => PpmFlowGraph(PpFlowGraphMode::Default), ("flowgraph,unlabelled", true) => PpmFlowGraph(PpFlowGraphMode::UnlabelledEdges), - _ => { + _ => return Err({ if extended { - sess.fatal(&format!( + format!( "argument to `xpretty` must be one of `normal`, \ `expanded`, `flowgraph[,unlabelled]=`, `typed`, \ `typed,unsuffixed_literals`, `identified`, \ - `expanded,identified`, or `everybody_loops`; got {}", name)); + `expanded,identified`, or `everybody_loops`; got {}", name) } else { - sess.fatal(&format!( + format!( "argument to `pretty` must be one of `normal`, \ `expanded`, `typed`, `identified`, \ - or `expanded,identified`; got {}", name)); + or `expanded,identified`; got {}", name) } - } + }) }; let opt_second = opt_second.and_then(|s| s.parse::().ok()); - (first, opt_second) + Ok((first, opt_second)) } struct NoAnn; @@ -391,15 +392,46 @@ impl fold::Folder for ReplaceBodyWithLoop { } } -pub fn printing_phase<'a, 'b>(control: &'a mut driver::CompileController<'b>, - ppm: PpMode, - opt_uii: Option<&UserIdentifiedItem>) - -> &'a mut driver::PhaseController<'b> { +pub fn setup_controller(control: &mut driver::CompileController, + ppm_and_uui: Option<(PpMode, Option)>, + dump_dir: Option<&str>, + keep_going: bool) { + + fn mk_absolute(path: &str) -> Path { + let path = os::getcwd().unwrap().join(path); + assert!(path.is_absolute()); + path + } + + let (ppm, opt_uii, dump_dir, keep_going) = match ppm_and_uui { + Some((ppm, opt_uii)) => { + (ppm, opt_uii, dump_dir.map(mk_absolute), keep_going) + } + None => { + let decoded = env::var("RUSTC_PRETTY_DUMP").ok().and_then(|s| { + let mut s = s.split(":"); + + s.next().and_then(|mode| { + parse_pretty(mode, true).ok() + }).and_then(|(ppm, opt_uii)| { + s.next().map(|dump_dir| { + (ppm, opt_uii, Some(mk_absolute(dump_dir)), true) + }) + }) + }); + if let Some(parts) = decoded { + parts + } else { + return; + } + } + }; + if ppm == PpmSource(PpmEveryBodyLoops) { control.every_body_loops = true; } - match ppm { + let phase = match ppm { PpmSource(PpmNormal) | PpmSource(PpmEveryBodyLoops) | PpmSource(PpmIdentified) => { @@ -421,14 +453,44 @@ pub fn printing_phase<'a, 'b>(control: &'a mut driver::CompileController<'b>, PpmFlowGraph(_) => { &mut control.after_analysis } + }; + + phase.callback = box move |state| { + let pretty_output_path; + let output = if let Some(ref dir) = dump_dir { + let file_path = if let Some(outputs) = state.output_filenames { + outputs.with_extension("rs") + } else { + state.session.fatal( + "-Z pretty-dump-dir cannot be used with --pretty \ + options that print before expansion"); + }; + let file_path = os::getcwd().unwrap().join(&file_path); + assert!(file_path.is_absolute()); + + // Cheap isomorphism: /foo/bar--bar/baz <-> foo--bar----bar--baz. + let components: Vec<_> = file_path.components().map(|bytes| { + String::from_utf8_lossy(bytes).replace("--", "----") + }).collect(); + + pretty_output_path = dir.join(components.connect("--")); + Some(&pretty_output_path) + } else { + state.output + }; + print_from_phase(state, ppm, opt_uii.as_ref(), output).unwrap(); + }; + + if !keep_going { + phase.stop = ::Compilation::Stop; } } -pub fn print_from_phase(state: driver::CompileState, - ppm: PpMode, - opt_uii: Option<&UserIdentifiedItem>, - output: Option<&Path>) - -> old_io::IoResult<()> { +fn print_from_phase(state: driver::CompileState, + ppm: PpMode, + opt_uii: Option<&UserIdentifiedItem>, + output: Option<&Path>) + -> old_io::IoResult<()> { let sess = state.session; let krate = state.krate.or(state.expanded_crate) .expect("--pretty=typed missing crate");