Skip to content

Commit 4c52c35

Browse files
Merge pull request #22376 from A4-Tacks/method-hide-same-name
fix: not complete same name inherent deref methods
2 parents 7a4f9e8 + be99012 commit 4c52c35

3 files changed

Lines changed: 111 additions & 8 deletions

File tree

crates/hir-ty/src/method_resolution/probe.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@
33
44
use std::{cell::RefCell, convert::Infallible, ops::ControlFlow};
55

6+
use base_db::FxIndexMap;
67
use hir_def::{
78
AssocItemId, FunctionId, GenericParamId, ImplId, ItemContainerId, TraitId,
89
hir::generics::GenericParams,
910
signatures::{FunctionSignature, TraitFlags, TraitSignature},
1011
};
1112
use hir_expand::name::Name;
1213
use rustc_ast_ir::Mutability;
13-
use rustc_hash::{FxHashMap, FxHashSet};
14+
use rustc_hash::FxHashSet;
1415
use rustc_type_ir::{
1516
InferTy, TypeVisitableExt, Upcast, Variance,
1617
elaborate::{self, supertrait_def_ids},
@@ -719,7 +720,7 @@ impl<'db> ProbeChoice<'db> for ProbeForNameChoice<'db> {
719720

720721
#[derive(Debug)]
721722
struct ProbeAllChoice<'db> {
722-
candidates: RefCell<FxHashMap<CandidateId, CandidateWithPrivate<'db>>>,
723+
candidates: RefCell<FxIndexMap<CandidateId, CandidateWithPrivate<'db>>>,
723724
considering_visible_candidates: bool,
724725
}
725726

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

Lines changed: 107 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
//! Completes references after dot (fields and method calls).
22
3-
use std::ops::ControlFlow;
3+
use std::{collections::hash_map, ops::ControlFlow};
44

5-
use hir::{Complete, Function, HasContainer, ItemContainer, MethodCandidateCallback};
6-
use ide_db::FxHashSet;
5+
use hir::{Complete, Function, HasContainer, ItemContainer, MethodCandidateCallback, Name};
6+
use ide_db::{FxHashMap, FxHashSet};
77
use itertools::Either;
88
use syntax::SmolStr;
99

@@ -239,6 +239,9 @@ fn complete_methods(
239239
// duplicated, trait methods can. And it is still useful to show all of them (even when there
240240
// is also an inherent method, especially considering that it may be private, and filtered later).
241241
seen_methods: FxHashSet<Function>,
242+
// However, duplicate inherent methods is usually meaningless
243+
// https://github.com/rust-lang/rust-analyzer/issues/20773#issuecomment-4302781553
244+
seen_inherent_methods: FxHashMap<Name, Function>,
242245
}
243246

244247
impl<F> MethodCandidateCallback for Callback<'_, '_, F>
@@ -249,7 +252,21 @@ fn complete_methods(
249252
// `where` clauses or `dyn Trait`.
250253
fn on_inherent_method(&mut self, func: hir::Function) -> ControlFlow<()> {
251254
if func.self_param(self.ctx.db).is_some() && self.seen_methods.insert(func) {
252-
(self.f)(func);
255+
let same_name = self.seen_inherent_methods.entry(func.name(self.ctx.db));
256+
let do_complete = match &same_name {
257+
hash_map::Entry::Vacant(_) => true,
258+
hash_map::Entry::Occupied(same_func) => {
259+
match self.ctx.is_visible(same_func.get()) {
260+
crate::context::Visible::Yes => false,
261+
crate::context::Visible::Editable => true,
262+
crate::context::Visible::No => true,
263+
}
264+
}
265+
};
266+
if do_complete {
267+
same_name.insert_entry(func);
268+
(self.f)(func);
269+
}
253270
}
254271
ControlFlow::Continue(())
255272
}
@@ -277,7 +294,12 @@ fn complete_methods(
277294
&ctx.scope,
278295
traits_in_scope,
279296
None,
280-
Callback { ctx, f, seen_methods: FxHashSet::default() },
297+
Callback {
298+
ctx,
299+
f,
300+
seen_methods: FxHashSet::default(),
301+
seen_inherent_methods: FxHashMap::default(),
302+
},
281303
);
282304
}
283305

