@@ -105,57 +105,103 @@ pub mod target_features;
105105const 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+
108138pub 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.
0 commit comments