Change:
While working on std lately, I semi-regularly end up with an error like below. Unfortunately I don’t know the exact conditions to reproduce this. It possibly involves re-using a build directory after starting a new branch from a new position of git . This looks similar to , which was fixed in Maybe something there regressed? CC
I think I know what the problem here is but it won't be a trivial fix -- we'll need to split into more structs. I think one of my planned refactors for rustbuild will fix this, but it's a couple weeks out probably.
Stuff like this is especially annoying during bisecting, you can't just checkout a commit and test.
I can confirm this error still happens. Restarting the build didn't help I had to first delete the generated libraries. did the refactor of rustbuild already land?
It's in progress; there's a PR open which I think might help with this or at least help make a future PR simpler ().
i am new to rust, i am brought here by search engine with the same error message. i "fixed" the error with cargo clean. !

Discussion:
let mut cargo = Command::new(&self.initial_cargo); let out_dir = self.stage_out(compiler, mode); <del> // command specific path, we call clear_if_dirty with this let mut my_out = match cmd { "build" => self.cargo_out(compiler, mode, target), // This is the intended out directory for crate documentation. "doc" | "rustdoc" =>  self.crate_doc_out(target), _ => self.stage_out(compiler, mode), }; // This is for the original compiler, but if we're forced to use stage 1, then // std/test/rustc stamps won't exist in stage 2, so we need to get those from stage 1, since // we copy the libs forward. let cmp = self.compiler_for(compiler.stage, compiler.host, target); let libstd_stamp = match cmd { "check" | "clippy" | "fix" => check::libstd_stamp(self, cmp, target), _ => compile::libstd_stamp(self, cmp, target), }; let libtest_stamp = match cmd { "check" | "clippy" | "fix" => check::libtest_stamp(self, cmp, target), _ => compile::libtest_stamp(self, cmp, target), }; let librustc_stamp = match cmd { "check" | "clippy" | "fix" => check::librustc_stamp(self, cmp, target), _ => compile::librustc_stamp(self, cmp, target), }; </del> <ins> // Codegen backends are not yet tracked by -Zbinary-dep-depinfo, // so we need to explicitly clear out if they've been updated. for backend in self.codegen_backends(compiler) { self.clear_if_dirty(&out_dir, &backend); } </ins> if cmd == "doc" || cmd == "rustdoc" { <del> if mode == Mode::Rustc || mode == Mode::ToolRustc || mode == Mode::Codegen { </del> <ins> let my_out = match mode { </ins> // This is the intended out directory for compiler documentation. <del> my_out = self.compiler_doc_out(target); } </del> <ins> Mode::Rustc | Mode::ToolRustc | Mode::Codegen => self.compiler_doc_out(target), _ => self.crate_doc_out(target), }; </ins> let rustdoc = self.rustdoc(compiler); self.clear_if_dirty(&my_out, &rustdoc); <del> } else if cmd != "test" { match mode { Mode::Std => { self.clear_if_dirty(&my_out, &self.rustc(compiler)); for backend in self.codegen_backends(compiler) { self.clear_if_dirty(&my_out, &backend); } }, Mode::Test => { self.clear_if_dirty(&my_out, &libstd_stamp); }, Mode::Rustc => { self.clear_if_dirty(&my_out, &self.rustc(compiler)); self.clear_if_dirty(&my_out, &libstd_stamp); self.clear_if_dirty(&my_out, &libtest_stamp); }, Mode::Codegen => { self.clear_if_dirty(&my_out, &librustc_stamp); }, Mode::ToolBootstrap => { }, Mode::ToolStd => { self.clear_if_dirty(&my_out, &libstd_stamp); }, Mode::ToolTest => { self.clear_if_dirty(&my_out, &libstd_stamp); self.clear_if_dirty(&my_out, &libtest_stamp); }, Mode::ToolRustc => { self.clear_if_dirty(&my_out, &libstd_stamp); self.clear_if_dirty(&my_out, &libtest_stamp); self.clear_if_dirty(&my_out, &librustc_stamp); }, } </del> } cargo

}, } <ins> // This tells Cargo (and in turn, rustc) to output more complete // dependency information.  Most importantly for rustbuild, this // includes sysroot artifacts, like libstd, which means that we don't // need to track those in rustbuild (an error prone process!). This // feature is currently unstable as there may be some bugs and such, but // it represents a big improvement in rustbuild's reliability on // rebuilds, so we're using it here. // // For some additional context, see #63470 (the PR originally adding // this), as well as #63012 which is the tracking issue for this // feature on the rustc side. cargo.arg("-Zbinary-dep-depinfo"); </ins> cargo.arg("-j").arg(self.jobs().to_string()); // Remove make-related flags to ensure Cargo can correctly set things up cargo.env_remove("MAKEFLAGS");

let libdir = builder.sysroot_libdir(compiler, target); let hostdir = builder.sysroot_libdir(compiler, compiler.host); add_to_sysroot(&builder, &libdir, &hostdir, &rustdoc_stamp(builder, compiler, target)); <del> builder.cargo(compiler, Mode::ToolRustc, target, "clean"); </del> } }

use std::process::{Command, Stdio, exit}; use std::str; <del> use build_helper::{output, mtime, t, up_to_date}; </del> <ins> use build_helper::{output, t, up_to_date}; </ins> use filetime::FileTime; use serde::Deserialize; use serde_json;

// for reason why the sanitizers are not built in stage0. copy_apple_sanitizer_dylibs(builder, &builder.native_dir(target), "osx", &libdir); } <del> builder.cargo(target_compiler, Mode::ToolStd, target, "clean"); </del> } }

&builder.sysroot_libdir(target_compiler, compiler.host), &libtest_stamp(builder, compiler, target) ); <del> builder.cargo(target_compiler, Mode::ToolTest, target, "clean"); </del> } }

&builder.sysroot_libdir(target_compiler, compiler.host), &librustc_stamp(builder, compiler, target) ); <del> builder.cargo(target_compiler, Mode::ToolRustc, target, "clean"); </del> } }

deps.push((path_to_add.into(), false)); } <del> // Now we want to update the contents of the stamp file, if necessary. First // we read off the previous contents along with its mtime. If our new // contents (the list of files to copy) is different or if any dep's mtime // is newer then we rewrite the stamp file. </del> deps.sort(); <del> let stamp_contents = fs::read(stamp); let stamp_mtime = mtime(&stamp); </del> let mut new_contents = Vec::new(); <del> let mut max = None; let mut max_path = None; </del> for (dep, proc_macro) in deps.iter() { <del> let mtime = mtime(dep); if Some(mtime) > max { max = Some(mtime); max_path = Some(dep.clone()); } </del> new_contents.extend(if *proc_macro { b"h" } else { b"t" }); new_contents.extend(dep.to_str().unwrap().as_bytes()); new_contents.extend(b"0"); } <del> let max = max.unwrap(); let max_path = max_path.unwrap(); let contents_equal = stamp_contents .map(|contents| contents == new_contents) .unwrap_or_default(); if contents_equal && max <= stamp_mtime { builder.verbose(&format!("not updating {:?}; contents equal and {:?} <= {:?}", stamp, max, stamp_mtime)); return deps.into_iter().map(|(d, _)| d).collect() } if max > stamp_mtime { builder.verbose(&format!("updating {:?} as {:?} changed", stamp, max_path)); } else { builder.verbose(&format!("updating {:?} as deps changed", stamp)); } </del> t!(fs::write(&stamp, &new_contents)); deps.into_iter().map(|(d, _)| d).collect() }