@@ -378,6 +378,74 @@ path = "lib.rs"
378378 }
379379}
380380
381+ enum CargoTargets {
382+ All ,
383+ Filtered { lib : bool , bin : Vec < String > , test : Vec < String > } ,
384+ }
385+
386+ impl CargoTargets {
387+ fn matches ( & self , kind : & str , name : & str ) -> bool {
388+ match self {
389+ CargoTargets :: All => true ,
390+ CargoTargets :: Filtered { lib, bin, test } => match kind {
391+ "lib" => * lib,
392+ "bin" => bin. iter ( ) . any ( |n| n == name) ,
393+ "test" => test. iter ( ) . any ( |n| n == name) ,
394+ _ => false ,
395+ } ,
396+ }
397+ }
398+ }
399+
400+ fn parse_cargo_miri_args (
401+ mut args : impl Iterator < Item = String > ,
402+ ) -> ( CargoTargets , Vec < String > , Vec < String > ) {
403+ let mut lib_present = false ;
404+ let mut bin_targets = Vec :: new ( ) ;
405+ let mut test_targets = Vec :: new ( ) ;
406+ let mut additional_args = Vec :: new ( ) ;
407+ while let Some ( arg) = args. next ( ) {
408+ match arg {
409+ arg if arg == "--" => {
410+ // Miri arguments begin after the first "--".
411+ break ;
412+ }
413+ arg if arg == "--lib" => lib_present = true ,
414+ arg if arg == "--bin" => {
415+ if let Some ( binary) = args. next ( ) {
416+ if binary == "--" {
417+ show_error ( format ! ( "\" --bin\" takes one argument." ) ) ;
418+ } else {
419+ bin_targets. push ( binary)
420+ }
421+ } else {
422+ show_error ( format ! ( "\" --bin\" takes one argument." ) ) ;
423+ }
424+ }
425+ arg if arg. starts_with ( "--bin=" ) => bin_targets. push ( ( & arg[ "--bin=" . len ( ) ..] ) . to_string ( ) ) ,
426+ arg if arg == "--test" => {
427+ if let Some ( test) = args. next ( ) {
428+ if test == "--" {
429+ show_error ( format ! ( "\" --test\" takes one argument." ) ) ;
430+ } else {
431+ test_targets. push ( test)
432+ }
433+ } else {
434+ show_error ( format ! ( "\" --test\" takes one argument." ) ) ;
435+ }
436+ }
437+ arg if arg. starts_with ( "--test=" ) => test_targets. push ( ( & arg[ "--test=" . len ( ) ..] ) . to_string ( ) ) ,
438+ other => additional_args. push ( other) ,
439+ }
440+ }
441+ let targets = if !lib_present && bin_targets. len ( ) == 0 && test_targets. len ( ) == 0 {
442+ CargoTargets :: All
443+ } else {
444+ CargoTargets :: Filtered { lib : lib_present, bin : bin_targets, test : test_targets }
445+ } ;
446+ ( targets, additional_args, args. collect ( ) )
447+ }
448+
381449fn in_cargo_miri ( ) {
382450 let ( subcommand, skip) = match std:: env:: args ( ) . nth ( 2 ) . as_deref ( ) {
383451 Some ( "test" ) => ( MiriCommand :: Test , 3 ) ,
@@ -398,22 +466,27 @@ fn in_cargo_miri() {
398466 return ;
399467 }
400468
469+ // FIXME: this accepts --test, --lib, and multiple --bin for `cargo miri run`.
470+ let ( target_filters, cargo_args, miri_args) =
471+ parse_cargo_miri_args ( std:: env:: args ( ) . skip ( skip) ) ;
472+
401473 // Now run the command.
402474 for target in list_targets ( ) {
403- let mut args = std:: env:: args ( ) . skip ( skip) ;
404475 let kind = target
405476 . kind
406477 . get ( 0 )
407478 . expect ( "badly formatted cargo metadata: target::kind is an empty array" ) ;
479+ if !target_filters. matches ( kind, & target. name ) {
480+ continue ;
481+ }
408482 // Now we run `cargo check $FLAGS $ARGS`, giving the user the
409483 // change to add additional arguments. `FLAGS` is set to identify
410484 // this target. The user gets to control what gets actually passed to Miri.
411485 let mut cmd = cargo ( ) ;
412486 cmd. arg ( "check" ) ;
413487 match ( subcommand, kind. as_str ( ) ) {
414488 ( MiriCommand :: Run , "bin" ) => {
415- // FIXME: we just run all the binaries here.
416- // We should instead support `cargo miri --bin foo`.
489+ // FIXME: we default to running all binaries here.
417490 cmd. arg ( "--bin" ) . arg ( target. name ) ;
418491 }
419492 ( MiriCommand :: Test , "test" ) => {
@@ -429,11 +502,8 @@ fn in_cargo_miri() {
429502 // The remaining targets we do not even want to build.
430503 _ => continue ,
431504 }
432- // Forward user-defined `cargo` args until first `--`.
433- while let Some ( arg) = args. next ( ) {
434- if arg == "--" {
435- break ;
436- }
505+ // Forward further `cargo` args.
506+ for arg in cargo_args. iter ( ) {
437507 cmd. arg ( arg) ;
438508 }
439509 // We want to always run `cargo` with `--target`. This later helps us detect
@@ -450,8 +520,7 @@ fn in_cargo_miri() {
450520 // our actual target crate (the binary or the test we are running).
451521 // Since we're using "cargo check", we have no other way of passing
452522 // these arguments.
453- let args_vec: Vec < String > = args. collect ( ) ;
454- cmd. env ( "MIRI_ARGS" , serde_json:: to_string ( & args_vec) . expect ( "failed to serialize args" ) ) ;
523+ cmd. env ( "MIRI_ARGS" , serde_json:: to_string ( & miri_args) . expect ( "failed to serialize args" ) ) ;
455524
456525 // Set `RUSTC_WRAPPER` to ourselves. Cargo will prepend that binary to its usual invocation,
457526 // i.e., the first argument is `rustc` -- which is what we use in `main` to distinguish
0 commit comments