Change:
Edit: see Seems to get past there fine if I remove .
Ok, works. That's the version rustbuild will download if left to its own devices. Bisecting built nightlies as my local rust gives this: nightly-2016-12-19 () - works [no nightlies] nightly-2016-12-29 - unrelated errors on some i128/u128 stuff before it gets to the relevant point [no nightlies] nightly-2017-01-04 () - broken
Note that this is really quick to reproduce (~1min), as it happens on the initial build of stage0 std. Here's the full log from : This issue may get a lot more attention once the stage0 downloaded compiler has its version bumped, as I suspect will be totally broken. Applying seems to fix it.
Ah I see, the more recent compiler is being detected as a local rebuild compiler, so rustbuild assumes it has a compiler with stage1 features and therefore performs a stage1 build, which seems to assume that jemalloc is available. On a positive note, this should never affect someone not using .
Ok I have a more solid understanding of the issue. Currently, a stage0-out libstd will never link against jemalloc. stage1-out is left to its own devices, linking against the default allocator for the compiler that's just been created (stage0-out) which is , system otherwise. However, a local rebuild uses for building the stage0 libstd, which means it uses the default allocator for the local rust. This tends to be we've disabled jemalloc, so it hasn't been built! Something along the lines of seems like the right approach, but I think some elaboration around the logic in this area is necessary in comments or something.

Discussion:
let out_dir = build.cargo_out(compiler, Mode::Libstd, target); build.clear_if_dirty(&out_dir, &build.compiler_path(compiler)); let mut cargo = build.cargo(compiler, Mode::Libstd, target, "build"); <del> cargo.arg("--features").arg(build.std_features()) </del> <ins> let mut features = build.std_features(); // When doing a local rebuild we tell cargo that we're stage1 rather than // stage0. This works fine if the local rust and being-built rust have the // same view of what the default allocator is, but fails otherwise. Since // we don't have a way to express an allocator preference yet, work // around the issue in the case of a local rebuild with jemalloc disabled. if compiler.stage == 0 && build.local_rebuild && !build.config.use_jemalloc { features.push_str(" force_alloc_system"); } cargo.arg("--features").arg(features) </ins> .arg("--manifest-path") .arg(build.src.join("src/rustc/std_shim/Cargo.toml"));

backtrace = [] debug-jemalloc = ["alloc_jemalloc/debug"] jemalloc = ["alloc_jemalloc"] <ins> force_alloc_system = [] </ins> panic-unwind = ["panic_unwind"]

// Tell the compiler to link to either panic_abort or panic_unwind #![needs_panic_runtime] <del> // Always use alloc_system during stage0 since jemalloc might be unavailable or // disabled (Issue #30592) #![cfg_attr(stage0, feature(alloc_system))] </del> <ins> // Always use alloc_system during stage0 since we don't know if the alloc_* // crate the stage0 compiler will pick by default is available (most // obviously, if the user has disabled jemalloc in `./configure`). #![cfg_attr(any(stage0, feature = "force_alloc_system"), feature(alloc_system))] </ins> // Turn warnings into errors, but only after stage0, where it can be useful for // code to emit warnings during language transitions

// We always need an unwinder currently for backtraces extern crate unwind; <del> #[cfg(stage0)] </del> <ins> #[cfg(any(stage0, feature = "force_alloc_system"))] </ins> extern crate alloc_system; // compiler-rt intrinsics

backtrace = ["std/backtrace"] debug-jemalloc = ["std/debug-jemalloc"] jemalloc = ["std/jemalloc"] <ins> force_alloc_system = ["std/force_alloc_system"] </ins> panic-unwind = ["std/panic-unwind"]