Skip to content

Commit 6bd782c

Browse files
committed
Try to run compiler callbacks when we error out
1 parent b6e4f18 commit 6bd782c

File tree

3 files changed

+106
-75
lines changed

3 files changed

+106
-75
lines changed

src/librustc_driver/driver.rs

Lines changed: 93 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@ use rustc::session::{Session, CompileResult, compile_result_from_err_count};
1616
use rustc::session::config::{self, Input, OutputFilenames, OutputType};
1717
use rustc::session::search_paths::PathKind;
1818
use rustc::lint;
19-
use rustc::middle::{stability, ty, reachable};
20-
use rustc::middle::dependency_format;
19+
use rustc::middle::{dependency_format, stability, ty, reachable};
20+
use rustc::middle::privacy::AccessLevels;
2121
use rustc::middle;
2222
use rustc::util::common::time;
23+
use rustc::util::nodemap::NodeSet;
2324
use rustc_borrowck as borrowck;
2425
use rustc_resolve as resolve;
2526
use rustc_metadata::macro_import;
@@ -57,15 +58,6 @@ use syntax::visit;
5758
use syntax;
5859
use syntax_ext;
5960

60-
macro_rules! throw_if_errors {
61-
($tsess: expr) => {{
62-
let err_count = $tsess.err_count();
63-
if err_count > 0 {
64-
return Err(err_count);
65-
}
66-
}}
67-
}
68-
6961
pub fn compile_input(sess: &Session,
7062
cstore: &CStore,
7163
cfg: ast::CrateConfig,
@@ -74,14 +66,19 @@ pub fn compile_input(sess: &Session,
7466
output: &Option<PathBuf>,
7567
addl_plugins: Option<Vec<String>>,
7668
control: CompileController) -> CompileResult {
77-
macro_rules! controller_entry_point{($point: ident, $tsess: expr, $make_state: expr) => ({
78-
let state = $make_state;
79-
(control.$point.callback)(state);
69+
macro_rules! controller_entry_point {
70+
($point: ident, $tsess: expr, $make_state: expr, $phase_result: expr) => {{
71+
let state = $make_state;
72+
let phase_result: &CompileResult = &$phase_result;
73+
if phase_result.is_ok() || control.$point.run_callback_on_error {
74+
(control.$point.callback)(state);
75+
}
8076

81-
if control.$point.stop == Compilation::Stop {
82-
return compile_result_from_err_count($tsess.err_count());
83-
}
84-
})}
77+
if control.$point.stop == Compilation::Stop {
78+
return compile_result_from_err_count($tsess.err_count());
79+
}
80+
}}
81+
}
8582

8683
// We need nested scopes here, because the intermediate results can keep
8784
// large chunks of memory alive and we want to free them as soon as
@@ -92,7 +89,8 @@ pub fn compile_input(sess: &Session,
9289

9390
controller_entry_point!(after_parse,
9491
sess,
95-
CompileState::state_after_parse(input, sess, outdir, &krate));
92+
CompileState::state_after_parse(input, sess, outdir, &krate),
93+
Ok(()));
9694

9795
let outputs = build_output_filenames(input, outdir, output, &krate.attrs, sess);
9896
let id = link::find_crate_name(Some(sess), &krate.attrs, input);
@@ -111,7 +109,8 @@ pub fn compile_input(sess: &Session,
111109
sess,
112110
outdir,
113111
&expanded_crate,
114-
&id[..]));
112+
&id[..]),
113+
Ok(()));
115114

116115
let expanded_crate = assign_node_ids(sess, expanded_crate);
117116
// Lower ast -> hir.
@@ -140,7 +139,8 @@ pub fn compile_input(sess: &Session,
140139
&expanded_crate,
141140
&hir_map.krate(),
142141
&id[..],
143-
&lcx));
142+
&lcx),
143+
Ok(()));
144144

