@@ -654,7 +654,22 @@ impl<'a> CrateLocator<'a> {
654654 continue ;
655655 }
656656 }
657- * slot = Some ( ( hash, metadata, lib. clone ( ) ) ) ;
657+
658+ // Question: maybe we shouldn't error eagerly here, because it is possible that
659+ // e.g. a rlib only contains a stub, but a (later-resolved) dylib contains the full
660+ // metadata?
661+ if metadata. get_header ( ) . is_stub {
662+ // `is_stub` should never be true for .rmeta files.
663+ assert_ne ! ( flavor, CrateFlavor :: Rmeta ) ;
664+
665+ // Because rmeta files are resolved before rlib/dylib files, if this is a stub and
666+ // we haven't found a slot already, it means that the full metadata is missing.
667+ if slot. is_none ( ) {
668+ return Err ( CrateError :: FullMetadataNotFound ( self . crate_name , flavor) ) ;
669+ }
670+ } else {
671+ * slot = Some ( ( hash, metadata, lib. clone ( ) ) ) ;
672+ }
658673 ret = Some ( ( lib, kind) ) ;
659674 }
660675
@@ -916,6 +931,7 @@ pub(crate) enum CrateError {
916931 ExternLocationNotExist ( Symbol , PathBuf ) ,
917932 ExternLocationNotFile ( Symbol , PathBuf ) ,
918933 MultipleCandidates ( Symbol , CrateFlavor , Vec < PathBuf > ) ,
934+ FullMetadataNotFound ( Symbol , CrateFlavor ) ,
919935 SymbolConflictsCurrent ( Symbol ) ,
920936 StableCrateIdCollision ( Symbol , Symbol ) ,
921937 DlOpen ( String , String ) ,
@@ -966,6 +982,9 @@ impl CrateError {
966982 CrateError :: MultipleCandidates ( crate_name, flavor, candidates) => {
967983 dcx. emit_err ( errors:: MultipleCandidates { span, crate_name, flavor, candidates } ) ;
968984 }
985+ CrateError :: FullMetadataNotFound ( crate_name, flavor) => {
986+ dcx. emit_err ( errors:: FullMetadataNotFound { span, crate_name, flavor } ) ;
987+ }
969988 CrateError :: SymbolConflictsCurrent ( root_name) => {
970989 dcx. emit_err ( errors:: SymbolConflictsCurrent { span, crate_name : root_name } ) ;
971990 }
0 commit comments