Skip to content

Commit a016555

Browse files
committed
Auto merge of #16582 - Veykril:find-path-length, r=Veykril
fix: Respect textual length of paths in find-path Fixes rust-lang/rust-analyzer#16572
2 parents 5261fb2 + c00c9ee commit a016555

File tree

3 files changed

+68
-11
lines changed

3 files changed

+68
-11
lines changed

crates/hir-def/src/find_path.rs

+52-11
Original file line numberDiff line numberDiff line change
@@ -447,18 +447,25 @@ fn select_best_path(
447447
}
448448
const STD_CRATES: [Name; 3] = [known::std, known::core, known::alloc];
449449

450-
let choose = |new_path: (ModPath, _), old_path: (ModPath, _)| {
451-
let new_has_prelude = new_path.0.segments().iter().any(|seg| seg == &known::prelude);
452-
let old_has_prelude = old_path.0.segments().iter().any(|seg| seg == &known::prelude);
450+
let choose = |new: (ModPath, _), old: (ModPath, _)| {
451+
let (new_path, _) = &new;
452+
let (old_path, _) = &old;
453+
let new_has_prelude = new_path.segments().iter().any(|seg| seg == &known::prelude);
454+
let old_has_prelude = old_path.segments().iter().any(|seg| seg == &known::prelude);
453455
match (new_has_prelude, old_has_prelude, prefer_prelude) {
454-
(true, false, true) | (false, true, false) => new_path,
455-
(true, false, false) | (false, true, true) => old_path,
456-
// no prelude difference in the paths, so pick the smaller one
456+
(true, false, true) | (false, true, false) => new,
457+
(true, false, false) | (false, true, true) => old,
458+
// no prelude difference in the paths, so pick the shorter one
457459
(true, true, _) | (false, false, _) => {
458-
if new_path.0.len() < old_path.0.len() {
459-
new_path
460+
let new_path_is_shorter = new_path
461+
.len()
462+
.cmp(&old_path.len())
463+
.then_with(|| new_path.textual_len().cmp(&old_path.textual_len()))
464+
.is_lt();
465+
if new_path_is_shorter {
466+
new
460467
} else {
461-
old_path
468+
old
462469
}
463470
}
464471
}
@@ -469,8 +476,8 @@ fn select_best_path(
469476
let rank = match prefer_no_std {
470477
false => |name: &Name| match name {
471478
name if name == &known::core => 0,
472-
name if name == &known::alloc => 0,
473-
name if name == &known::std => 1,
479+
name if name == &known::alloc => 1,
480+
name if name == &known::std => 2,
474481
_ => unreachable!(),
475482
},
476483
true => |name: &Name| match name {
@@ -1539,4 +1546,38 @@ pub mod foo {
15391546
"krate::prelude::Foo",
15401547
);
15411548
}
1549+
1550+
#[test]
1551+
fn respect_segment_length() {
1552+
check_found_path(
1553+
r#"
1554+
//- /main.rs crate:main deps:petgraph
1555+
$0
1556+
//- /petgraph.rs crate:petgraph
1557+
pub mod graph {
1558+
pub use crate::graph_impl::{
1559+
NodeIndex
1560+
};
1561+
}
1562+
1563+
mod graph_impl {
1564+
pub struct NodeIndex<Ix>(Ix);
1565+
}
1566+
1567+
pub mod stable_graph {
1568+
#[doc(no_inline)]
1569+
pub use crate::graph::{NodeIndex};
1570+
}
1571+
1572+
pub mod prelude {
1573+
#[doc(no_inline)]
1574+
pub use crate::graph::{NodeIndex};
1575+
}
1576+
"#,
1577+
"petgraph::graph::NodeIndex",
1578+
"petgraph::graph::NodeIndex",
1579+
"petgraph::graph::NodeIndex",
1580+
"petgraph::graph::NodeIndex",
1581+
);
1582+
}
15421583
}

crates/hir-def/src/hir.rs

+1
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ pub enum Expr {
182182
tail: Option<ExprId>,
183183
},
184184
Const(ConstBlockId),
185+
// FIXME: Fold this into Block with an unsafe flag?
185186
Unsafe {
186187
id: Option<BlockId>,
187188
statements: Box<[Statement]>,

crates/hir-expand/src/mod_path.rs

+15
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,21 @@ impl ModPath {
9494
}
9595
}
9696

97+
pub fn textual_len(&self) -> usize {
98+
let base = match self.kind {
99+
PathKind::Plain => 0,
100+
PathKind::Super(0) => "self".len(),
101+
PathKind::Super(i) => "super".len() * i as usize,
102+
PathKind::Crate => "crate".len(),
103+
PathKind::Abs => 0,
104+
PathKind::DollarCrate(_) => "$crate".len(),
105+
};
106+
self.segments()
107+
.iter()
108+
.map(|segment| segment.as_str().map_or(0, str::len))
109+
.fold(base, core::ops::Add::add)
110+
}
111+
97112
pub fn is_ident(&self) -> bool {
98113
self.as_ident().is_some()
99114
}

0 commit comments

Comments
 (0)