@@ -499,8 +499,11 @@ impl<'a> CrateLocator<'a> {
499499 dylibs : FxIndexMap < PathBuf , PathKind > ,
500500 ) -> Result < Option < ( Svh , Library ) > , CrateError > {
501501 let mut slot = None ;
502- // Order here matters, rmeta should come first. See comment in
503- // `extract_one` below.
502+ // Order here matters, rmeta should come first.
503+ //
504+ // Make sure there's at most one rlib and at most one dylib.
505+ //
506+ // See comment in `extract_one` below.
504507 let source = CrateSource {
505508 rmeta : self . extract_one ( rmetas, CrateFlavor :: Rmeta , & mut slot) ?,
506509 rlib : self . extract_one ( rlibs, CrateFlavor :: Rlib , & mut slot) ?,
@@ -706,54 +709,58 @@ impl<'a> CrateLocator<'a> {
706709 let mut rmetas = FxIndexMap :: default ( ) ;
707710 let mut dylibs = FxIndexMap :: default ( ) ;
708711 for loc in & self . exact_paths {
709- if !loc. canonicalized ( ) . exists ( ) {
710- return Err ( CrateError :: ExternLocationNotExist (
711- self . crate_name ,
712- loc. original ( ) . clone ( ) ,
713- ) ) ;
712+ let loc_canon = loc. canonicalized ( ) ;
713+ let loc_orig = loc. original ( ) ;
714+ if !loc_canon. exists ( ) {
715+ return Err ( CrateError :: ExternLocationNotExist ( self . crate_name , loc_orig. clone ( ) ) ) ;
714716 }
715- if !loc. original ( ) . is_file ( ) {
716- return Err ( CrateError :: ExternLocationNotFile (
717- self . crate_name ,
718- loc. original ( ) . clone ( ) ,
719- ) ) ;
717+ if !loc_orig. is_file ( ) {
718+ return Err ( CrateError :: ExternLocationNotFile ( self . crate_name , loc_orig. clone ( ) ) ) ;
720719 }
721- let Some ( file) = loc. original ( ) . file_name ( ) . and_then ( |s| s. to_str ( ) ) else {
722- return Err ( CrateError :: ExternLocationNotFile (
723- self . crate_name ,
724- loc. original ( ) . clone ( ) ,
725- ) ) ;
720+ // Note to take care and match against the non-canonicalized name:
721+ // some systems save build artifacts into content-addressed stores
722+ // that do not preserve extensions, and then link to them using
723+ // e.g. symbolic links. If we canonicalize too early, we resolve
724+ // the symlink, the file type is lost and we might treat rlibs and
725+ // rmetas as dylibs.
726+ let Some ( file) = loc_orig. file_name ( ) . and_then ( |s| s. to_str ( ) ) else {
727+ return Err ( CrateError :: ExternLocationNotFile ( self . crate_name , loc_orig. clone ( ) ) ) ;
726728 } ;
727-
728- if file. starts_with ( "lib" ) && ( file. ends_with ( ".rlib" ) || file. ends_with ( ".rmeta" ) )
729- || file. starts_with ( self . target . dll_prefix . as_ref ( ) )
730- && file. ends_with ( self . target . dll_suffix . as_ref ( ) )
731- {
732- // Make sure there's at most one rlib and at most one dylib.
733- // Note to take care and match against the non-canonicalized name:
734- // some systems save build artifacts into content-addressed stores
735- // that do not preserve extensions, and then link to them using
736- // e.g. symbolic links. If we canonicalize too early, we resolve
737- // the symlink, the file type is lost and we might treat rlibs and
738- // rmetas as dylibs.
739- let loc_canon = loc. canonicalized ( ) . clone ( ) ;
740- let loc = loc. original ( ) ;
741- if loc. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) . ends_with ( ".rlib" ) {
742- rlibs. insert ( loc_canon, PathKind :: ExternFlag ) ;
743- } else if loc. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) . ends_with ( ".rmeta" ) {
744- rmetas. insert ( loc_canon, PathKind :: ExternFlag ) ;
745- } else {
746- dylibs. insert ( loc_canon, PathKind :: ExternFlag ) ;
729+ // FnMut cannot return reference to captured value, so references
730+ // must be taken outside the closure.
731+ let rlibs = & mut rlibs;
732+ let rmetas = & mut rmetas;
733+ let dylibs = & mut dylibs;
734+ let type_via_filename = ( || {
735+ if file. starts_with ( "lib" ) {
736+ if file. ends_with ( ".rlib" ) {
737+ return Some ( rlibs) ;
738+ }
739+ if file. ends_with ( ".rmeta" ) {
740+ return Some ( rmetas) ;
741+ }
742+ }
743+ let dll_prefix = self . target . dll_prefix . as_ref ( ) ;
744+ let dll_suffix = self . target . dll_suffix . as_ref ( ) ;
745+ if file. starts_with ( dll_prefix) && file. ends_with ( dll_suffix) {
746+ return Some ( dylibs) ;
747+ }
748+ None
749+ } ) ( ) ;
750+ match type_via_filename {
751+ Some ( type_via_filename) => {
752+ type_via_filename. insert ( loc_canon. clone ( ) , PathKind :: ExternFlag ) ;
753+ }
754+ None => {
755+ self . crate_rejections
756+ . via_filename
757+ . push ( CrateMismatch { path : loc_orig. clone ( ) , got : String :: new ( ) } ) ;
747758 }
748- } else {
749- self . crate_rejections
750- . via_filename
751- . push ( CrateMismatch { path : loc. original ( ) . clone ( ) , got : String :: new ( ) } ) ;
752759 }
753760 }
754761
755762 // Extract the dylib/rlib/rmeta triple.
756- Ok ( self . extract_lib ( rlibs, rmetas, dylibs) ? . map ( |( _, lib) | lib) )
763+ self . extract_lib ( rlibs, rmetas, dylibs) . map ( |opt| opt . map ( |( _, lib) | lib) )
757764 }
758765
759766 pub ( crate ) fn into_error ( self , root : Option < CratePaths > ) -> CrateError {
0 commit comments