1
1
//! An algorithm to find a path to refer to a certain item.
2
2
3
- use std:: { cell:: Cell , cmp:: Ordering , iter} ;
3
+ use std:: { cell:: Cell , cmp:: Ordering , iter, ops :: BitOr } ;
4
4
5
+ use base_db:: CrateId ;
5
6
use hir_expand:: {
6
7
name:: { AsName , Name } ,
7
8
Lookup ,
@@ -37,7 +38,8 @@ pub fn find_path(
37
38
38
39
// within block modules, forcing a `self` or `crate` prefix will not allow using inner items, so
39
40
// default to plain paths.
40
- if item. module ( db) . is_some_and ( ModuleId :: is_within_block) {
41
+ let item_module = item. module ( db) ?;
42
+ if item_module. is_within_block ( ) {
41
43
prefix_kind = PrefixKind :: Plain ;
42
44
}
43
45
cfg. prefer_no_std = cfg. prefer_no_std || db. crate_supports_no_std ( from. krate ( ) ) ;
@@ -50,6 +52,7 @@ pub fn find_path(
50
52
ignore_local_imports,
51
53
from,
52
54
from_def_map : & from. def_map ( db) ,
55
+ is_std_item : db. crate_graph ( ) [ item_module. krate ( ) ] . origin . is_lang ( ) ,
53
56
fuel : Cell :: new ( FIND_PATH_FUEL ) ,
54
57
} ,
55
58
item,
@@ -104,6 +107,7 @@ struct FindPathCtx<'db> {
104
107
ignore_local_imports : bool ,
105
108
from : ModuleId ,
106
109
from_def_map : & ' db DefMap ,
110
+ is_std_item : bool ,
107
111
fuel : Cell < usize > ,
108
112
}
109
113
@@ -373,9 +377,12 @@ fn calculate_best_path(
373
377
// too (unless we can't name it at all). It could *also* be (re)exported by the same crate
374
378
// that wants to import it here, but we always prefer to use the external path here.
375
379
376
- for dep in & db. crate_graph ( ) [ ctx. from . krate ] . dependencies {
377
- let import_map = db. import_map ( dep. crate_id ) ;
378
- let Some ( import_info_for) = import_map. import_info_for ( item) else { continue } ;
380
+ let mut process_dep = |dep : CrateId | {
381
+ let import_map = db. import_map ( dep) ;
382
+ let Some ( import_info_for) = import_map. import_info_for ( item) else {
383
+ return false ;
384
+ } ;
385
+ let mut processed_something = false ;
379
386
for info in import_info_for {
380
387
if info. is_doc_hidden {
381
388
// the item or import is `#[doc(hidden)]`, so skip it as it is in an external crate
@@ -396,8 +403,33 @@ fn calculate_best_path(
396
403
) ;
397
404
398
405
process ( path, info. name . clone ( ) , & mut best_path_len) ;
406
+ processed_something = true ;
407
+ }
408
+ processed_something
409
+ } ;
410
+
411
+ let dependencies = & db. crate_graph ( ) [ ctx. from . krate ] . dependencies ;
412
+ if ctx. is_std_item {
413
+ // The item we are searching for comes from the sysroot libraries, so skip prefer looking in
414
+ // the sysroot libraries directly.
415
+ // We do need to fallback as the item in question could be re-exported by another crate
416
+ // while not being a transitive dependency of the current crate.
417
+ let processed = dependencies
418
+ . iter ( )
419
+ . filter ( |it| it. is_sysroot ( ) )
420
+ . map ( |dep| process_dep ( dep. crate_id ) )
421
+ . reduce ( BitOr :: bitor)
422
+ . unwrap_or ( false ) ;
423
+ if processed {
424
+ // Found a path in a sysroot crate, so return it.
425
+ return best_path;
399
426
}
400
427
}
428
+
429
+ dependencies
430
+ . iter ( )
431
+ . filter ( |it| !ctx. is_std_item || !it. is_sysroot ( ) )
432
+ . for_each ( |dep| _ = process_dep ( dep. crate_id ) ) ;
401
433
}
402
434
best_path
403
435
}
@@ -1918,4 +1950,34 @@ pub fn c() {}
1918
1950
"# ] ] ,
1919
1951
) ;
1920
1952
}
1953
+
1954
+ #[ test]
1955
+ fn prefer_long_std_over_short_extern ( ) {
1956
+ check_found_path (
1957
+ r#"
1958
+ //- /lib.rs crate:main deps:futures_lite,std,core
1959
+ $0
1960
+ //- /futures_lite.rs crate:futures_lite deps:std,core
1961
+ pub use crate::future::Future;
1962
+ pub mod future {
1963
+ pub use core::future::Future;
1964
+ }
1965
+ //- /std.rs crate:std deps:core
1966
+ pub use core::future;
1967
+ //- /core.rs crate:core
1968
+ pub mod future {
1969
+ pub trait Future {}
1970
+ }
1971
+ "# ,
1972
+ "core::future::Future" ,
1973
+ expect ! [ [ r#"
1974
+ Plain (imports ✔): std::future::Future
1975
+ Plain (imports ✖): std::future::Future
1976
+ ByCrate(imports ✔): std::future::Future
1977
+ ByCrate(imports ✖): std::future::Future
1978
+ BySelf (imports ✔): std::future::Future
1979
+ BySelf (imports ✖): std::future::Future
1980
+ "# ] ] ,
1981
+ ) ;
1982
+ }
1921
1983
}
0 commit comments