145145
time(sess.time_passes(), "attribute checking", || {
146146
front::check_attr::check_crate(sess, &expanded_crate);
@@ -159,38 +159,38 @@ pub fn compile_input(sess: &Session,
159159
};
160160

161161
try!(try!(phase_3_run_analysis_passes(sess,
162-
&cstore,
163-
hir_map,
164-
&arenas,
165-
&id,
166-
control.make_glob_map,
167-
|tcx, mir_map, analysis| {
162+
&cstore,
163+
hir_map,
164+
&arenas,
165+
&id,
166+
control.make_glob_map,
167+
|tcx, mir_map, analysis, result| {
168168
{
169-
let state =
170-
CompileState::state_after_analysis(input,
171-
&tcx.sess,
172-
outdir,
173-
opt_crate,
174-
tcx.map.krate(),
175-
&analysis,
176-
&mir_map,
177-
tcx,
178-
&lcx,
179-
&id);
169+
let state = CompileState::state_after_analysis(input,
170+
&tcx.sess,
171+
outdir,
172+
opt_crate,
173+
tcx.map.krate(),
174+
&analysis,
175+
mir_map.as_ref(),
176+
tcx,
177+
&lcx,
178+
&id);
180179
(control.after_analysis.callback)(state);
181180

182-
throw_if_errors!(tcx.sess);
183181
if control.after_analysis.stop == Compilation::Stop {
184182
return Err(0usize);
185183
}
186184
}
187185

186+
try!(result);
187+
188188
if log_enabled!(::log::INFO) {
189189
println!("Pre-trans");
190190
tcx.print_debug_stats();
191191
}
192192
let trans = phase_4_translate_to_llvm(tcx,
193-
mir_map,
193+
mir_map.unwrap(),
194194
analysis);
195195

196196
if log_enabled!(::log::INFO) {
@@ -205,17 +205,20 @@ pub fn compile_input(sess: &Session,
205205
})))
206206
};
207207

208-
try!(phase_5_run_llvm_passes(sess, &trans, &outputs));
208+
let phase5_result = phase_5_run_llvm_passes(sess, &trans, &outputs);
209209

210210
controller_entry_point!(after_llvm,
211211
sess,
212-
CompileState::state_after_llvm(input, sess, outdir, &trans));
212+
CompileState::state_after_llvm(input, sess, outdir, &trans),
213+
phase5_result);
214+
try!(phase5_result);
213215

214216
phase_6_link_output(sess, &trans, &outputs);
215217

216218
Ok(())
217219
}
218220

221+
219222
/// The name used for source code that doesn't originate in a file
220223
/// (e.g. source from stdin or a string)
221224
pub fn anon_src() -> String {
@@ -269,13 +272,17 @@ impl<'a> CompileController<'a> {
269272

270273
pub struct PhaseController<'a> {
271274
pub stop: Compilation,
275+
// If true then the compiler will try to run the callback even if the phase
276+
// ends with an error. Note that this is not always possible.
277+
pub run_callback_on_error: bool,
272278
pub callback: Box<Fn(CompileState) -> () + 'a>,
273279
}
274280

275281
impl<'a> PhaseController<'a> {
276282
pub fn basic() -> PhaseController<'a> {
277283
PhaseController {
278284
stop: Compilation::Continue,
285+
run_callback_on_error: false,
279286
callback: box |_| {},
280287
}
281288
}
@@ -372,14 +379,14 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> {
372379
krate: Option<&'a ast::Crate>,
373380
hir_crate: &'a hir::Crate,
374381
analysis: &'a ty::CrateAnalysis,
375-
mir_map: &'a MirMap<'tcx>,
382+
mir_map: Option<&'a MirMap<'tcx>>,
376383
tcx: &'a ty::ctxt<'tcx>,
377384
lcx: &'a LoweringContext<'a>,
378385
crate_name: &'a str)
379386
-> CompileState<'a, 'ast, 'tcx> {
380387
CompileState {
381388
analysis: Some(analysis),
382-
mir_map: Some(mir_map),
389+
mir_map: mir_map,
383390
tcx: Some(tcx),
384391
krate: krate,
385392
hir_crate: Some(hir_crate),
@@ -713,8 +720,20 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
713720
make_glob_map: resolve::MakeGlobMap,
714721
f: F)
715722
-> Result<R, usize>
716-
where F: for<'a> FnOnce(&'a ty::ctxt<'tcx>, MirMap<'tcx>, ty::CrateAnalysis) -> R
723+
where F: FnOnce(&ty::ctxt<'tcx>, Option<MirMap<'tcx>>, ty::CrateAnalysis, CompileResult) -> R
717724
{
725+
macro_rules! try_with_f {
726+
($e: expr, ($t: expr, $m: expr, $a: expr)) => {
727+
match $e {
728+
Ok(x) => x,
729+
Err(x) => {
730+
f($t, $m, $a, Err(x));
731+
return Err(x);
732+
}
733+
}
734+
}
735+
}
736+
718737
let time_passes = sess.time_passes();
719738
let krate = hir_map.krate();
720739

@@ -739,6 +758,14 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
739758
"resolution",
740759
|| resolve::resolve_crate(sess, &hir_map, make_glob_map));
741760

761+
let mut analysis = ty::CrateAnalysis {
762+
export_map: export_map,
763+
access_levels: AccessLevels::default(),
764+
reachable: NodeSet(),
765+
name: name,
766+
glob_map: glob_map,
767+
};
768+
742769
let named_region_map = try!(time(time_passes,
743770
"lifetime resolution",
744771
|| middle::resolve_lifetime::krate(sess,
@@ -776,22 +803,22 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
776803
stability::Index::new(krate),
777804
|tcx| {
778805
// passes are timed inside typeck
779-
try!(typeck::check_crate(tcx, trait_map));
806+
try_with_f!(typeck::check_crate(tcx, trait_map), (tcx, None, analysis));
780807

781808
time(time_passes,
782809
"const checking",
783810
|| consts::check_crate(tcx));
784811

785-
let access_levels =
812+
analysis.access_levels =
786813
time(time_passes, "privacy checking", || {
787814
rustc_privacy::check_crate(tcx,
788-
&export_map,
815+
&analysis.export_map,
789816
external_exports)
790817
});
791818

792819
// Do not move this check past lint
793820
time(time_passes, "stability index", || {
794-
tcx.stability.borrow_mut().build(tcx, krate, &access_levels)
821+
tcx.stability.borrow_mut().build(tcx, krate, &analysis.access_levels)
795822
});
796823

797824
time(time_passes,
@@ -829,15 +856,17 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
829856
// lot of annoying errors in the compile-fail tests (basically,
830857
// lint warnings and so on -- kindck used to do this abort, but
831858
// kindck is gone now). -nmatsakis
832-
throw_if_errors!(tcx.sess);
859+
if sess.err_count() > 0 {
860+
return Ok(f(tcx, Some(mir_map), analysis, Err(sess.err_count())));
861+
}
833862

834-
let reachable_map =
863+
analysis.reachable =
835864
time(time_passes,
836865
"reachability checking",
837-
|| reachable::find_reachable(tcx, &access_levels));
866+
|| reachable::find_reachable(tcx, &analysis.access_levels));
838867

839868
time(time_passes, "death checking", || {
840-
middle::dead::check_crate(tcx, &access_levels);
869+
middle::dead::check_crate(tcx, &analysis.access_levels);
841870
});
842871

843872
let ref lib_features_used =
@@ -852,20 +881,14 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
852881

853882
time(time_passes,
854883
"lint checking",
855-
|| lint::check_crate(tcx, &access_levels));
884+
|| lint::check_crate(tcx, &analysis.access_levels));
856885

857886
// The above three passes generate errors w/o aborting
858-
throw_if_errors!(tcx.sess);
859-
860-
Ok(f(tcx,
861-
mir_map,
862-
ty::CrateAnalysis {
863-
export_map: export_map,
864-
access_levels: access_levels,
865-
reachable: reachable_map,
866-
name: name,
867-
glob_map: glob_map,
868-
}))
887+
if sess.err_count() > 0 {
888+
return Ok(f(tcx, Some(mir_map), analysis, Err(sess.err_count())));
889+
}
890+
891+
Ok(f(tcx, Some(mir_map), analysis, Ok(())))
869892
})
870893
}
871894

@@ -915,8 +938,11 @@ pub fn phase_5_run_llvm_passes(sess: &Session,
915938
|| write::run_passes(sess, trans, &sess.opts.output_types, outputs));
916939
}
917940

918-
throw_if_errors!(sess);
919-
Ok(())
941+
if sess.err_count() > 0 {
942+
Err(sess.err_count())
943+
} else {
944+
Ok(())
945+
}
920946
}
921947

922948
/// Run the linker on any artifacts that resulted from the LLVM run.

src/librustc_driver/lib.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ pub fn run(args: Vec<String>) -> isize {
134134
let mut emitter =
135135
errors::emitter::BasicEmitter::stderr(errors::ColorConfig::Auto);
136136
emitter.emit(None, &abort_msg(err_count), None, errors::Level::Fatal);
137-
panic!(errors::FatalError);
137+
exit_on_err();
138138
}
139139
}
140140
}
@@ -450,6 +450,7 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
450450
state.out_dir)
451451
});
452452
};
453+
control.after_analysis.run_callback_on_error = true;
453454
control.make_glob_map = resolve::MakeGlobMap::Yes;
454455
}
455456

