@@ -414,15 +414,17 @@ impl Config {
414414 // Set config values based on flags.
415415 let mut exec_ctx = ExecutionContext :: new ( flags_verbose, flags_cmd. fail_fast ( ) ) ;
416416 exec_ctx. set_dry_run ( if flags_dry_run { DryRun :: UserSelected } else { DryRun :: Disabled } ) ;
417- let mut src = {
417+
418+ let default_src_dir = {
418419 let manifest_dir = PathBuf :: from ( env ! ( "CARGO_MANIFEST_DIR" ) ) ;
419420 // Undo `src/bootstrap`
420421 manifest_dir. parent ( ) . unwrap ( ) . parent ( ) . unwrap ( ) . to_owned ( )
421422 } ;
422-
423- if let Some ( src_) = compute_src_directory ( flags_src, & exec_ctx) {
424- src = src_;
425- }
423+ let src = if let Some ( s) = compute_src_directory ( flags_src, & exec_ctx) {
424+ s
425+ } else {
426+ default_src_dir. clone ( )
427+ } ;
426428
427429 #[ cfg( test) ]
428430 {
@@ -659,6 +661,10 @@ impl Config {
659661 out
660662 } ;
661663
664+ let default_stage0_rustc_path = |dir : & Path | {
665+ dir. join ( host_target) . join ( "stage0" ) . join ( "bin" ) . join ( exe ( "rustc" , host_target) )
666+ } ;
667+
662668 if cfg ! ( test) {
663669 // When configuring bootstrap for tests, make sure to set the rustc and Cargo to the
664670 // same ones used to call the tests (if custom ones are not defined in the toml). If we
@@ -667,6 +673,24 @@ impl Config {
667673 // Cargo in their bootstrap.toml.
668674 build_rustc = build_rustc. take ( ) . or ( std:: env:: var_os ( "RUSTC" ) . map ( |p| p. into ( ) ) ) ;
669675 build_cargo = build_cargo. take ( ) . or ( std:: env:: var_os ( "CARGO" ) . map ( |p| p. into ( ) ) ) ;
676+
677+ // If we are running only `cargo test` (and not `x test bootstrap`), which is useful
678+ // e.g. for debugging bootstrap itself, then we won't have RUSTC and CARGO set to the
679+ // proper paths.
680+ // We thus "guess" that the build directory is located at <src>/build, and try to load
681+ // rustc and cargo from there
682+ let is_test_outside_x = std:: env:: var ( "CARGO_TARGET_DIR" ) . is_err ( ) ;
683+ if is_test_outside_x {
684+ if build_rustc. is_none ( ) {
685+ let stage0_rustc = default_stage0_rustc_path ( & default_src_dir. join ( "build" ) ) ;
686+ assert ! (
687+ stage0_rustc. exists( ) ,
688+ "Trying to run cargo test without having a stage0 rustc available in {}" ,
689+ stage0_rustc. display( )
690+ ) ;
691+ build_rustc = Some ( stage0_rustc) ;
692+ }
693+ }
670694 }
671695
672696 if !flags_skip_stage0_validation {
@@ -700,7 +724,7 @@ impl Config {
700724
701725 let initial_rustc = build_rustc. unwrap_or_else ( || {
702726 download_beta_toolchain ( & dwn_ctx, & out) ;
703- out . join ( host_target ) . join ( "stage0" ) . join ( "bin" ) . join ( exe ( "rustc" , host_target ) )
727+ default_stage0_rustc_path ( & out )
704728 } ) ;
705729
706730 let initial_sysroot = t ! ( PathBuf :: from_str(
@@ -1540,11 +1564,11 @@ impl Config {
15401564 println ! ( "WARNING: CI rustc has some fields that are no longer supported in bootstrap; download-rustc will be disabled." ) ;
15411565 println ! ( "HELP: Consider rebasing to a newer commit if available." ) ;
15421566 return None ;
1543- } ,
1567+ }
15441568 Err ( e) => {
15451569 eprintln ! ( "ERROR: Failed to parse CI rustc bootstrap.toml: {e}" ) ;
15461570 exit ! ( 2 ) ;
1547- } ,
1571+ }
15481572 } ;
15491573
15501574 let current_config_toml = Self :: get_toml ( config_path) . unwrap ( ) ;
0 commit comments