@@ -869,6 +891,86 @@ fn test(a: A) {
869891
);
870892
}
871893

894+
#[test]
895+
fn test_inherent_method_no_same_name() {
896+
check_no_kw(
897+
r#"
898+
//- minicore: deref
899+
struct A {}
900+
struct B {}
901+
impl core::ops::Deref for A {
902+
type Target = B;
903+
fn deref(&self) -> &Self::Target { loop {} }
904+
}
905+
trait Foo { fn foo(&self) -> u32 {} }
906+
impl Foo for A {}
907+
impl Foo for B {}
908+
impl A { fn foo(&self) -> u8 {} }
909+
impl B { fn foo(&self) -> u16 {} }
910+
fn test(a: A) {
911+
a.$0
912+
}
913+
"#,
914+
expect![[r#"
915+
me deref() (use core::ops::Deref) fn(&self) -> &<Self as Deref>::Target
916+
me foo() fn(&self) -> u8
917+
me foo() (as Foo) fn(&self) -> u32
918+
"#]],
919+
);
920+
921+
check_no_kw(
922+
r#"
923+
//- minicore: deref
924+
//- /dep.rs crate:dep
925+
pub struct A {}
926+
pub struct B {}
927+
pub struct C {}
928+
pub struct D {}
929+
pub struct E {}
930+
pub struct F {}
931+
impl core::ops::Deref for A {
932+
type Target = B;
933+
fn deref(&self) -> &Self::Target { loop {} }
934+
}
935+
impl core::ops::Deref for B {
936+
type Target = C;
937+
fn deref(&self) -> &Self::Target { loop {} }
938+
}
939+
impl core::ops::Deref for C {
940+
type Target = D;
941+
fn deref(&self) -> &Self::Target { loop {} }
942+
}
943+
impl core::ops::Deref for D {
944+
type Target = E;
945+
fn deref(&self) -> &Self::Target { loop {} }
946+
}
947+
impl core::ops::Deref for E {
948+
type Target = F;
949+
fn deref(&self) -> &Self::Target { loop {} }
950+
}
951+
pub trait Foo { fn foo(&self) -> u32 {} }
952+
impl Foo for A {}
953+
impl Foo for B {}
954+
impl A { fn foo(&self) -> u8 {} }
955+
impl B { pub fn foo(&self) -> u16 {} }
956+
impl C { fn foo(&self) -> i8 {} }
957+
impl D { fn foo(&self) -> i16 {} }
958+
impl E { pub fn foo(&self) -> i32 {} }
959+
impl F { pub fn foo(&self) -> f32 {} }
960+
//- /main.rs crate:main deps:dep
961+
use dep::*;
962+
fn test(a: A) {
963+
a.$0
964+
}
965+
"#,
966+
expect![[r#"
967+
me deref() (use core::ops::Deref) fn(&self) -> &<Self as Deref>::Target
968+
me foo() fn(&self) -> u16
969+
me foo() (as Foo) fn(&self) -> u32
970+
"#]],
971+
);
972+
}
973+
872974
#[test]
873975
fn test_completion_works_in_consts() {
874976
check_no_kw(

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -781,9 +781,9 @@ fn main() {
781781
}
782782
"#,
783783
expect![[r#"
784-
me random_method(…) (use dep::test_mod::TestTrait) fn(&self) DEPRECATED
785784
ct SPECIAL_CONST (use dep::test_mod::TestTrait) u8 DEPRECATED
786785
fn weird_function() (use dep::test_mod::TestTrait) fn() DEPRECATED
786+
me random_method(…) (use dep::test_mod::TestTrait) fn(&self) DEPRECATED
787787
"#]],
788788
);
789789
}

0 commit comments

Comments
 (0)