@@ -935,15 +936,19 @@ pub fn monitor<F: FnOnce() + Send + 'static>(f: F) {
935936
println!("{}", str::from_utf8(&data.lock().unwrap()).unwrap());
936937
}
937938

938-
// Panic so the process returns a failure code, but don't pollute the
939-
// output with some unnecessary panic messages, we've already
940-
// printed everything that we needed to.
941-
io::set_panic(box io::sink());
942-
panic!();
939+
exit_on_err();
943940
}
944941
}
945942
}
946943

944+
fn exit_on_err() -> ! {
945+
// Panic so the process returns a failure code, but don't pollute the
946+
// output with some unnecessary panic messages, we've already
947+
// printed everything that we needed to.
948+
io::set_panic(box io::sink());
949+
panic!();
950+
}
951+
947952
pub fn diagnostics_registry() -> diagnostics::registry::Registry {
948953
use syntax::diagnostics::registry::Registry;
949954

src/librustc_driver/pretty.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ impl PpSourceMode {
200200
arenas,
201201
id,
202202
resolve::MakeGlobMap::No,
203-
|tcx, _, _| {
203+
|tcx, _, _, _| {
204204
let annotation = TypedAnnotation {
205205
tcx: tcx,
206206
};
@@ -824,7 +824,7 @@ pub fn pretty_print_input(sess: Session,
824824
&arenas,
825825
&id,
826826
resolve::MakeGlobMap::No,
827-
|tcx, _, _| {
827+
|tcx, _, _, _| {
828828
print_flowgraph(variants,
829829
tcx,
830830
code,

0 commit comments

Comments
 (0)