Skip to content

Commit 5274eb1

Browse files
Merge #8539
8539: fix: Do not propose inherent traits in flyimports and import assists r=flodiebold a=SomeoneToIgnore Closes #8520 I've went with a separate method approach, since the [highlighted code](#8520 (comment)) has not`Type` and uses `Ty` to get his data, but the code I had to change has no access to `Ty` and has `Type` only. Co-authored-by: Kirill Bulatov <[email protected]>
2 parents 47b40b6 + 739edfd commit 5274eb1

File tree

5 files changed

+53
-7
lines changed

5 files changed

+53
-7
lines changed

crates/hir/src/lib.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2066,6 +2066,18 @@ impl Type {
20662066
self.ty.dyn_trait().map(Into::into)
20672067
}
20682068

2069+
/// If a type can be represented as `dyn Trait`, returns all traits accessible via this type,
2070+
/// or an empty iterator otherwise.
2071+
pub fn applicable_inherent_traits<'a>(
2072+
&'a self,
2073+
db: &'a dyn HirDatabase,
2074+
) -> impl Iterator<Item = Trait> + 'a {
2075+
self.autoderef(db)
2076+
.filter_map(|derefed_type| derefed_type.ty.dyn_trait())
2077+
.flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db.upcast(), dyn_trait_id))
2078+
.map(Trait::from)
2079+
}
2080+
20692081
pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<Vec<Trait>> {
20702082
self.ty.impl_trait_bounds(db).map(|it| {
20712083
it.into_iter()

crates/hir_ty/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ pub use mapping::{
5656
to_foreign_def_id, to_placeholder_idx,
5757
};
5858
pub use traits::TraitEnvironment;
59+
pub use utils::all_super_traits;
5960
pub use walk::TypeWalk;
6061

6162
pub use chalk_ir::{

crates/hir_ty/src/utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<Tr
7878

7979
/// Returns an iterator over the whole super trait hierarchy (including the
8080
/// trait itself).
81-
pub(super) fn all_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
81+
pub fn all_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
8282
// we need to take care a bit here to avoid infinite loops in case of cycles
8383
// (i.e. if we have `trait A: B; trait B: A;`)
8484
let mut result = vec![trait_];

crates/ide_completion/src/completions/flyimport.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,4 +1127,27 @@ impl Bar for Foo {
11271127
expect![[r#""#]],
11281128
);
11291129
}
1130+
1131+
#[test]
1132+
fn no_inherent_candidates_proposed() {
1133+
check(
1134+
r#"
1135+
mod baz {
1136+
pub trait DefDatabase {
1137+
fn method1(&self);
1138+
}
1139+
pub trait HirDatabase: DefDatabase {
1140+
fn method2(&self);
1141+
}
1142+
}
1143+
1144+
mod bar {
1145+
fn test(db: &dyn crate::baz::HirDatabase) {
1146+
db.metho$0
1147+
}
1148+
}
1149+
"#,
1150+
expect![[r#""#]],
1151+
);
1152+
}
11301153
}

crates/ide_db/src/helpers/import_assets.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,8 @@ fn trait_applicable_items(
436436
})
437437
.collect();
438438

439+
let related_dyn_traits =
440+
trait_candidate.receiver_ty.applicable_inherent_traits(db).collect::<FxHashSet<_>>();
439441
let mut located_imports = FxHashSet::default();
440442

441443
if trait_assoc_item {
@@ -451,12 +453,16 @@ fn trait_applicable_items(
451453
return None;
452454
}
453455
}
456+
let located_trait = assoc.containing_trait(db)?;
457+
if related_dyn_traits.contains(&located_trait) {
458+
return None;
459+
}
454460

455-
let item = ItemInNs::from(ModuleDef::from(assoc.containing_trait(db)?));
461+
let trait_item = ItemInNs::from(ModuleDef::from(located_trait));
456462
let original_item = assoc_to_item(assoc);
457463
located_imports.insert(LocatedImport::new(
458-
mod_path(item)?,
459-
item,
464+
mod_path(trait_item)?,
465+
trait_item,
460466
original_item,
461467
mod_path(original_item),
462468
));
@@ -473,11 +479,15 @@ fn trait_applicable_items(
473479
|_, function| {
474480
let assoc = function.as_assoc_item(db)?;
475481
if required_assoc_items.contains(&assoc) {
476-
let item = ItemInNs::from(ModuleDef::from(assoc.containing_trait(db)?));
482+
let located_trait = assoc.containing_trait(db)?;
483+
if related_dyn_traits.contains(&located_trait) {
484+
return None;
485+
}
486+
let trait_item = ItemInNs::from(ModuleDef::from(located_trait));
477487
let original_item = assoc_to_item(assoc);
478488
located_imports.insert(LocatedImport::new(
479-
mod_path(item)?,
480-
item,
489+
mod_path(trait_item)?,
490+
trait_item,
481491
original_item,
482492
mod_path(original_item),
483493
));

0 commit comments

Comments
 (0)