@@ -30,7 +30,7 @@ use std::ops::Range;
3030use std:: path:: PathBuf ;
3131use std:: str:: FromStr ;
3232use std:: sync:: Arc ;
33- use std:: sync:: atomic:: { AtomicBool , Ordering } ;
33+ use std:: sync:: atomic:: { AtomicBool , AtomicI32 , Ordering } ;
3434
3535use miri:: {
3636 BacktraceStyle , BorrowTrackerMethod , MiriConfig , ProvenanceMode , RetagFields , ValidationMode ,
@@ -59,11 +59,16 @@ use tracing::debug;
5959
6060struct MiriCompilerCalls {
6161 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 ,
6368}
6469
6570impl MiriCompilerCalls {
66- fn new ( miri_config : MiriConfig , many_seeds : Option < Range < u32 > > ) -> Self {
71+ fn new ( miri_config : MiriConfig , many_seeds : Option < ManySeedsConfig > ) -> Self {
6772 Self { miri_config : Some ( miri_config) , many_seeds }
6873 }
6974}
@@ -176,19 +181,24 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
176181
177182 if let Some ( many_seeds) = self . many_seeds . take ( ) {
178183 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| {
180186 let mut config = config. clone ( ) ;
181187 config. seed = Some ( seed. into ( ) ) ;
182188 eprintln ! ( "Trying seed: {seed}" ) ;
183189 let return_code = miri:: eval_entry ( tcx, entry_def_id, entry_type, config)
184190 . unwrap_or ( rustc_driver:: EXIT_FAILURE ) ;
185191 if return_code != rustc_driver:: EXIT_SUCCESS {
186192 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 ) ;
189199 }
190200 } ) ;
191- std:: process:: exit ( rustc_driver :: EXIT_SUCCESS ) ;
201+ std:: process:: exit ( exit_code . 0 . into_inner ( ) ) ;
192202 } else {
193203 let return_code = miri:: eval_entry ( tcx, entry_def_id, entry_type, config)
194204 . unwrap_or_else ( || {
@@ -500,6 +510,7 @@ fn main() {
500510
501511 // Parse our arguments and split them across `rustc` and `miri`.
502512 let mut many_seeds: Option < Range < u32 > > = None ;
513+ let mut many_seeds_keep_going = false ;
503514 let mut miri_config = MiriConfig :: default ( ) ;
504515 miri_config. env = env_snapshot;
505516
@@ -611,6 +622,8 @@ fn main() {
611622 many_seeds = Some ( range) ;
612623 } else if arg == "-Zmiri-many-seeds" {
613624 many_seeds = Some ( 0 ..64 ) ;
625+ } else if arg == "-Zmiri-many-seeds-keep-going" {
626+ many_seeds_keep_going = true ;
614627 } else if let Some ( _param) = arg. strip_prefix ( "-Zmiri-env-exclude=" ) {
615628 show_error ! (
616629 "`-Zmiri-env-exclude` has been removed; unset env vars before starting Miri instead"
@@ -736,6 +749,8 @@ fn main() {
736749 std:: thread:: available_parallelism( ) . map_or( 1 , |n| n. get( ) )
737750 ) ) ;
738751 }
752+ let many_seeds =
753+ many_seeds. map ( |seeds| ManySeedsConfig { seeds, keep_going : many_seeds_keep_going } ) ;
739754
740755 debug ! ( "rustc arguments: {:?}" , rustc_args) ;
741756 debug ! ( "crate arguments: {:?}" , miri_config. args) ;
0 commit comments