Skip to content

Commit b8b18aa

Browse files
committed
Auto merge of #31206 - nrc:early-save, r=nikomatsakis
r? @nikomatsakis
2 parents aba11b3 + 7b47f5e commit b8b18aa

File tree

8 files changed

+331
-265
lines changed

8 files changed

+331
-265
lines changed

src/librustc/session/mod.rs

+18-5
Original file line numberDiff line numberDiff line change
@@ -176,15 +176,28 @@ impl Session {
176176
pub fn abort_if_errors(&self) {
177177
self.diagnostic().abort_if_errors();
178178
}
179-
pub fn abort_if_new_errors<F, T>(&self, f: F) -> T
179+
pub fn track_errors<F, T>(&self, f: F) -> Result<T, usize>
180180
where F: FnOnce() -> T
181181
{
182-
let count = self.err_count();
182+
let mut count = self.err_count();
183183
let result = f();
184-
if self.err_count() > count {
185-
self.abort_if_errors();
184+
count -= self.err_count();
185+
if count == 0 {
186+
Ok(result)
187+
} else {
188+
Err(count)
189+
}
190+
}
191+
pub fn abort_if_new_errors<F, T>(&self, f: F) -> T
192+
where F: FnOnce() -> T
193+
{
194+
match self.track_errors(f) {
195+
Ok(result) => result,
196+
Err(_) => {
197+
self.abort_if_errors();
198+
unreachable!();
199+
}
186200
}
187-
result
188201
}
189202
pub fn span_warn(&self, sp: Span, msg: &str) {
190203
self.diagnostic().span_warn(sp, msg)

src/librustc_driver/driver.rs

+203-202
Large diffs are not rendered by default.

src/librustc_driver/lib.rs

+60-13
Original file line numberDiff line numberDiff line change
@@ -105,57 +105,103 @@ pub mod target_features;
105105
const BUG_REPORT_URL: &'static str = "https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.\
106106
md#bug-reports";
107107

108+
// Err(0) means compilation was stopped, but no errors were found.
109+
// This would be better as a dedicated enum, but using try! is so convenient.
110+
pub type CompileResult = Result<(), usize>;
111+
112+
pub fn compile_result_from_err_count(err_count: usize) -> CompileResult {
113+
if err_count == 0 {
114+
Ok(())
115+
} else {
116+
Err(err_count)
117+
}
118+
}
119+
120+
#[inline]
121+
fn abort_msg(err_count: usize) -> String {
122+
match err_count {
123+
0 => "aborting with no errors (maybe a bug?)".to_owned(),
124+
1 => "aborting due to previous error".to_owned(),
125+
e => format!("aborting due to {} previous errors", e),
126+
}
127+
}
128+
129+
pub fn abort_on_err<T>(result: Result<T, usize>, sess: &Session) -> T {
130+
match result {
131+
Err(err_count) => {
132+
sess.fatal(&abort_msg(err_count));
133+
}
134+
Ok(x) => x,
135+
}
136+
}
137+
108138
pub fn run(args: Vec<String>) -> isize {
109-
monitor(move || run_compiler(&args, &mut RustcDefaultCalls));
139+
monitor(move || {
140+
let (result, session) = run_compiler(&args, &mut RustcDefaultCalls);
141+
if let Err(err_count) = result {
142+
if err_count > 0 {
143+
match session {
144+
Some(sess) => sess.fatal(&abort_msg(err_count)),
145+
None => {
146+
let mut emitter =
147+
errors::emitter::BasicEmitter::stderr(errors::ColorConfig::Auto);
148+
emitter.emit(None, &abort_msg(err_count), None, errors::Level::Fatal);
149+
panic!(errors::FatalError);
150+
}
151+
}
152+
}
153+
}
154+
});
110155
0
111156
}
112157

113158
// Parse args and run the compiler. This is the primary entry point for rustc.
114159
// See comments on CompilerCalls below for details about the callbacks argument.
115-
pub fn run_compiler<'a>(args: &[String], callbacks: &mut CompilerCalls<'a>) {
116-
macro_rules! do_or_return {($expr: expr) => {
160+
pub fn run_compiler<'a>(args: &[String],
161+
callbacks: &mut CompilerCalls<'a>)
162+
-> (CompileResult, Option<Session>) {
163+
macro_rules! do_or_return {($expr: expr, $sess: expr) => {
117164
match $expr {
118-
Compilation::Stop => return,
165+
Compilation::Stop => return (Ok(()), $sess),
119166
Compilation::Continue => {}
120167
}
121168
}}
122169

123170
let matches = match handle_options(args.to_vec()) {
124171
Some(matches) => matches,
125-
None => return,
172+
None => return (Ok(()), None),
126173
};
127174

128175
let sopts = config::build_session_options(&matches);
129176

130177
let descriptions = diagnostics_registry();
131178

132-
do_or_return!(callbacks.early_callback(&matches, &descriptions, sopts.error_format));
179+
do_or_return!(callbacks.early_callback(&matches, &descriptions, sopts.error_format), None);
133180

134181
let (odir, ofile) = make_output(&matches);
135182
let (input, input_file_path) = match make_input(&matches.free) {
136183
Some((input, input_file_path)) => callbacks.some_input(input, input_file_path),
137184
None => match callbacks.no_input(&matches, &sopts, &odir, &ofile, &descriptions) {
138185
Some((input, input_file_path)) => (input, input_file_path),
139-
None => return,
186+
None => return (Ok(()), None),
140187
},
141188
};
142189

143190
let cstore = Rc::new(CStore::new(token::get_ident_interner()));
144-
let sess = build_session(sopts, input_file_path, descriptions,
145-
cstore.clone());
191+
let sess = build_session(sopts, input_file_path, descriptions, cstore.clone());
146192
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
147193
let mut cfg = config::build_configuration(&sess);
148194
target_features::add_configuration(&mut cfg, &sess);
149195

150-
do_or_return!(callbacks.late_callback(&matches, &sess, &input, &odir, &ofile));
196+
do_or_return!(callbacks.late_callback(&matches, &sess, &input, &odir, &ofile), Some(sess));
151197

152198
// It is somewhat unfortunate that this is hardwired in - this is forced by
153199
// the fact that pretty_print_input requires the session by value.
154200
let pretty = callbacks.parse_pretty(&sess, &matches);
155201
match pretty {
156202
Some((ppm, opt_uii)) => {
157203
pretty::pretty_print_input(sess, &cstore, cfg, &input, ppm, opt_uii, ofile);
158-
return;
204+
return (Ok(()), None);
159205
}
160206
None => {
161207
// continue
@@ -164,8 +210,9 @@ pub fn run_compiler<'a>(args: &[String], callbacks: &mut CompilerCalls<'a>) {
164210

165211
let plugins = sess.opts.debugging_opts.extra_plugins.clone();
166212
let control = callbacks.build_controller(&sess);
167-
driver::compile_input(sess, &cstore, cfg, &input, &odir, &ofile,
168-
Some(plugins), control);
213+
(driver::compile_input(&sess, &cstore, cfg, &input, &odir, &ofile,
214+
Some(plugins), control),
215+
Some(sess))
169216
}
170217

171218
// Extract output directory and file from matches.

src/librustc_driver/pretty.rs

+31-31
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use self::NodesMatchingUII::*;
1717

1818
use rustc_trans::back::link;
1919

20-
use driver;
20+
use {driver, abort_on_err};
2121

2222
use rustc::middle::ty;
2323
use rustc::middle::cfg;
@@ -194,21 +194,21 @@ impl PpSourceMode {
194194
f(&annotation, payload, &ast_map.forest.krate)
195195
}
196196
PpmTyped => {
197-
driver::phase_3_run_analysis_passes(sess,
198-
cstore,
199-
ast_map.clone(),
200-
arenas,
201-
id,
202-
resolve::MakeGlobMap::No,
203-
|tcx, _, _| {
204-
let annotation = TypedAnnotation {
205-
tcx: tcx,
206-
};
207-
let _ignore = tcx.dep_graph.in_ignore();
208-
f(&annotation,
209-
payload,
210-
&ast_map.forest.krate)
211-
})
197+
abort_on_err(driver::phase_3_run_analysis_passes(sess,
198+
cstore,
199+
ast_map.clone(),
200+
arenas,
201+
id,
202+
resolve::MakeGlobMap::No,
203+
|tcx, _, _| {
204+
let annotation = TypedAnnotation {
205+
tcx: tcx,
206+
};
207+
let _ignore = tcx.dep_graph.in_ignore();
208+
f(&annotation,
209+
payload,
210+
&ast_map.forest.krate)
211+
}), sess)
212212
}
213213
_ => panic!("Should use call_with_pp_support"),
214214
}
@@ -694,8 +694,8 @@ pub fn pretty_print_input(sess: Session,
694694
let compute_ast_map = needs_ast_map(&ppm, &opt_uii);
695695
let krate = if compute_ast_map {
696696
match driver::phase_2_configure_and_expand(&sess, &cstore, krate, &id[..], None) {
697-
None => return,
698-
Some(k) => driver::assign_node_ids(&sess, k),
697+
Err(_) => return,
698+
Ok(k) => driver::assign_node_ids(&sess, k),
699699
}
700700
} else {
701701
krate
@@ -818,19 +818,19 @@ pub fn pretty_print_input(sess: Session,
818818
match code {
819819
Some(code) => {
820820
let variants = gather_flowgraph_variants(&sess);
821-
driver::phase_3_run_analysis_passes(&sess,
822-
&cstore,
823-
ast_map,
824-
&arenas,
825-
&id,
826-
resolve::MakeGlobMap::No,
827-
|tcx, _, _| {
828-
print_flowgraph(variants,
829-
tcx,
830-
code,
831-
mode,
832-
out)
833-
})
821+
abort_on_err(driver::phase_3_run_analysis_passes(&sess,
822+
&cstore,
823+
ast_map,
824+
&arenas,
825+
&id,
826+
resolve::MakeGlobMap::No,
827+
|tcx, _, _| {
828+
print_flowgraph(variants,
829+
tcx,
830+
code,
831+
mode,
832+
out)
833+
}), &sess)
834834
}
835835
None => {
836836
let message = format!("--pretty=flowgraph needs block, fn, or method; got \

src/librustdoc/core.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
pub use self::MaybeTyped::*;
1111

1212
use rustc_lint;
13-
use rustc_driver::{driver, target_features};
13+
use rustc_driver::{driver, target_features, abort_on_err};
1414
use rustc::session::{self, config};
1515
use rustc::middle::def_id::DefId;
1616
use rustc::middle::privacy::AccessLevels;
@@ -147,13 +147,13 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
147147
let arenas = ty::CtxtArenas::new();
148148
let hir_map = driver::make_map(&sess, &mut hir_forest);
149149

150-
driver::phase_3_run_analysis_passes(&sess,
151-
&cstore,
152-
hir_map,
153-
&arenas,
154-
&name,
155-
resolve::MakeGlobMap::No,
156-
|tcx, _, analysis| {
150+
abort_on_err(driver::phase_3_run_analysis_passes(&sess,
151+
&cstore,
152+
hir_map,
153+
&arenas,
154+
&name,
155+
resolve::MakeGlobMap::No,
156+
|tcx, _, analysis| {
157157
let _ignore = tcx.dep_graph.in_ignore();
158158
let ty::CrateAnalysis { access_levels, .. } = analysis;
159159

@@ -200,5 +200,5 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
200200
*analysis.inlined.borrow_mut() = map;
201201
analysis.deref_trait_did = ctxt.deref_trait_did.get();
202202
(krate, analysis)
203-
})
203+
}), &sess)
204204
}

src/librustdoc/test.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,12 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec<String>, libs: SearchPaths,
250250
if no_run {
251251
control.after_analysis.stop = Compilation::Stop;
252252
}
253-
driver::compile_input(sess, &cstore, cfg, &input, &out, &None, None, control);
253+
let result = driver::compile_input(&sess, &cstore, cfg, &input,
254+
&out, &None, None, control);
255+
match result {
256+
Err(count) if count > 0 => sess.fatal("aborting due to previous error(s)"),
257+
_ => {}
258+
}
254259

255260
if no_run { return }
256261

src/test/run-make/execution-engine/test.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use rustc::middle::cstore::{CrateStore, LinkagePreference};
3232
use rustc::middle::ty;
3333
use rustc::session::config::{self, basic_options, build_configuration, Input, Options};
3434
use rustc::session::build_session;
35-
use rustc_driver::driver;
35+
use rustc_driver::{driver, abort_on_err};
3636
use rustc_front::lowering::{lower_crate, LoweringContext};
3737
use rustc_resolve::MakeGlobMap;
3838
use rustc_metadata::cstore::CStore;
@@ -234,7 +234,7 @@ fn compile_program(input: &str, sysroot: PathBuf)
234234
let arenas = ty::CtxtArenas::new();
235235
let ast_map = driver::make_map(&sess, &mut hir_forest);
236236

237-
driver::phase_3_run_analysis_passes(
237+
abort_on_err(driver::phase_3_run_analysis_passes(
238238
&sess, &cstore, ast_map, &arenas, &id,
239239
MakeGlobMap::No, |tcx, mir_map, analysis| {
240240

@@ -254,7 +254,7 @@ fn compile_program(input: &str, sysroot: PathBuf)
254254
let modp = llmod as usize;
255255

256256
(modp, deps)
257-
})
257+
}), &sess)
258258
}).unwrap();
259259

260260
match handle.join() {

src/test/run-make/issue-19371/foo.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
6565
let cfg = build_configuration(&sess);
6666
let control = CompileController::basic();
6767

68-
compile_input(sess, &cstore,
68+
compile_input(&sess, &cstore,
6969
cfg,
7070
&Input::Str(code),
7171
&None,

0 commit comments

Comments
 (0)