@@ -347,11 +347,11 @@ impl<'a> Context<'a> {
347
347
// read the metadata from it if `*slot` is `None`. If the metadata couldn't
348
348
// be read, it is assumed that the file isn't a valid rust library (no
349
349
// errors are emitted).
350
+ //
351
+ // If there are multiple candidates, and one of them lives in the target
352
+ // lib path, pick that candidate instead of erroring out.
350
353
fn extract_one ( & mut self , m : HashSet < Path > , flavor : & str ,
351
354
slot : & mut Option < MetadataBlob > ) -> Option < Path > {
352
- let mut ret = None :: < Path > ;
353
- let mut error = 0 ;
354
-
355
355
if slot. is_some ( ) {
356
356
// FIXME(#10786): for an optimization, we only read one of the
357
357
// library's metadata sections. In theory we should
@@ -364,6 +364,8 @@ impl<'a> Context<'a> {
364
364
}
365
365
}
366
366
367
+ let mut candidates: Vec < ( Path , MetadataBlob ) > = Vec :: new ( ) ;
368
+
367
369
for lib in m. move_iter ( ) {
368
370
info ! ( "{} reading metadata from: {}" , flavor, lib. display( ) ) ;
369
371
let metadata = match get_metadata_section ( self . os , & lib) {
@@ -380,30 +382,45 @@ impl<'a> Context<'a> {
380
382
continue
381
383
}
382
384
} ;
383
- if ret. is_some ( ) {
385
+ candidates. push ( ( lib, metadata) ) ;
386
+ }
387
+ let ( lib, metadata) = if candidates. len ( ) > 1 {
388
+ info ! ( "multiple {} candidates for `{}`" , flavor, self . crate_id. name) ;
389
+ // look for one from the target lib path
390
+ let target_lib_path = self . filesearch . get_lib_path ( ) ;
391
+
392
+ let ( idx_opt, has_multiple) = {
393
+ let mut idxs = candidates. iter ( ) . enumerate ( ) . filter_map ( |( i, & ( ref lib, _) ) | {
394
+ if target_lib_path. is_ancestor_of ( lib) { Some ( i) } else { None }
395
+ } ) ;
396
+ ( idxs. next ( ) , idxs. next ( ) . is_some ( ) )
397
+ } ;
398
+ if idx_opt. is_some ( ) && !has_multiple {
399
+ // only one library is in the target lib path
400
+ let idx = idx_opt. unwrap ( ) ;
401
+ let ( lib, metadata) = candidates. move_iter ( ) . nth ( idx) . unwrap ( ) ;
402
+ info ! ( "found candidate in target lib path: {}" , lib. display( ) ) ;
403
+ ( lib, metadata)
404
+ } else {
405
+ // either multiple libraries were found in the target lib path, or none
384
406
self . sess . span_err ( self . span ,
385
- format ! ( "multiple {} candidates for `{}` \
386
- found",
387
- flavor,
388
- self . crate_id. name) . as_slice ( ) ) ;
389
- self . sess . span_note ( self . span ,
390
- format ! ( r"candidate \#1: {}" ,
391
- ret. get_ref( )
392
- . display( ) ) . as_slice ( ) ) ;
393
- error = 1 ;
394
- ret = None ;
407
+ format ! ( "multiple {} candidates for `{}` found" ,
408
+ flavor, self . crate_id. name) . as_slice ( ) ) ;
409
+ for ( i, ( lib, _) ) in candidates. move_iter ( ) . enumerate ( ) {
410
+ self . sess . span_note ( self . span ,
411
+ format ! ( r"candidate \#{}: {}" , i+1 ,
412
+ lib. display( ) ) . as_slice ( ) ) ;
413
+ }
414
+ return None ;
395
415
}
396
- if error > 0 {
397
- error += 1 ;
398
- self . sess . span_note ( self . span ,
399
- format ! ( r"candidate \#{}: {}" , error,
400
- lib. display( ) ) . as_slice ( ) ) ;
401
- continue
416
+ } else {
417
+ match candidates. move_iter ( ) . next ( ) {
418
+ Some ( x) => x,
419
+ None => return None
402
420
}
403
- * slot = Some ( metadata) ;
404
- ret = Some ( lib) ;
405
- }
406
- return if error > 0 { None } else { ret}
421
+ } ;
422
+ * slot = Some ( metadata) ;
423
+ Some ( lib)
407
424
}
408
425
409
426
fn crate_matches ( & mut self , crate_data : & [ u8 ] , libpath : & Path ) -> bool {
0 commit comments