@@ -16,10 +16,11 @@ use rustc::session::{Session, CompileResult, compile_result_from_err_count};
16
16
use rustc:: session:: config:: { self , Input , OutputFilenames , OutputType } ;
17
17
use rustc:: session:: search_paths:: PathKind ;
18
18
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 ;
21
21
use rustc:: middle;
22
22
use rustc:: util:: common:: time;
23
+ use rustc:: util:: nodemap:: NodeSet ;
23
24
use rustc_borrowck as borrowck;
24
25
use rustc_resolve as resolve;
25
26
use rustc_metadata:: macro_import;
@@ -57,15 +58,6 @@ use syntax::visit;
57
58
use syntax;
58
59
use syntax_ext;
59
60
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
-
69
61
pub fn compile_input ( sess : & Session ,
70
62
cstore : & CStore ,
71
63
cfg : ast:: CrateConfig ,
@@ -74,14 +66,19 @@ pub fn compile_input(sess: &Session,
74
66
output : & Option < PathBuf > ,
75
67
addl_plugins : Option < Vec < String > > ,
76
68
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
+ }
80
76
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
+ }
85
82
86
83
// We need nested scopes here, because the intermediate results can keep
87
84
// large chunks of memory alive and we want to free them as soon as
@@ -92,7 +89,8 @@ pub fn compile_input(sess: &Session,
92
89
93
90
controller_entry_point ! ( after_parse,
94
91
sess,
95
- CompileState :: state_after_parse( input, sess, outdir, & krate) ) ;
92
+ CompileState :: state_after_parse( input, sess, outdir, & krate) ,
93
+ Ok ( ( ) ) ) ;
96
94
97
95
let outputs = build_output_filenames ( input, outdir, output, & krate. attrs , sess) ;
98
96
let id = link:: find_crate_name ( Some ( sess) , & krate. attrs , input) ;
@@ -111,7 +109,8 @@ pub fn compile_input(sess: &Session,
111
109
sess,
112
110
outdir,
113
111
& expanded_crate,
114
- & id[ ..] ) ) ;
112
+ & id[ ..] ) ,
113
+ Ok ( ( ) ) ) ;
115
114
116
115
let expanded_crate = assign_node_ids ( sess, expanded_crate) ;
117
116
// Lower ast -> hir.
@@ -140,7 +139,8 @@ pub fn compile_input(sess: &Session,
140
139
& expanded_crate,
141
140
& hir_map. krate( ) ,
142
141
& id[ ..] ,
143
- & lcx) ) ;
142
+ & lcx) ,
143
+ Ok ( ( ) ) ) ;
144
144
145
145
time ( sess. time_passes ( ) , "attribute checking" , || {
146
146
front:: check_attr:: check_crate ( sess, & expanded_crate) ;
@@ -159,38 +159,38 @@ pub fn compile_input(sess: &Session,
159
159
} ;
160
160
161
161
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 | {
168
168
{
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) ;
180
179
( control. after_analysis . callback ) ( state) ;
181
180
182
- throw_if_errors ! ( tcx. sess) ;
183
181
if control. after_analysis . stop == Compilation :: Stop {
184
182
return Err ( 0usize ) ;
185
183
}
186
184
}
187
185
186
+ try!( result) ;
187
+
188
188
if log_enabled ! ( :: log:: INFO ) {
189
189
println ! ( "Pre-trans" ) ;
190
190
tcx. print_debug_stats ( ) ;
191
191
}
192
192
let trans = phase_4_translate_to_llvm ( tcx,
193
- mir_map,
193
+ mir_map. unwrap ( ) ,
194
194
analysis) ;
195
195
196
196
if log_enabled ! ( :: log:: INFO ) {
@@ -205,17 +205,20 @@ pub fn compile_input(sess: &Session,
205
205
} ) ) )
206
206
} ;
207
207
208
- try! ( phase_5_run_llvm_passes ( sess, & trans, & outputs) ) ;
208
+ let phase5_result = phase_5_run_llvm_passes ( sess, & trans, & outputs) ;
209
209
210
210
controller_entry_point ! ( after_llvm,
211
211
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) ;
213
215
214
216
phase_6_link_output ( sess, & trans, & outputs) ;
215
217
216
218
Ok ( ( ) )
217
219
}
218
220
221
+
219
222
/// The name used for source code that doesn't originate in a file
220
223
/// (e.g. source from stdin or a string)
221
224
pub fn anon_src ( ) -> String {
@@ -269,13 +272,17 @@ impl<'a> CompileController<'a> {
269
272
270
273
pub struct PhaseController < ' a > {
271
274
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 ,
272
278
pub callback : Box < Fn ( CompileState ) -> ( ) + ' a > ,
273
279
}
274
280
275
281
impl < ' a > PhaseController < ' a > {
276
282
pub fn basic ( ) -> PhaseController < ' a > {
277
283
PhaseController {
278
284
stop : Compilation :: Continue ,
285
+ run_callback_on_error : false ,
279
286
callback : box |_| { } ,
280
287
}
281
288
}
@@ -372,14 +379,14 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> {
372
379
krate : Option < & ' a ast:: Crate > ,
373
380
hir_crate : & ' a hir:: Crate ,
374
381
analysis : & ' a ty:: CrateAnalysis ,
375
- mir_map : & ' a MirMap < ' tcx > ,
382
+ mir_map : Option < & ' a MirMap < ' tcx > > ,
376
383
tcx : & ' a ty:: ctxt < ' tcx > ,
377
384
lcx : & ' a LoweringContext < ' a > ,
378
385
crate_name : & ' a str )
379
386
-> CompileState < ' a , ' ast , ' tcx > {
380
387
CompileState {
381
388
analysis : Some ( analysis) ,
382
- mir_map : Some ( mir_map) ,
389
+ mir_map : mir_map,
383
390
tcx : Some ( tcx) ,
384
391
krate : krate,
385
392
hir_crate : Some ( hir_crate) ,
@@ -713,8 +720,20 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
713
720
make_glob_map : resolve:: MakeGlobMap ,
714
721
f : F )
715
722
-> 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
717
724
{
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
+
718
737
let time_passes = sess. time_passes ( ) ;
719
738
let krate = hir_map. krate ( ) ;
720
739
@@ -739,6 +758,14 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
739
758
"resolution" ,
740
759
|| resolve:: resolve_crate ( sess, & hir_map, make_glob_map) ) ;
741
760
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
+
742
769
let named_region_map = try!( time ( time_passes,
743
770
"lifetime resolution" ,
744
771
|| middle:: resolve_lifetime:: krate ( sess,
@@ -776,22 +803,22 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
776
803
stability:: Index :: new ( krate) ,
777
804
|tcx| {
778
805
// 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 ) ) ;
780
807
781
808
time ( time_passes,
782
809
"const checking" ,
783
810
|| consts:: check_crate ( tcx) ) ;
784
811
785
- let access_levels =
812
+ analysis . access_levels =
786
813
time ( time_passes, "privacy checking" , || {
787
814
rustc_privacy:: check_crate ( tcx,
788
- & export_map,
815
+ & analysis . export_map ,
789
816
external_exports)
790
817
} ) ;
791
818
792
819
// Do not move this check past lint
793
820
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 )
795
822
} ) ;
796
823
797
824
time ( time_passes,
@@ -829,15 +856,17 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
829
856
// lot of annoying errors in the compile-fail tests (basically,
830
857
// lint warnings and so on -- kindck used to do this abort, but
831
858
// 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
+ }
833
862
834
- let reachable_map =
863
+ analysis . reachable =
835
864
time ( time_passes,
836
865
"reachability checking" ,
837
- || reachable:: find_reachable ( tcx, & access_levels) ) ;
866
+ || reachable:: find_reachable ( tcx, & analysis . access_levels ) ) ;
838
867
839
868
time ( time_passes, "death checking" , || {
840
- middle:: dead:: check_crate ( tcx, & access_levels) ;
869
+ middle:: dead:: check_crate ( tcx, & analysis . access_levels ) ;
841
870
} ) ;
842
871
843
872
let ref lib_features_used =
@@ -852,20 +881,14 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
852
881
853
882
time ( time_passes,
854
883
"lint checking" ,
855
- || lint:: check_crate ( tcx, & access_levels) ) ;
884
+ || lint:: check_crate ( tcx, & analysis . access_levels ) ) ;
856
885
857
886
// 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 ( ( ) ) ) )
869
892
} )
870
893
}
871
894
@@ -915,8 +938,11 @@ pub fn phase_5_run_llvm_passes(sess: &Session,
915
938
|| write:: run_passes ( sess, trans, & sess. opts . output_types , outputs) ) ;
916
939
}
917
940
918
- throw_if_errors ! ( sess) ;
919
- Ok ( ( ) )
941
+ if sess. err_count ( ) > 0 {
942
+ Err ( sess. err_count ( ) )
943
+ } else {
944
+ Ok ( ( ) )
945
+ }
920
946
}
921
947
922
948
/// Run the linker on any artifacts that resulted from the LLVM run.
0 commit comments