summaryrefslogtreecommitdiff
path: root/compiler/rustc_metadata
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-03-09 16:21:17 +0100
committerGitHub <noreply@github.com>2024-03-09 16:21:17 +0100
commit9ac5cc86d7ffcedb37ce52c43a6baca6bdf24df0 (patch)
tree456b5549ea1e670d15e5399ed1955661ff5ed122 /compiler/rustc_metadata
parent577632d4d4b35d00a81b219144cd55e2f36d86e8 (diff)
parentfdff4d7682071b981a40dcc3575300a661a1f382 (diff)
Rollup merge of #122187 - bjorn3:merge_header_version_checks, r=petrochenkov
Move metadata header and version checks together This will make it easier to report rustc versions for older metadata formats. Split out of https://github.com/rust-lang/rust/pull/120855
Diffstat (limited to 'compiler/rustc_metadata')
-rw-r--r--compiler/rustc_metadata/src/locator.rs99
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs24
2 files changed, 78 insertions, 45 deletions
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index dcccace12b0..10bbebb3871 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -569,31 +569,47 @@ impl<'a> CrateLocator<'a> {
debug!("skipping empty file");
continue;
}
- let (hash, metadata) =
- match get_metadata_section(self.target, flavor, &lib, self.metadata_loader) {
- Ok(blob) => {
- if let Some(h) = self.crate_matches(&blob, &lib) {
- (h, blob)
- } else {
- info!("metadata mismatch");
- continue;
- }
- }
- Err(MetadataError::LoadFailure(err)) => {
- info!("no metadata found: {}", err);
- // The file was present and created by the same compiler version, but we
- // couldn't load it for some reason. Give a hard error instead of silently
- // ignoring it, but only if we would have given an error anyway.
- self.crate_rejections
- .via_invalid
- .push(CrateMismatch { path: lib, got: err });
- continue;
- }
- Err(err @ MetadataError::NotPresent(_)) => {
- info!("no metadata found: {}", err);
+ let (hash, metadata) = match get_metadata_section(
+ self.target,
+ flavor,
+ &lib,
+ self.metadata_loader,
+ self.cfg_version,
+ ) {
+ Ok(blob) => {
+ if let Some(h) = self.crate_matches(&blob, &lib) {
+ (h, blob)
+ } else {
+ info!("metadata mismatch");
continue;
}
- };
+ }
+ Err(MetadataError::VersionMismatch { expected_version, found_version }) => {
+ // The file was present and created by the same compiler version, but we
+ // couldn't load it for some reason. Give a hard error instead of silently
+ // ignoring it, but only if we would have given an error anyway.
+ info!(
+ "Rejecting via version: expected {} got {}",
+ expected_version, found_version
+ );
+ self.crate_rejections
+ .via_version
+ .push(CrateMismatch { path: lib, got: found_version });
+ continue;
+ }
+ Err(MetadataError::LoadFailure(err)) => {
+ info!("no metadata found: {}", err);
+ // The file was present and created by the same compiler version, but we
+ // couldn't load it for some reason. Give a hard error instead of silently
+ // ignoring it, but only if we would have given an error anyway.
+ self.crate_rejections.via_invalid.push(CrateMismatch { path: lib, got: err });
+ continue;
+ }
+ Err(err @ MetadataError::NotPresent(_)) => {
+ info!("no metadata found: {}", err);
+ continue;
+ }
+ };
// If we see multiple hashes, emit an error about duplicate candidates.
if slot.as_ref().is_some_and(|s| s.0 != hash) {
if let Some(candidates) = err_data {
@@ -648,16 +664,6 @@ impl<'a> CrateLocator<'a> {
}
fn crate_matches(&mut self, metadata: &MetadataBlob, libpath: &Path) -> Option<Svh> {
- let rustc_version = rustc_version(self.cfg_version);
- let found_version = metadata.get_rustc_version();
- if found_version != rustc_version {
- info!("Rejecting via version: expected {} got {}", rustc_version, found_version);
- self.crate_rejections
- .via_version
- .push(CrateMismatch { path: libpath.to_path_buf(), got: found_version });
- return None;
- }
-
let header = metadata.get_header();
if header.is_proc_macro_crate != self.is_proc_macro {
info!(
@@ -770,6 +776,7 @@ fn get_metadata_section<'p>(
flavor: CrateFlavor,
filename: &'p Path,
loader: &dyn MetadataLoader,
+ cfg_version: &'static str,
) -> Result<MetadataBlob, MetadataError<'p>> {
if !filename.exists() {
return Err(MetadataError::NotPresent(filename));
@@ -847,13 +854,18 @@ fn get_metadata_section<'p>(
}
};
let blob = MetadataBlob(raw_bytes);
- if blob.is_compatible() {
- Ok(blob)
- } else {
- Err(MetadataError::LoadFailure(format!(
+ match blob.check_compatibility(cfg_version) {
+ Ok(()) => Ok(blob),
+ Err(None) => Err(MetadataError::LoadFailure(format!(
"invalid metadata version found: {}",
filename.display()
- )))
+ ))),
+ Err(Some(found_version)) => {
+ return Err(MetadataError::VersionMismatch {
+ expected_version: rustc_version(cfg_version),
+ found_version,
+ });
+ }
}
}
@@ -864,9 +876,10 @@ pub fn list_file_metadata(
metadata_loader: &dyn MetadataLoader,
out: &mut dyn Write,
ls_kinds: &[String],
+ cfg_version: &'static str,
) -> IoResult<()> {
let flavor = get_flavor_from_path(path);
- match get_metadata_section(target, flavor, path, metadata_loader) {
+ match get_metadata_section(target, flavor, path, metadata_loader, cfg_version) {
Ok(metadata) => metadata.list_crate_metadata(out, ls_kinds),
Err(msg) => write!(out, "{msg}\n"),
}
@@ -932,6 +945,8 @@ enum MetadataError<'a> {
NotPresent(&'a Path),
/// The file was present and invalid.
LoadFailure(String),
+ /// The file was present, but compiled with a different rustc version.
+ VersionMismatch { expected_version: String, found_version: String },
}
impl fmt::Display for MetadataError<'_> {
@@ -941,6 +956,12 @@ impl fmt::Display for MetadataError<'_> {
f.write_str(&format!("no such file: '{}'", filename.display()))
}
MetadataError::LoadFailure(msg) => f.write_str(msg),
+ MetadataError::VersionMismatch { expected_version, found_version } => {
+ f.write_str(&format!(
+ "rustc version mismatch. expected {}, found {}",
+ expected_version, found_version,
+ ))
+ }
}
}
}
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index da384007c22..0467cf2969f 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -684,13 +684,25 @@ impl<'a, 'tcx, I: Idx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyTable<I, T>
implement_ty_decoder!(DecodeContext<'a, 'tcx>);
impl MetadataBlob {
- pub(crate) fn is_compatible(&self) -> bool {
- self.blob().starts_with(METADATA_HEADER)
- }
+ pub(crate) fn check_compatibility(
+ &self,
+ cfg_version: &'static str,
+ ) -> Result<(), Option<String>> {
+ if !self.blob().starts_with(METADATA_HEADER) {
+ if self.blob().starts_with(b"rust") {
+ return Err(Some("<unknown rustc version>".to_owned()));
+ }
+ return Err(None);
+ }
- pub(crate) fn get_rustc_version(&self) -> String {
- LazyValue::<String>::from_position(NonZero::new(METADATA_HEADER.len() + 8).unwrap())
- .decode(self)
+ let found_version =
+ LazyValue::<String>::from_position(NonZero::new(METADATA_HEADER.len() + 8).unwrap())
+ .decode(self);
+ if rustc_version(cfg_version) != found_version {
+ return Err(Some(found_version));
+ }
+
+ Ok(())
}
fn root_pos(&self) -> NonZero<usize> {