]> git.lizzy.rs Git - rust.git/commitdiff
Try to run compiler callbacks when we error out
authorNick Cameron <ncameron@mozilla.com>
Wed, 27 Jan 2016 20:49:18 +0000 (09:49 +1300)
committerNick Cameron <ncameron@mozilla.com>
Sun, 31 Jan 2016 19:42:27 +0000 (08:42 +1300)
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_driver/pretty.rs

index 0a5f6d84de16f8cdd52b23fabf6509f2dd3a00db..c189df18a82e1ab93ec205a81ba33f4df04519eb 100644 (file)
 use rustc::session::config::{self, Input, OutputFilenames, OutputType};
 use rustc::session::search_paths::PathKind;
 use rustc::lint;
-use rustc::middle::{stability, ty, reachable};
-use rustc::middle::dependency_format;
+use rustc::middle::{dependency_format, stability, ty, reachable};
+use rustc::middle::privacy::AccessLevels;
 use rustc::middle;
 use rustc::util::common::time;
+use rustc::util::nodemap::NodeSet;
 use rustc_borrowck as borrowck;
 use rustc_resolve as resolve;
 use rustc_metadata::macro_import;
 use syntax;
 use syntax_ext;
 
-macro_rules! throw_if_errors {
-    ($tsess: expr) => {{
-        let err_count = $tsess.err_count();
-        if err_count > 0 {
-            return Err(err_count);
-        }
-    }}
-}
-
 pub fn compile_input(sess: &Session,
                      cstore: &CStore,
                      cfg: ast::CrateConfig,
@@ -74,14 +66,19 @@ pub fn compile_input(sess: &Session,
                      output: &Option<PathBuf>,
                      addl_plugins: Option<Vec<String>>,
                      control: CompileController) -> CompileResult {
-    macro_rules! controller_entry_point{($point: ident, $tsess: expr, $make_state: expr) => ({
-        let state = $make_state;
-        (control.$point.callback)(state);
+    macro_rules! controller_entry_point {
+        ($point: ident, $tsess: expr, $make_state: expr, $phase_result: expr) => {{
+            let state = $make_state;
+            let phase_result: &CompileResult = &$phase_result;
+            if phase_result.is_ok() || control.$point.run_callback_on_error {
+                (control.$point.callback)(state);
+            }
 
-        if control.$point.stop == Compilation::Stop {
-            return compile_result_from_err_count($tsess.err_count());
-        }
-    })}
+            if control.$point.stop == Compilation::Stop {
+                return compile_result_from_err_count($tsess.err_count());
+            }
+        }}
+    }
 
     // We need nested scopes here, because the intermediate results can keep
     // large chunks of memory alive and we want to free them as soon as
@@ -92,7 +89,8 @@ macro_rules! controller_entry_point{($point: ident, $tsess: expr, $make_state: e
 
             controller_entry_point!(after_parse,
                                     sess,
-                                    CompileState::state_after_parse(input, sess, outdir, &krate));
+                                    CompileState::state_after_parse(input, sess, outdir, &krate),
+                                    Ok(()));
 
             let outputs = build_output_filenames(input, outdir, output, &krate.attrs, sess);
             let id = link::find_crate_name(Some(sess), &krate.attrs, input);
@@ -111,7 +109,8 @@ macro_rules! controller_entry_point{($point: ident, $tsess: expr, $make_state: e
                                                                  sess,
                                                                  outdir,
                                                                  &expanded_crate,
-                                                                 &id[..]));
+                                                                 &id[..]),
+                                Ok(()));
 
         let expanded_crate = assign_node_ids(sess, expanded_crate);
         // Lower ast -> hir.
@@ -140,7 +139,8 @@ macro_rules! controller_entry_point{($point: ident, $tsess: expr, $make_state: e
                                                                      &expanded_crate,
                                                                      &hir_map.krate(),
                                                                      &id[..],
-                                                                     &lcx));
+                                                                     &lcx),
+                                Ok(()));
 
         time(sess.time_passes(), "attribute checking", || {
             front::check_attr::check_crate(sess, &expanded_crate);
@@ -159,38 +159,38 @@ macro_rules! controller_entry_point{($point: ident, $tsess: expr, $make_state: e
         };
 
         try!(try!(phase_3_run_analysis_passes(sess,
-                                         &cstore,
-                                         hir_map,
-                                         &arenas,
-                                         &id,
-                                         control.make_glob_map,
-                                         |tcx, mir_map, analysis| {
+                                              &cstore,
+                                              hir_map,
+                                              &arenas,
+                                              &id,
+                                              control.make_glob_map,
+                                              |tcx, mir_map, analysis, result| {
             {
-                let state =
-                    CompileState::state_after_analysis(input,
-                                                       &tcx.sess,
-                                                       outdir,
-                                                       opt_crate,
-                                                       tcx.map.krate(),
-                                                       &analysis,
-                                                       &mir_map,
-                                                       tcx,
-                                                       &lcx,
-                                                       &id);
+                let state = CompileState::state_after_analysis(input,
+                                                               &tcx.sess,
+                                                               outdir,
+                                                               opt_crate,
+                                                               tcx.map.krate(),
+                                                               &analysis,
+                                                               mir_map.as_ref(),
+                                                               tcx,
+                                                               &lcx,
+                                                               &id);
                 (control.after_analysis.callback)(state);
 
-                throw_if_errors!(tcx.sess);
                 if control.after_analysis.stop == Compilation::Stop {
                     return Err(0usize);
                 }
             }
 
+            try!(result);
+
             if log_enabled!(::log::INFO) {
                 println!("Pre-trans");
                 tcx.print_debug_stats();
             }
             let trans = phase_4_translate_to_llvm(tcx,
-                                                  mir_map,
+                                                  mir_map.unwrap(),
                                                   analysis);
 
             if log_enabled!(::log::INFO) {
@@ -205,17 +205,20 @@ macro_rules! controller_entry_point{($point: ident, $tsess: expr, $make_state: e
         })))
     };
 
-    try!(phase_5_run_llvm_passes(sess, &trans, &outputs));
+    let phase5_result = phase_5_run_llvm_passes(sess, &trans, &outputs);
 
     controller_entry_point!(after_llvm,
                             sess,
-                            CompileState::state_after_llvm(input, sess, outdir, &trans));
+                            CompileState::state_after_llvm(input, sess, outdir, &trans),
+                            phase5_result);
+    try!(phase5_result);
 
     phase_6_link_output(sess, &trans, &outputs);
 
     Ok(())
 }
 
+
 /// The name used for source code that doesn't originate in a file
 /// (e.g. source from stdin or a string)
 pub fn anon_src() -> String {
@@ -269,6 +272,9 @@ pub fn basic() -> CompileController<'a> {
 
 pub struct PhaseController<'a> {
     pub stop: Compilation,
+    // If true then the compiler will try to run the callback even if the phase
+    // ends with an error. Note that this is not always possible.
+    pub run_callback_on_error: bool,
     pub callback: Box<Fn(CompileState) -> () + 'a>,
 }
 
@@ -276,6 +282,7 @@ impl<'a> PhaseController<'a> {
     pub fn basic() -> PhaseController<'a> {
         PhaseController {
             stop: Compilation::Continue,
+            run_callback_on_error: false,
             callback: box |_| {},
         }
     }
@@ -372,14 +379,14 @@ fn state_after_analysis(input: &'a Input,
                             krate: Option<&'a ast::Crate>,
                             hir_crate: &'a hir::Crate,
                             analysis: &'a ty::CrateAnalysis,
-                            mir_map: &'a MirMap<'tcx>,
+                            mir_map: Option<&'a MirMap<'tcx>>,
                             tcx: &'a ty::ctxt<'tcx>,
                             lcx: &'a LoweringContext<'a>,
                             crate_name: &'a str)
                             -> CompileState<'a, 'ast, 'tcx> {
         CompileState {
             analysis: Some(analysis),
-            mir_map: Some(mir_map),
+            mir_map: mir_map,
             tcx: Some(tcx),
             krate: krate,
             hir_crate: Some(hir_crate),
@@ -713,8 +720,20 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
                                                make_glob_map: resolve::MakeGlobMap,
                                                f: F)
                                                -> Result<R, usize>
-    where F: for<'a> FnOnce(&'a ty::ctxt<'tcx>, MirMap<'tcx>, ty::CrateAnalysis) -> R
+    where F: FnOnce(&ty::ctxt<'tcx>, Option<MirMap<'tcx>>, ty::CrateAnalysis, CompileResult) -> R
 {
+    macro_rules! try_with_f {
+        ($e: expr, ($t: expr, $m: expr, $a: expr)) => {
+            match $e {
+                Ok(x) => x,
+                Err(x) => {
+                    f($t, $m, $a, Err(x));
+                    return Err(x);
+                }
+            }
+        }
+    }
+
     let time_passes = sess.time_passes();
     let krate = hir_map.krate();
 
@@ -739,6 +758,14 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
              "resolution",
              || resolve::resolve_crate(sess, &hir_map, make_glob_map));
 
+    let mut analysis = ty::CrateAnalysis {
+        export_map: export_map,
+        access_levels: AccessLevels::default(),
+        reachable: NodeSet(),
+        name: name,
+        glob_map: glob_map,
+    };
+
     let named_region_map = try!(time(time_passes,
                                      "lifetime resolution",
                                      || middle::resolve_lifetime::krate(sess,
@@ -776,22 +803,22 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
                                stability::Index::new(krate),
                                |tcx| {
         // passes are timed inside typeck
-        try!(typeck::check_crate(tcx, trait_map));
+        try_with_f!(typeck::check_crate(tcx, trait_map), (tcx, None, analysis));
 
         time(time_passes,
              "const checking",
              || consts::check_crate(tcx));
 
-        let access_levels =
+        analysis.access_levels =
             time(time_passes, "privacy checking", || {
                 rustc_privacy::check_crate(tcx,
-                                           &export_map,
+                                           &analysis.export_map,
                                            external_exports)
             });
 
         // Do not move this check past lint
         time(time_passes, "stability index", || {
-            tcx.stability.borrow_mut().build(tcx, krate, &access_levels)
+            tcx.stability.borrow_mut().build(tcx, krate, &analysis.access_levels)
         });
 
         time(time_passes,
@@ -829,15 +856,17 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
         // lot of annoying errors in the compile-fail tests (basically,
         // lint warnings and so on -- kindck used to do this abort, but
         // kindck is gone now). -nmatsakis
-        throw_if_errors!(tcx.sess);
+        if sess.err_count() > 0 {
+            return Ok(f(tcx, Some(mir_map), analysis, Err(sess.err_count())));
+        }
 
-        let reachable_map =
+        analysis.reachable =
             time(time_passes,
                  "reachability checking",
-                 || reachable::find_reachable(tcx, &access_levels));
+                 || reachable::find_reachable(tcx, &analysis.access_levels));
 
         time(time_passes, "death checking", || {
-            middle::dead::check_crate(tcx, &access_levels);
+            middle::dead::check_crate(tcx, &analysis.access_levels);
         });
 
         let ref lib_features_used =
@@ -852,20 +881,14 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
 
         time(time_passes,
              "lint checking",
-             || lint::check_crate(tcx, &access_levels));
+             || lint::check_crate(tcx, &analysis.access_levels));
 
         // The above three passes generate errors w/o aborting
-        throw_if_errors!(tcx.sess);
-
-        Ok(f(tcx,
-          mir_map,
-          ty::CrateAnalysis {
-              export_map: export_map,
-              access_levels: access_levels,
-              reachable: reachable_map,
-              name: name,
-              glob_map: glob_map,
-          }))
+        if sess.err_count() > 0 {
+            return Ok(f(tcx, Some(mir_map), analysis, Err(sess.err_count())));
+        }
+
+        Ok(f(tcx, Some(mir_map), analysis, Ok(())))
     })
 }
 
@@ -915,8 +938,11 @@ pub fn phase_5_run_llvm_passes(sess: &Session,
              || write::run_passes(sess, trans, &sess.opts.output_types, outputs));
     }
 
-    throw_if_errors!(sess);
-    Ok(())
+    if sess.err_count() > 0 {
+        Err(sess.err_count())
+    } else {
+        Ok(())
+    }
 }
 
 /// Run the linker on any artifacts that resulted from the LLVM run.
index baeef135d75706c6b00eb109d7b06eb201e60bfa..70bd938321a8e70250ebed79c08188ad570e4610 100644 (file)
@@ -134,7 +134,7 @@ pub fn run(args: Vec<String>) -> isize {
                         let mut emitter =
                             errors::emitter::BasicEmitter::stderr(errors::ColorConfig::Auto);
                         emitter.emit(None, &abort_msg(err_count), None, errors::Level::Fatal);
-                        panic!(errors::FatalError);
+                        exit_on_err();
                     }
                 }
             }
