Change:
I'm trying to build Rust on a Tier 3 platform (; actually it's that's listed in Tier 3, but I don't think that affects the problem). Since there are no snapshots for this platform, I installed rustc from the distro's package manager (apk) and created a file to force using the pre-installed rustc rather than downloading snapshots: And the output of : I ran ; when it got as far as building the core library, I got a series of errors that were very hard to make sense of until I realized that it's because core library code depends on unstable features and I was using a stable rustc to compile it: There were many more errors, but I think they all relate to unstable features. It took me ages to figure out that (for example) the first error is due to the feature being disabled in stable. I understand that the stable compiler won't allow using unstable features even with , but is it possible for the parser to recognize this code even so and reject it with something like "feature is not enabled" instead of the much more generic "expected identifier" error?
Huh, usually Rust gets around this by setting , and usually when we bootstrap it's with a beta compiler, which does need that set by , and that would allow all the features. I wonder if wasn't set?
It's set, but the command that's actually failing (it took some effort to figure out which executable was actually failing) is: And what's installed for me in is a stable compiler. I realized after the fact that I can't use it to bootstrap, but with a different error message I might have noticed that sooner.
Forwards compatibility in diagnostics seems extremely hard. I think a much simpler and more helpful fix is to check the output of in bootstrap and give a hard error if it's not either the current version or N-1.
Note that the problem here is that you were trying to use 1.68 to build 1.70; it's unrelated to stable vs beta, the problem is that it was two versions behind instead of only one.
Mentoring instructions: in , if is set, run that process with . Compare that output to the contents of using the crate; if the minor versions aren't either the same or 1 apart, give a hard error. Note that this should also disallow e.g. building 1.68 with 1.69; we use deny-warnings in most cases and have no guarantees that unstable features will be the same between releases. Only building 1.68 with 1.67 or 1.68 should be allowed.
btw I've noticed you running into a few different bootstrap bugs the past few days — reading through https://rustc-dev- may or may not make it easier to diagnose these issues without having to spend ages interpreting the diagnostics. I'm also happy to chat about "how should this work" sorts of things .
Yes, I've read that. Thanks!
The error message could be improved though. Maybe one could make the to put into libcore/bootstrap's
I don't think rust-version is a good way to solve this, no - that won't give a warning or error if you use a future version to compile an older version. Also it won't be able to catch local-rebuild issues where the nightly version of the bootstrap compiler is too old. See my suggestion in
Hmm, I'm afraid I might have said something unclear. I'm not asking for forward compatibility in diagnostics. The feature was in version 1.68.0, according to , and I was using rustc version 1.68.2. So it should "know" about that feature, but my understanding is that when I was invoking rustc it was with flags that prevent unstable features from being used.
hmm, in that case something strange is going on because playground gives a much more reasonable error than the one you saw:
what commit of rustc were you trying to build when you got this error? I'm going to see if I can replicate it locally.
I was trying to build .
Ah ok, it was related to the context of the closure: If you look at the same gist with beta, the error message is much better: So I think this particular diagnostic issue has already been fixed. I still want to keep this issue open to track checking the version of the bootstrap compiler, though.

Discussion:
"once_cell", "opener", "pretty_assertions", <ins> "semver", </ins> "serde", "serde_derive", "serde_json",

checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] <ins> name = "semver" version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" [[package]] </ins> name = "serde" version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index"

sysinfo = { version = "0.26.0", optional = true } clap = { version = "4.2.4", default-features = false, features = ["std", "usage", "help", "derive", "error-context"] } clap_complete = "4.2.2" <ins> semver = "1.0.17" </ins> # Solaris doesn't support flock() and thus fd-lock is not option now [target.'cfg(not(target_os = "solaris"))'.dependencies]

use crate::flags::{Color, Flags, Warnings}; use crate::util::{exe, output, t}; use once_cell::sync::OnceCell; <ins> use semver::Version; </ins> use serde::{Deserialize, Deserializer}; use serde_derive::Deserialize;

config.download_beta_toolchain(); config.out.join(config.build.triple).join("stage0/bin/rustc") }); config.initial_cargo = build .cargo .map(|cargo| {

self.rust_codegen_backends.get(0).cloned() } <ins> pub fn check_build_rustc_version(&self) { if self.dry_run() { return; } // check rustc version is same or lower with 1 apart from the building one let mut cmd = Command::new(&self.initial_rustc); cmd.arg("--version"); let rustc_output = output(&mut cmd) .lines() .next() .unwrap() .split(' ') .nth(1) .unwrap() .split('-') .next() .unwrap() .to_owned(); let rustc_version = Version::parse(&rustc_output.trim()).unwrap(); let source_version = Version::parse(&fs::read_to_string(self.src.join("src/version")).unwrap().trim()) .unwrap(); if !(source_version == rustc_version || (source_version.major == rustc_version.major && source_version.minor == rustc_version.minor + 1)) { let prev_version = format!("{}.{}.x", source_version.major, source_version.minor - 1); eprintln!( "Unexpected rustc version: {}, we should use {}/{} to build source with {}", rustc_version, prev_version, source_version, source_version ); crate::detail_exit(1); } } </ins> /// Returns the commit to download, or `None` if we shouldn't download CI artifacts. fn download_ci_rustc_commit(&self, download_rustc: Option<StringOrBool>) -> Option<String> { // If `download-rustc` is not set, default to rebuilding.

bootstrap_out.display() ) } <ins> config.check_build_rustc_version(); </ins> if rust_info.is_from_tarball() && config.description.is_none() { config.description = Some("built from a source tarball".to_owned());