From 674a7adf9bd765354f58c50f3632f3410a6ac9f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 14 Mar 2025 11:45:22 +0100 Subject: [PATCH] Add an error when full metadata was not found --- compiler/rustc_metadata/messages.ftl | 4 ++++ compiler/rustc_metadata/src/errors.rs | 9 +++++++++ compiler/rustc_metadata/src/locator.rs | 23 ++++++++++++++++++++++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl index 9adbcabcf45..d997ba198ac 100644 --- a/compiler/rustc_metadata/messages.ftl +++ b/compiler/rustc_metadata/messages.ftl @@ -97,6 +97,10 @@ metadata_found_staticlib = found staticlib `{$crate_name}` instead of rlib or dylib{$add_info} .help = please recompile that crate using --crate-type lib +metadata_full_metadata_not_found = + only metadata stub found for `{$flavor}` dependency `{$crate_name}` + please provide path to the corresponding .rmeta file with full metadata + metadata_global_alloc_required = no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 0c54628598c..c45daeda85d 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -525,6 +525,15 @@ impl Diagnostic<'_, G> for MultipleCandidates { } } +#[derive(Diagnostic)] +#[diag(metadata_full_metadata_not_found)] +pub(crate) struct FullMetadataNotFound { + #[primary_span] + pub span: Span, + pub flavor: CrateFlavor, + pub crate_name: Symbol, +} + #[derive(Diagnostic)] #[diag(metadata_symbol_conflicts_current, code = E0519)] pub struct SymbolConflictsCurrent { diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 03823682748..112954eca0d 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -654,7 +654,24 @@ impl<'a> CrateLocator<'a> { continue; } } - *slot = Some((hash, metadata, lib.clone())); + + // We error eagerly here. If we're locating a rlib, then in theory the full metadata + // could still be in a (later resolved) dylib. In practice, if the rlib and dylib + // were produced in a way where one has full metadata and the other hasn't, it would + // mean that they were compiled using different compiler flags and probably also have + // a different SVH value. + if metadata.get_header().is_stub { + // `is_stub` should never be true for .rmeta files. + assert_ne!(flavor, CrateFlavor::Rmeta); + + // Because rmeta files are resolved before rlib/dylib files, if this is a stub and + // we haven't found a slot already, it means that the full metadata is missing. + if slot.is_none() { + return Err(CrateError::FullMetadataNotFound(self.crate_name, flavor)); + } + } else { + *slot = Some((hash, metadata, lib.clone())); + } ret = Some((lib, kind)); } @@ -916,6 +933,7 @@ pub(crate) enum CrateError { ExternLocationNotExist(Symbol, PathBuf), ExternLocationNotFile(Symbol, PathBuf), MultipleCandidates(Symbol, CrateFlavor, Vec), + FullMetadataNotFound(Symbol, CrateFlavor), SymbolConflictsCurrent(Symbol), StableCrateIdCollision(Symbol, Symbol), DlOpen(String, String), @@ -966,6 +984,9 @@ impl CrateError { CrateError::MultipleCandidates(crate_name, flavor, candidates) => { dcx.emit_err(errors::MultipleCandidates { span, crate_name, flavor, candidates }); } + CrateError::FullMetadataNotFound(crate_name, flavor) => { + dcx.emit_err(errors::FullMetadataNotFound { span, crate_name, flavor }); + } CrateError::SymbolConflictsCurrent(root_name) => { dcx.emit_err(errors::SymbolConflictsCurrent { span, crate_name: root_name }); }