@@ -450,6 +450,7 @@ fn build_controller(&mut self, sess: &Session) -> CompileController<'a> {
                                         state.out_dir)
                 });
             };
+            control.after_analysis.run_callback_on_error = true;
             control.make_glob_map = resolve::MakeGlobMap::Yes;
         }
 
@@ -935,15 +936,19 @@ fn flush(&mut self) -> io::Result<()> {
                 println!("{}", str::from_utf8(&data.lock().unwrap()).unwrap());
             }
 
-            // Panic so the process returns a failure code, but don't pollute the
-            // output with some unnecessary panic messages, we've already
-            // printed everything that we needed to.
-            io::set_panic(box io::sink());
-            panic!();
+            exit_on_err();
         }
     }
 }
 
+fn exit_on_err() -> ! {
+    // Panic so the process returns a failure code, but don't pollute the
+    // output with some unnecessary panic messages, we've already
+    // printed everything that we needed to.
+    io::set_panic(box io::sink());
+    panic!();
+}
+
 pub fn diagnostics_registry() -> diagnostics::registry::Registry {
     use syntax::diagnostics::registry::Registry;
 
index 1e99067bf32ed9e0a5bc8c9ec0425418b2ebcb94..91af78a5bd4fbaaf92ac171aec970f67cb98bbde 100644 (file)
@@ -200,7 +200,7 @@ fn call_with_pp_support_hir<'tcx, A, B, F>(&self,
                                                                  arenas,
                                                                  id,
                                                                  resolve::MakeGlobMap::No,
-                                                                 |tcx, _, _| {
+                                                                 |tcx, _, _, _| {
                     let annotation = TypedAnnotation {
                         tcx: tcx,
                     };
@@ -824,7 +824,7 @@ pub fn pretty_print_input(sess: Session,
                                                                      &arenas,
                                                                      &id,
                                                                      resolve::MakeGlobMap::No,
-                                                                     |tcx, _, _| {
+                                                                     |tcx, _, _, _| {
                         print_flowgraph(variants,
                                         tcx,
                                         code,