mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
Prefer standard library paths over shorter extern deps re-exports
This commit is contained in:
parent
41603ab14e
commit
40bbc684ad
2 changed files with 69 additions and 6 deletions
|
@ -1,7 +1,8 @@
|
||||||
//! An algorithm to find a path to refer to a certain item.
|
//! An algorithm to find a path to refer to a certain item.
|
||||||
|
|
||||||
use std::{cell::Cell, cmp::Ordering, iter};
|
use std::{cell::Cell, cmp::Ordering, iter, ops::BitOr};
|
||||||
|
|
||||||
|
use base_db::CrateId;
|
||||||
use hir_expand::{
|
use hir_expand::{
|
||||||
name::{AsName, Name},
|
name::{AsName, Name},
|
||||||
Lookup,
|
Lookup,
|
||||||
|
@ -37,7 +38,8 @@ pub fn find_path(
|
||||||
|
|
||||||
// within block modules, forcing a `self` or `crate` prefix will not allow using inner items, so
|
// within block modules, forcing a `self` or `crate` prefix will not allow using inner items, so
|
||||||
// default to plain paths.
|
// default to plain paths.
|
||||||
if item.module(db).is_some_and(ModuleId::is_within_block) {
|
let item_module = item.module(db)?;
|
||||||
|
if item_module.is_within_block() {
|
||||||
prefix_kind = PrefixKind::Plain;
|
prefix_kind = PrefixKind::Plain;
|
||||||
}
|
}
|
||||||
cfg.prefer_no_std = cfg.prefer_no_std || db.crate_supports_no_std(from.krate());
|
cfg.prefer_no_std = cfg.prefer_no_std || db.crate_supports_no_std(from.krate());
|
||||||
|
@ -50,6 +52,7 @@ pub fn find_path(
|
||||||
ignore_local_imports,
|
ignore_local_imports,
|
||||||
from,
|
from,
|
||||||
from_def_map: &from.def_map(db),
|
from_def_map: &from.def_map(db),
|
||||||
|
is_std_item: db.crate_graph()[item_module.krate()].origin.is_lang(),
|
||||||
fuel: Cell::new(FIND_PATH_FUEL),
|
fuel: Cell::new(FIND_PATH_FUEL),
|
||||||
},
|
},
|
||||||
item,
|
item,
|
||||||
|
@ -104,6 +107,7 @@ struct FindPathCtx<'db> {
|
||||||
ignore_local_imports: bool,
|
ignore_local_imports: bool,
|
||||||
from: ModuleId,
|
from: ModuleId,
|
||||||
from_def_map: &'db DefMap,
|
from_def_map: &'db DefMap,
|
||||||
|
is_std_item: bool,
|
||||||
fuel: Cell<usize>,
|
fuel: Cell<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,9 +377,12 @@ fn calculate_best_path(
|
||||||
// too (unless we can't name it at all). It could *also* be (re)exported by the same crate
|
// too (unless we can't name it at all). It could *also* be (re)exported by the same crate
|
||||||
// that wants to import it here, but we always prefer to use the external path here.
|
// that wants to import it here, but we always prefer to use the external path here.
|
||||||
|
|
||||||
for dep in &db.crate_graph()[ctx.from.krate].dependencies {
|
let mut process_dep = |dep: CrateId| {
|
||||||
let import_map = db.import_map(dep.crate_id);
|
let import_map = db.import_map(dep);
|
||||||
let Some(import_info_for) = import_map.import_info_for(item) else { continue };
|
let Some(import_info_for) = import_map.import_info_for(item) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
let mut processed_something = false;
|
||||||
for info in import_info_for {
|
for info in import_info_for {
|
||||||
if info.is_doc_hidden {
|
if info.is_doc_hidden {
|
||||||
// the item or import is `#[doc(hidden)]`, so skip it as it is in an external crate
|
// 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(
|
||||||
);
|
);
|
||||||
|
|
||||||
process(path, info.name.clone(), &mut best_path_len);
|
process(path, info.name.clone(), &mut best_path_len);
|
||||||
|
processed_something = true;
|
||||||
|
}
|
||||||
|
processed_something
|
||||||
|
};
|
||||||
|
|
||||||
|
let dependencies = &db.crate_graph()[ctx.from.krate].dependencies;
|
||||||
|
if ctx.is_std_item {
|
||||||
|
// The item we are searching for comes from the sysroot libraries, so skip prefer looking in
|
||||||
|
// the sysroot libraries directly.
|
||||||
|
// We do need to fallback as the item in question could be re-exported by another crate
|
||||||
|
// while not being a transitive dependency of the current crate.
|
||||||
|
let processed = dependencies
|
||||||
|
.iter()
|
||||||
|
.filter(|it| it.is_sysroot())
|
||||||
|
.map(|dep| process_dep(dep.crate_id))
|
||||||
|
.reduce(BitOr::bitor)
|
||||||
|
.unwrap_or(false);
|
||||||
|
if processed {
|
||||||
|
// Found a path in a sysroot crate, so return it.
|
||||||
|
return best_path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dependencies
|
||||||
|
.iter()
|
||||||
|
.filter(|it| !ctx.is_std_item || !it.is_sysroot())
|
||||||
|
.for_each(|dep| _ = process_dep(dep.crate_id));
|
||||||
}
|
}
|
||||||
best_path
|
best_path
|
||||||
}
|
}
|
||||||
|
@ -1918,4 +1950,34 @@ pub fn c() {}
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn prefer_long_std_over_short_extern() {
|
||||||
|
check_found_path(
|
||||||
|
r#"
|
||||||
|
//- /lib.rs crate:main deps:futures_lite,std,core
|
||||||
|
$0
|
||||||
|
//- /futures_lite.rs crate:futures_lite deps:std,core
|
||||||
|
pub use crate::future::Future;
|
||||||
|
pub mod future {
|
||||||
|
pub use core::future::Future;
|
||||||
|
}
|
||||||
|
//- /std.rs crate:std deps:core
|
||||||
|
pub use core::future;
|
||||||
|
//- /core.rs crate:core
|
||||||
|
pub mod future {
|
||||||
|
pub trait Future {}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
"core::future::Future",
|
||||||
|
expect![[r#"
|
||||||
|
Plain (imports ✔): std::future::Future
|
||||||
|
Plain (imports ✖): std::future::Future
|
||||||
|
ByCrate(imports ✔): std::future::Future
|
||||||
|
ByCrate(imports ✖): std::future::Future
|
||||||
|
BySelf (imports ✔): std::future::Future
|
||||||
|
BySelf (imports ✖): std::future::Future
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -246,6 +246,7 @@ impl ChangeFixture {
|
||||||
for (from, to, prelude) in crate_deps {
|
for (from, to, prelude) in crate_deps {
|
||||||
let from_id = crates[&from];
|
let from_id = crates[&from];
|
||||||
let to_id = crates[&to];
|
let to_id = crates[&to];
|
||||||
|
let sysroot = crate_graph[to_id].origin.is_lang();
|
||||||
crate_graph
|
crate_graph
|
||||||
.add_dep(
|
.add_dep(
|
||||||
from_id,
|
from_id,
|
||||||
|
@ -253,7 +254,7 @@ impl ChangeFixture {
|
||||||
CrateName::new(&to).unwrap(),
|
CrateName::new(&to).unwrap(),
|
||||||
to_id,
|
to_id,
|
||||||
prelude,
|
prelude,
|
||||||
false,
|
sysroot,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
Loading…
Reference in a new issue