@@ -104,57 +104,103 @@ pub mod target_features;
104104const BUG_REPORT_URL : & ' static str = "https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.\
105105 md#bug-reports";
106106
107+ // Err(0) means compilation was stopped, but no errors were found.
108+ // This would be better as a dedicated enum, but using try! is so convenient.
109+ pub type CompileResult = Result < ( ) , usize > ;
110+
111+ pub fn compile_result_from_err_count ( err_count : usize ) -> CompileResult {
112+ if err_count == 0 {
113+ Ok ( ( ) )
114+ } else {
115+ Err ( err_count)
116+ }
117+ }
118+
119+ #[ inline]
120+ fn abort_msg ( err_count : usize ) -> String {
121+ match err_count {
122+ 0 => "aborting with no errors (maybe a bug?)" . to_owned ( ) ,
123+ 1 => "aborting due to previous error" . to_owned ( ) ,
124+ e => format ! ( "aborting due to {} previous errors" , e) ,
125+ }
126+ }
127+
128+ pub fn abort_on_err < T > ( result : Result < T , usize > , sess : & Session ) -> T {
129+ match result {
130+ Err ( err_count) => {
131+ sess. fatal ( & abort_msg ( err_count) ) ;
132+ }
133+ Ok ( x) => x,
134+ }
135+ }
136+
107137pub fn run ( args : Vec < String > ) -> isize {
108- monitor ( move || run_compiler ( & args, & mut RustcDefaultCalls ) ) ;
138+ monitor ( move || {
139+ let ( result, session) = run_compiler ( & args, & mut RustcDefaultCalls ) ;
140+ if let Err ( err_count) = result {
141+ if err_count > 0 {
142+ match session {
143+ Some ( sess) => sess. fatal ( & abort_msg ( err_count) ) ,
144+ None => {
145+ let mut emitter =
146+ errors:: emitter:: BasicEmitter :: stderr ( errors:: ColorConfig :: Auto ) ;
147+ emitter. emit ( None , & abort_msg ( err_count) , None , errors:: Level :: Fatal ) ;
148+ panic ! ( errors:: FatalError ) ;
149+ }
150+ }
151+ }
152+ }
153+ } ) ;
109154 0
110155}
111156
112157// Parse args and run the compiler. This is the primary entry point for rustc.
113158// See comments on CompilerCalls below for details about the callbacks argument.
114- pub fn run_compiler < ' a > ( args : & [ String ] , callbacks : & mut CompilerCalls < ' a > ) {
115- macro_rules! do_or_return { ( $expr: expr) => {
159+ pub fn run_compiler < ' a > ( args : & [ String ] ,
160+ callbacks : & mut CompilerCalls < ' a > )
161+ -> ( CompileResult , Option < Session > ) {
162+ macro_rules! do_or_return { ( $expr: expr, $sess: expr) => {
116163 match $expr {
117- Compilation :: Stop => return ,
164+ Compilation :: Stop => return ( Ok ( ( ) ) , $sess ) ,
118165 Compilation :: Continue => { }
119166 }
120167 } }
121168
122169 let matches = match handle_options ( args. to_vec ( ) ) {
123170 Some ( matches) => matches,
124- None => return ,
171+ None => return ( Ok ( ( ) ) , None ) ,
125172 } ;
126173
127174 let sopts = config:: build_session_options ( & matches) ;
128175
129176 let descriptions = diagnostics_registry ( ) ;
130177
131- do_or_return ! ( callbacks. early_callback( & matches, & descriptions, sopts. error_format) ) ;
178+ do_or_return ! ( callbacks. early_callback( & matches, & descriptions, sopts. error_format) , None ) ;
132179
133180 let ( odir, ofile) = make_output ( & matches) ;
134181 let ( input, input_file_path) = match make_input ( & matches. free ) {
135182 Some ( ( input, input_file_path) ) => callbacks. some_input ( input, input_file_path) ,
136183 None => match callbacks. no_input ( & matches, & sopts, & odir, & ofile, & descriptions) {
137184 Some ( ( input, input_file_path) ) => ( input, input_file_path) ,
138- None => return ,
185+ None => return ( Ok ( ( ) ) , None ) ,
139186 } ,
140187 } ;
141188
142189 let cstore = Rc :: new ( CStore :: new ( token:: get_ident_interner ( ) ) ) ;
143- let sess = build_session ( sopts, input_file_path, descriptions,
144- cstore. clone ( ) ) ;
190+ let sess = build_session ( sopts, input_file_path, descriptions, cstore. clone ( ) ) ;
145191 rustc_lint:: register_builtins ( & mut sess. lint_store . borrow_mut ( ) , Some ( & sess) ) ;
146192 let mut cfg = config:: build_configuration ( & sess) ;
147193 target_features:: add_configuration ( & mut cfg, & sess) ;
148194
149- do_or_return ! ( callbacks. late_callback( & matches, & sess, & input, & odir, & ofile) ) ;
195+ do_or_return ! ( callbacks. late_callback( & matches, & sess, & input, & odir, & ofile) , Some ( sess ) ) ;
150196
151197 // It is somewhat unfortunate that this is hardwired in - this is forced by
152198 // the fact that pretty_print_input requires the session by value.
153199 let pretty = callbacks. parse_pretty ( & sess, & matches) ;
154200 match pretty {
155201 Some ( ( ppm, opt_uii) ) => {
156202 pretty:: pretty_print_input ( sess, & cstore, cfg, & input, ppm, opt_uii, ofile) ;
157- return ;
203+ return ( Ok ( ( ) ) , None ) ;
158204 }
159205 None => {
160206 // continue
@@ -163,8 +209,9 @@ pub fn run_compiler<'a>(args: &[String], callbacks: &mut CompilerCalls<'a>) {
163209
164210 let plugins = sess. opts . debugging_opts . extra_plugins . clone ( ) ;
165211 let control = callbacks. build_controller ( & sess) ;
166- driver:: compile_input ( sess, & cstore, cfg, & input, & odir, & ofile,
167- Some ( plugins) , control) ;
212+ ( driver:: compile_input ( & sess, & cstore, cfg, & input, & odir, & ofile,
213+ Some ( plugins) , control) ,
214+ Some ( sess) )
168215}
169216
170217// Extract output directory and file from matches.
0 commit comments