@@ -16,10 +16,11 @@ use rustc::session::{Session, CompileResult, compile_result_from_err_count};
1616use rustc:: session:: config:: { self , Input , OutputFilenames , OutputType } ;
1717use rustc:: session:: search_paths:: PathKind ;
1818use 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 ;
2121use rustc:: middle;
2222use rustc:: util:: common:: time;
23+ use rustc:: util:: nodemap:: NodeSet ;
2324use rustc_borrowck as borrowck;
2425use rustc_resolve as resolve;
2526use rustc_metadata:: macro_import;
@@ -57,15 +58,6 @@ use syntax::visit;
5758use syntax;
5859use 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-
6961pub 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)
221224pub fn anon_src ( ) -> String {
@@ -269,13 +272,17 @@ impl<'a> CompileController<'a> {
269272
270273pub 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
275281impl < ' 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.
0 commit comments