Skip to content

Commit 8a2e845

Browse files
Deduplicate methods in completion by function ID and not by name
Because duplicates can be found with traits. Worse, the inherent methods could be private, and we'll discover that only later. But even if they're not they're different methods, and its seems worthy to present them all to the user.
1 parent 21614ed commit 8a2e845

File tree

2 files changed

+47
-8
lines changed

2 files changed

+47
-8
lines changed

crates/ide-completion/src/completions/dot.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use std::ops::ControlFlow;
44

5-
use hir::{Complete, HasContainer, ItemContainer, MethodCandidateCallback, Name};
5+
use hir::{Complete, Function, HasContainer, ItemContainer, MethodCandidateCallback};
66
use ide_db::FxHashSet;
77
use syntax::SmolStr;
88

@@ -237,7 +237,10 @@ fn complete_methods(
237237
struct Callback<'a, F> {
238238
ctx: &'a CompletionContext<'a>,
239239
f: F,
240-
seen_methods: FxHashSet<Name>,
240+
// We deliberately deduplicate by function ID and not name, because while inherent methods cannot be
241+
// duplicated, trait methods can. And it is still useful to show all of them (even when there
242+
// is also an inherent method, especially considering that it may be private, and filtered later).
243+
seen_methods: FxHashSet<Function>,
241244
}
242245

243246
impl<F> MethodCandidateCallback for Callback<'_, F>
@@ -247,9 +250,7 @@ fn complete_methods(
247250
// We don't want to exclude inherent trait methods - that is, methods of traits available from
248251
// `where` clauses or `dyn Trait`.
249252
fn on_inherent_method(&mut self, func: hir::Function) -> ControlFlow<()> {
250-
if func.self_param(self.ctx.db).is_some()
251-
&& self.seen_methods.insert(func.name(self.ctx.db))
252-
{
253+
if func.self_param(self.ctx.db).is_some() && self.seen_methods.insert(func) {
253254
(self.f)(func);
254255
}
255256
ControlFlow::Continue(())
@@ -265,9 +266,7 @@ fn complete_methods(
265266
return ControlFlow::Continue(());
266267
}
267268

268-
if func.self_param(self.ctx.db).is_some()
269-
&& self.seen_methods.insert(func.name(self.ctx.db))
270-
{
269+
if func.self_param(self.ctx.db).is_some() && self.seen_methods.insert(func) {
271270
(self.f)(func);
272271
}
273272

crates/ide-completion/src/tests/expression.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2632,3 +2632,43 @@ fn let_in_condition() {
26322632
fn let_in_let_chain() {
26332633
check_edit("let", r#"fn f() { if true && $0 {} }"#, r#"fn f() { if true && let $1 = $0 {} }"#);
26342634
}
2635+
2636+
#[test]
2637+
fn private_inherent_and_public_trait() {
2638+
check(
2639+
r#"
2640+
struct Foo;
2641+
2642+
mod private {
2643+
impl super::Foo {
2644+
fn method(&self) {}
2645+
}
2646+
}
2647+
2648+
trait Trait {
2649+
fn method(&self) {}
2650+
}
2651+
impl Trait for Foo {}
2652+
2653+
fn main() {
2654+
Foo.$0
2655+
}
2656+
"#,
2657+
expect![[r#"
2658+
me method() (as Trait) fn(&self)
2659+
sn box Box::new(expr)
2660+
sn call function(expr)
2661+
sn const const {}
2662+
sn dbg dbg!(expr)
2663+
sn dbgr dbg!(&expr)
2664+
sn deref *expr
2665+
sn let let
2666+
sn letm let mut
2667+
sn match match expr {}
2668+
sn ref &expr
2669+
sn refm &mut expr
2670+
sn return return expr
2671+
sn unsafe unsafe {}
2672+
"#]],
2673+
);
2674+
}

0 commit comments

Comments
 (0)