Unnamed repository; edit this file 'description' to name the repository.
fix: ensure implied bounds from associated types are considered in autocomplete
David Barsky 2024-05-23
parent 870ad35 · commit a0d3a81
-rw-r--r--crates/hir/src/lib.rs3
-rw-r--r--crates/ide-completion/src/tests/flyimport.rs41
-rw-r--r--crates/ide-db/src/imports/import_assets.rs11
3 files changed, 53 insertions, 2 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 0b68762e4f..777be711a5 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -68,7 +68,7 @@ use hir_ty::{
diagnostics::BodyValidationDiagnostic,
error_lifetime, known_const_to_ast,
layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding},
- method_resolution::{self, TyFingerprint},
+ method_resolution::{self},
mir::{interpret_mir, MutBorrowKind},
primitive::UintTy,
traits::FnTrait,
@@ -99,6 +99,7 @@ pub use crate::{
VisibleTraits,
},
};
+pub use hir_ty::method_resolution::TyFingerprint;
// Be careful with these re-exports.
//
diff --git a/crates/ide-completion/src/tests/flyimport.rs b/crates/ide-completion/src/tests/flyimport.rs
index d2227d23cd..abffa73c3b 100644
--- a/crates/ide-completion/src/tests/flyimport.rs
+++ b/crates/ide-completion/src/tests/flyimport.rs
@@ -473,6 +473,47 @@ fn main() {
}
#[test]
+fn trait_completions_handle_associated_types() {
+ let fixture = r#"
+//- /foo.rs crate:foo
+pub trait NotInScope {
+ fn not_in_scope(&self);
+}
+
+pub trait Wrapper {
+ type Inner: NotInScope;
+ fn inner(&self) -> Self::Inner;
+}
+
+//- /main.rs crate:main deps:foo
+use foo::Wrapper;
+
+fn completion<T: Wrapper>(whatever: T) {
+ whatever.inner().$0
+}
+"#;
+
+ check(
+ fixture,
+ expect![[r#"
+ me not_in_scope() (use foo::NotInScope) fn(&self)
+ "#]],
+ );
+
+ check_edit(
+ "not_in_scope",
+ fixture,
+ r#"
+use foo::{NotInScope, Wrapper};
+
+fn completion<T: Wrapper>(whatever: T) {
+ whatever.inner().not_in_scope()$0
+}
+"#,
+ );
+}
+
+#[test]
fn trait_method_fuzzy_completion_aware_of_unit_type() {
let fixture = r#"
//- /test_trait.rs crate:test_trait
diff --git a/crates/ide-db/src/imports/import_assets.rs b/crates/ide-db/src/imports/import_assets.rs
index 6e708182d0..4caecb3f2f 100644
--- a/crates/ide-db/src/imports/import_assets.rs
+++ b/crates/ide-db/src/imports/import_assets.rs
@@ -3,7 +3,7 @@
use hir::{
db::HirDatabase, AsAssocItem, AssocItem, AssocItemContainer, Crate, HasCrate, ImportPathConfig,
ItemInNs, ModPath, Module, ModuleDef, Name, PathResolution, PrefixKind, ScopeDef, Semantics,
- SemanticsScope, Trait, Type,
+ SemanticsScope, Trait, TyFingerprint, Type,
};
use itertools::{EitherOrBoth, Itertools};
use rustc_hash::{FxHashMap, FxHashSet};
@@ -545,6 +545,15 @@ fn trait_applicable_items(
let Some(receiver) = trait_candidate.receiver_ty.fingerprint_for_trait_impl() else {
return false;
};
+
+ // in order to handle implied bounds through an associated type, keep any
+ // method receiver that matches `TyFingerprint::Unnameable`. this receiver
+ // won't be in `TraitImpls` anyways, as `TraitImpls` only contains actual
+ // implementations.
+ if matches!(receiver, TyFingerprint::Unnameable) {
+ return true;
+ }
+
let definitions_exist_in_trait_crate = db
.trait_impls_in_crate(defining_crate_for_trait.into())
.has_impls_for_trait_and_self_ty(candidate_trait_id, receiver);