@@ -30,7 +30,7 @@ use std::ops::Range;
30
30
use std:: path:: PathBuf ;
31
31
use std:: str:: FromStr ;
32
32
use std:: sync:: Arc ;
33
- use std:: sync:: atomic:: { AtomicBool , Ordering } ;
33
+ use std:: sync:: atomic:: { AtomicBool , AtomicI32 , Ordering } ;
34
34
35
35
use miri:: {
36
36
BacktraceStyle , BorrowTrackerMethod , MiriConfig , ProvenanceMode , RetagFields , ValidationMode ,
@@ -59,11 +59,16 @@ use tracing::debug;
59
59
60
60
struct MiriCompilerCalls {
61
61
miri_config : Option < MiriConfig > ,
62
- many_seeds : Option < Range < u32 > > ,
62
+ many_seeds : Option < ManySeedsConfig > ,
63
+ }
64
+
65
+ struct ManySeedsConfig {
66
+ seeds : Range < u32 > ,
67
+ keep_going : bool ,
63
68
}
64
69
65
70
impl MiriCompilerCalls {
66
- fn new ( miri_config : MiriConfig , many_seeds : Option < Range < u32 > > ) -> Self {
71
+ fn new ( miri_config : MiriConfig , many_seeds : Option < ManySeedsConfig > ) -> Self {
67
72
Self { miri_config : Some ( miri_config) , many_seeds }
68
73
}
69
74
}
@@ -176,19 +181,24 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
176
181
177
182
if let Some ( many_seeds) = self . many_seeds . take ( ) {
178
183
assert ! ( config. seed. is_none( ) ) ;
179
- sync:: par_for_each_in ( many_seeds, |seed| {
184
+ let exit_code = sync:: IntoDynSyncSend ( AtomicI32 :: new ( rustc_driver:: EXIT_SUCCESS ) ) ;
185
+ sync:: par_for_each_in ( many_seeds. seeds , |seed| {
180
186
let mut config = config. clone ( ) ;
181
187
config. seed = Some ( seed. into ( ) ) ;
182
188
eprintln ! ( "Trying seed: {seed}" ) ;
183
189
let return_code = miri:: eval_entry ( tcx, entry_def_id, entry_type, config)
184
190
. unwrap_or ( rustc_driver:: EXIT_FAILURE ) ;
185
191
if return_code != rustc_driver:: EXIT_SUCCESS {
186
192
eprintln ! ( "FAILING SEED: {seed}" ) ;
187
- tcx. dcx ( ) . abort_if_errors ( ) ; // exits with a different error message
188
- std:: process:: exit ( return_code) ;
193
+ if !many_seeds. keep_going {
194
+ // `abort_if_errors` would actually not stop, since `par_for_each` waits for the
195
+ // rest of the to finish, so we just exit immediately.
196
+ std:: process:: exit ( return_code) ;
197
+ }
198
+ exit_code. store ( return_code, Ordering :: Relaxed ) ;
189
199
}
190
200
} ) ;
191
- std:: process:: exit ( rustc_driver :: EXIT_SUCCESS ) ;
201
+ std:: process:: exit ( exit_code . 0 . into_inner ( ) ) ;
192
202
} else {
193
203
let return_code = miri:: eval_entry ( tcx, entry_def_id, entry_type, config)
194
204
. unwrap_or_else ( || {
@@ -500,6 +510,7 @@ fn main() {
500
510
501
511
// Parse our arguments and split them across `rustc` and `miri`.
502
512
let mut many_seeds: Option < Range < u32 > > = None ;
513
+ let mut many_seeds_keep_going = false ;
503
514
let mut miri_config = MiriConfig :: default ( ) ;
504
515
miri_config. env = env_snapshot;
505
516
@@ -611,6 +622,8 @@ fn main() {
611
622
many_seeds = Some ( range) ;
612
623
} else if arg == "-Zmiri-many-seeds" {
613
624
many_seeds = Some ( 0 ..64 ) ;
625
+ } else if arg == "-Zmiri-many-seeds-keep-going" {
626
+ many_seeds_keep_going = true ;
614
627
} else if let Some ( _param) = arg. strip_prefix ( "-Zmiri-env-exclude=" ) {
615
628
show_error ! (
616
629
"`-Zmiri-env-exclude` has been removed; unset env vars before starting Miri instead"
@@ -736,6 +749,8 @@ fn main() {
736
749
std:: thread:: available_parallelism( ) . map_or( 1 , |n| n. get( ) )
737
750
) ) ;
738
751
}
752
+ let many_seeds =
753
+ many_seeds. map ( |seeds| ManySeedsConfig { seeds, keep_going : many_seeds_keep_going } ) ;
739
754
740
755
debug ! ( "rustc arguments: {:?}" , rustc_args) ;
741
756
debug ! ( "crate arguments: {:?}" , miri_config. args) ;
0 commit comments